如何在JavaScript中使用LUT? [英] How to use LUT with JavaScript?

查看:176
本文介绍了如何在JavaScript中使用LUT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是图像处理的新手。

我想使用JavaScript将效果应用于使用LUT(LookUp Tables)或相应的查找PNG的图像,类似于这个:

I want to use JavaScript to apply effects to images using LUTs (LookUp Tables) or the corresponding lookup PNGs, something like this:

我搜索了很多内容,找不到文章或任何资源来描述使用LUT进行像素转换的确切过程。

I have googled a lot and couldn't find an article or any resource which will describe the exact process of pixel transformation using LUTs.

我找到了一篇很好的文章这里,它描述了1D和3D LUT以及它们之间的差异。但它对我来说仍然不完全清楚。

I have found a nice article here, which describes the 1D and 3D LUTs and the differences between them. But its still is not fully clear for me.

我想要像这个,适用于iOS。

I want something like this, which is done for iOS.

PS请不要发布有关图像过滤库的链接/答案,这些库使用卷积矩阵作为效果或过滤器。

P.S. Please do not post links/answers regarding image filtering libs, which are using convolution matrices for effects or for filters.

更新:

终于!感谢@abbath,我得到了答案。我在GitHub中创建了一个要点,你可以在这里找到这里

Finally! I have got the answer thanks to @abbath. I've created a gist in GitHub, which you can find here.

推荐答案

我也是这个话题的新手,但我希望它对我迄今为止发现的内容有所帮助。您的图像(LUT)是3D阵列的表示,想象一下64x64x64立方体。该表示是2D,一个平面是64x64平方。你需要64个这个平面,这就是png中有8x8个方块的原因。
如果仔细观察,左上方在X轴上为红色(RGB为R),在Y轴上为绿色(G)。蓝色(B)是Z轴(我想象它向上),它不能用2D表示,所以它出现在接下来的64x64方格中。在最后(右下)的方块上,您可以看到它主要是蓝色,红色和绿色坐标为0。

I am also new to the topic, but I hope it helps what I've found out so far. Your image (the LUT) is a representation of a 3D array, imagine a 64x64x64 cube. This representation is in 2D, one plane is a 64x64 square. You need 64 piece of this plane, which is why the png has 8x8 squares in it. If you look carefully, the upperleft square has red (R of RGB) on the X axis and green (G) on the Y axis. The blue (B) is the Z axis (I imagine it upwards), which can't be representated in 2D, so it comes on the next 64x64 squares. On the last (lower right) square you can see that it is mostly blue, where the red and green coordinates are 0.

所以下一个问题是如何投影这个LUT的图像。我已经在Java中试过了,在我看来你将不得不丢失一些信息,因为64x64x64远小于256x256x256,在这种情况下,你必须将每个像素颜色值除以4。

So the next question is how to project an image with this LUT. I have tried it out in Java, in my opinion you will have to lose some information because 64x64x64 is far less than 256x256x256, in this case, you have to divide by 4 each pixel color value.

步骤:


  1. 迭代原始图像的像素。在一次迭代中,您将拥有原始图像的一个像素。获取该像素的R,G,B值。

  2. 将值除以4,因此您的值将小于64.

  3. 从LUT获取相应的像素,就好像它是一个64x64x64的立方体。因此,如果RGB =(255,0,255)在原始像素上,则将其除以得到(63,0,63),然后检查B值,以获得png上相应的方格,这将是右下方的方格(在b = 63的情况下),得到它的r,g =(63,0)像素,在你的png图像上是紫色的。

我现在在Android上检查了java代码,在我看来它足够快。下面是我写的代码,我希望它足以将它移植到javascript。 (我希望这些评论足以理解)

I checked now on android, with java code, its fast enough in my opinion. Below is the code I've written, I hope it's enough to port it to javascript. (I hope the comments are enough to understand)

