android – require(*picture*) in React Native appears to extend RAM utilization drastically

android – require(*picture*) in React Native appears to extend RAM utilization drastically


Some particulars on the setup – I am utilizing React Native with Expo (SDK 51) and I am constructing an app that has a picture filter/editor sort element on one of many pages.

I ended up utilizing gl-react and gl-react-expo to use some filters to the photographs after which use captureRef to avoid wasting the edited photographs. The issue is available in once I need to use LUTs – this was (or at the least appeared like) the best choice to simply switch any photograph edits I’ve made right into a filter. I opted to make use of sq. LUT png textures, began with smaller ones nevertheless it launched banding, so I went for 4096x4096 textures, and it seems fantastic.

Firstly, it takes ages to load every one of many filters (I nonetheless have not tried out the app exterior of Metro in a standalone construct), and when the filter does load, it takes up an extra 150-250MB of RAM for every filter loaded within the efficiency inspector. I am genuinely unsure why this is able to be occurring, when the LUT photos are 10-12MB at most. When clicking by way of all the filters the RAM utilization simply goes up, going from 300MB to 3-4GB! This goes again to regular when leaving the web page.

The biggest of the filter textures is not more than 11-12 MB, and I’ve all of them in a map able to map over within the listing the place the person chooses filters, like this:

export const FILTERS = {
  regular: {
    key: 'regular',
    sort: 'lut',
    title: 'Regular',
    displayName: <LUTPreview color1="#FFFFFF" color2="#FFFFFF" title="Regular" />,
    shader: lutShader,
    uniforms: {
      lut: require('../belongings/luts/impartial.png'),
      t: { uri: '' },
      depth: 1,
    },
  },
  'blackwhite-fade': {
    key: 'blackwhite-fade',
    sort: 'lut',
    title: 'B&W Fade',
    displayName: (
      <LUTPreview color1="#FFFFFF" color2="#222222" title="B&W Fade" />
    ),
    shader: lutShader,
    uniforms: {
      lut: require('../belongings/luts/blackwhite-fade.png'),
      t: { uri: '' },
      depth: 1,
    },
  },
... remainder of the filters

Then within the ImageEditor element I load up the filter and shader, cross within the t prop of the uniforms for the picture being edited:

{*/ Shortened for simply the half the place I present the picture /*}
          <Floor
            model={{
              width: imageDimensions.width,
              peak: imageDimensions.peak,
            }}
          >
            {selectedFilterObj && (
              <ImageFilter
                key={selectedFilterObj.key}
                shader={selectedFilterObj.shader}
                uniforms={{
                  ...selectedFilterObj.uniforms,
                  depth: filterIntensity,
                }}
              />
            )}
          </Floor>

The ImageFilter is only a Node from gl-react:

const ImageFilter = ({ uniforms, shader }: ImageFilterProps<UniformsType>) => {
  return (
    <Node
      shader={shader}
      uniforms={{
        ...uniforms,
      }}
    />
  );
};

I will embrace the shader as properly, together with a pattern LUT picture:

Shader

import { GLSL } from 'gl-react';

const lutShader = {
  frag: GLSL`
    precision mediump float; 
    various vec2 uv;
    uniform sampler2D t;    
    uniform sampler2D lut;  
    uniform float depth;

    vec4 applyLUT(vec4 src_color) {
      const vec2 tiles = vec2(16.0); 
      const float tileSize = 256.0;  
      
      float b = clamp(src_color.b * 255.0, 0.0, 255.0);
      float b_i = ground(b);
      
      // Calculate tile indices extra effectively
      vec2 tileIndex;
      tileIndex.y = ground(b_i * 0.0625);  // Precalculated 1/16
      tileIndex.x = mod(b_i, 16.0);
      
      // Simplified UV calculation
      vec2 pixelPos = src_color.rg * (tileSize - 1.0) + 0.5;
      vec2 uv1 = (tileIndex * tileSize + pixelPos) * 0.000244140625;  // Precalculated 1/4096

      vec3 lutColor = texture2D(lut, uv1).rgb;
      return vec4(lutColor, 1.0);
    }

    void essential() {
      vec4 shade = texture2D(t, uv);
      vec4 lutColor = applyLUT(shade);
      gl_FragColor = combine(shade, lutColor, depth);
    }
  `,
};

export default lutShader;

Pattern LUT – Notice needed to compress into JPEG to submit right here

Example LUT

I attempted to vary the tactic to make use of Skia, nevertheless it wasn’t working properly and it wasn’t even a lot quicker. I consider I additionally tried preloading the belongings with expo-asset which simply stored the app loading for a very long time, and did not assist in any respect.

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 
rooshohttps://www.roosho.com
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here


Latest Articles

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog.