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 kind element on one of many pages.
I ended up utilizing gl-react
and gl-react-expo
to use some filters to the pictures after which use captureRef
to avoid wasting the edited images. The issue is available in once I need to use LUTs – this was (or a minimum of appeared like) the most suitable choice to simply switch any picture 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 to be 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 undecided why this is able to be taking place, when the LUT photographs 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 consumer chooses filters, like this:
export const FILTERS = {
regular: {
key: 'regular',
kind: 'lut',
title: 'Regular',
displayName: ,
shader: lutShader,
uniforms: {
lut: require('../belongings/luts/impartial.png'),
t: { uri: '' },
depth: 1,
},
},
'blackwhite-fade': {
key: 'blackwhite-fade',
kind: 'lut',
title: 'B&W Fade',
displayName: (
),
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, go within the t
prop of the uniforms for the picture being edited:
{*/ Shortened for simply the half the place I present the picture /*}
{selectedFilterObj && (
)}
The ImageFilter is only a Node
from gl-react
:
const ImageFilter = ({ uniforms, shader }: ImageFilterProps) => {
return (
);
};
I will embrace the shader as effectively, 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 major() {
vec4 colour = texture2D(t, uv);
vec4 lutColor = applyLUT(colour);
gl_FragColor = combine(colour, lutColor, depth);
}
`,
};
export default lutShader;
Pattern LUT – Notice needed to compress into JPEG to publish right here
I attempted to alter the strategy to make use of Skia, nevertheless it wasn’t working effectively 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.