public Bitmap applyEffectToBitmap(Bitmap src, Bitmap lutbitmap) {
    //android specific code, storing the LUT image's pixels in an int array
    int lutWidth = lutBitmap.getWidth();
    int lutColors[] = new int[lutWidth * lutBitmap.getHeight()];
    lutBitmap.getPixels(lutColors, 0, lutWidth, 0, 0, lutWidth, lutBitmap.getHeight());

    //android specific code, storing the source image's pixels in an int array
    int srcWidth = src.getWidth();
    int srcHeight = src.getHeight();
    int[] pix = new int[srcWidth * srcHeight];

    src.getPixels(pix, 0, srcWidth, 0, 0, srcWidth, srcHeight);

    int R, G, B;
    //now we can iterate through the pixels of the source image
    for (int y = 0; y < srcHeight; y++){
        for (int x = 0; x < srcWidth; x++) {
            //index: because the pix[] is one dimensional
            int index = y * srcWidth+ x;
            //pix[index] returns a color, we need it's r g b values, thats why the shift operator is used
            int r = ((pix[index] >> 16) & 0xff) / 4;
            int g = ((pix[index] >> 8) & 0xff) / 4;
            int b = (pix[index] & 0xff) / 4;

            //the magic happens here: the 3rd step above: blue pixel describes the 
            //column and row of which square you'll need the pixel from
            //then simply add the r and green value to get the coordinates 
            int lutX = (b % 8) * 64 + r;
            int lutY = (b / 8) * 64 + g;
            int lutIndex = lutY * lutWidth + lutX;


            //same pixel getting as above, but now from the lutColors int array
            R = ((lutColors[lutIndex] >> 16) & 0xff);
            G = ((lutColors[lutIndex] >> 8) & 0xff);
            B = ((lutColors[lutIndex]) & 0xff);


            //overwrite pix array with the filtered values, alpha is 256 in my case, but you can use the original alpha
            pix[index] = 0xff000000 | (R << 16) | (G << 8) | B;
        }
    }
    //at the end of operations pix[] has the transformed pixels sou can set them to your new bitmap
    //some android specific code is here for creating bitmaps
    Bitmap result = Bitmap.createBitmap(srcWidth, srcHeight, src.getConfig());
    result.setPixels(pix, 0, srcWidth, 0, 0, srcWidth, srcHeight);
    return result ;
}

现在我已经成功实现了javascript,请检查是否使用了数学。 floor()函数:

Now I've successfully implemented in javascript too, check for using the Math.floor() functions:

for (var i=0;i<imgData.data.length;i+=4){
    var r=Math.floor(imgData.data[i]/4);
    var g=Math.floor(imgData.data[i+1]/4);
    var b=Math.floor(imgData.data[i+2]/4);    
    var a=255;


    var lutX = (b % 8) * 64 + r;
    var lutY = Math.floor(b / 8) * 64 + g;
    var lutIndex = (lutY * lutWidth + lutX)*4;

    var Rr =  filterData.data[lutIndex];
    var Gg =  filterData.data[lutIndex+1];    
    var Bb =  filterData.data[lutIndex+2];

    imgData.data[i] = Rr;
    imgData.data[i+1] = Gg;
    imgData.data[i+2] = Bb;
    imgData.data[i+3] = 255;

}

点击此处:http://jsfiddle.net/gxu080ve/1/ lut图像是字节代码,很抱歉。

Check it here: http://jsfiddle.net/gxu080ve/1/ The lut image is in byte code, sorry for that.

此代码仅适用于64x64x64 3DLUT图像。如果您的LUT具有其他尺寸,则参数会有所不同; / 4 * 64 %8 / 8 必须针对其他维度进行更改,但在此问题的范围内,LUT为64x64x64。

This code only applies for 64x64x64 3DLUT images. The parameters vary if your LUT has other dimensions; the / 4, * 64, % 8, / 8 must be changed for other dimensions, but in this question's scope the LUT is 64x64x64.

这篇关于如何在JavaScript中使用LUT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