dntks / easyLUT

Android library for applying color look-up table (CLUT) image transformations on bitmaps and imageviews
Apache License 2.0
70 stars 15 forks source link

Hald CLUT to shader #6

Closed Zer0bee closed 6 years ago

Zer0bee commented 6 years ago

Hi, i want to apply hald clut on a video. But this lib is limited to images only. So, i want to write Hald 64x64x64 LUT into opengl shader but i am stuck in logic behind it. Can you please explain, how to read data from halt clut.

Zer0bee commented 6 years ago

@dntks any update??

dntks commented 6 years ago

@Zer0bee First of all; using a Color LUT means you will most probably use less color depth than the original image/video. If you check the LUTImage.java in the code it has the rgbDistortion property, that stores how much less colors you will have correlated to the 8 bit (256 256 256) color depth. If you have a 4096x4096 LUT image you won't have the distortion (as 4096 4096 = 256 256 * 256).

There is the identity LUT which has all the colors in the correct order: if you check the RGB(256,0,0) = pure red color, when you get this on the identity LUT, you will get the same red color (but distorted in depth). First step using a LUT is to check the original color's coordinate on the Identity LUT. Identity LUT-s differ by the type of the LUT, which can be square LUT or Hald LUT. In the EasyLUT library this is called LutAlignment.

Identity LUTs can also vary in how they use the 3 color coordinates, the x y and z axes represent a color each, so X can be the red, Z the blue, Y the green, or any other combination. That's why it's important to define this before using the LUT, you need to define how the identity LUT looks like. This is handled by CoordinateToColor.java class and the CoordinateToColor.Type, and the DistortedColor class's methods get the coordinates of the given color on the identity LUT.

LUT images can differ in their size as well, they can have 256x16, 64x64 or any variation of pixel dimension that's why the rowdepth is important, it stores how the 3d cube is represented in the 2d LUT image (how many 2d layers are in one row).

Then comes the LutAlignment, which returns the 2d coordinate representing the color in the Identity LUT. The library gives the rowDepth and the 3d coordinates to the Alignement, which returns the 2d coordinates of the color of the identity LUT. For Hald this looks like:

class Hald implements LutAlignment {
        @Override
        public int getX(int rowDepth, int sideSize, int x, int y, int z) {
            int red = x;
            int green = y % rowDepth * sideSize;
            return red + green;
        }
        @Override
        public int getY(int rowDepth, int sideSize, int x, int y, int z) {
            int green = y / rowDepth;
            int blue = z * rowDepth;
            return green + blue;
        }
}

Then you have the 2d coordinates for the color, then you just need to get the same coordinate on you distorted LUT image.

Zer0bee commented 6 years ago

@dntks Thanks for the explanation. It really helps. 👍

abi98213 commented 4 years ago

@Zer0bee any update on GLSL shader ?