如何在JavaScript中使用LUT?
我是图像处理新手 我想使用JavaScript使用LUT(查找表)或相应的查找PNG将效果应用于图像,如下所示: 我在谷歌上搜索了很多,没有找到一篇文章或任何资源来描述使用LUT进行像素转换的确切过程 我发现了一篇很好的文章,它描述了1D和3D LUT以及它们之间的差异。但我还是不太清楚 我想要像这样的东西,这是为iOS做的 另外,请不要发布有关图像过滤LIB的链接/答案,这些LIB使用卷积矩阵进行效果或过滤器 更新:如何在JavaScript中使用LUT?,javascript,image-processing,lookup-tables,Javascript,Image Processing,Lookup Tables,我是图像处理新手 我想使用JavaScript使用LUT(查找表)或相应的查找PNG将效果应用于图像,如下所示: 我在谷歌上搜索了很多,没有找到一篇文章或任何资源来描述使用LUT进行像素转换的确切过程 我发现了一篇很好的文章,它描述了1D和3D LUT以及它们之间的差异。但我还是不太清楚 我想要像这样的东西,这是为iOS做的 另外,请不要发布有关图像过滤LIB的链接/答案,这些LIB使用卷积矩阵进行效果或过滤器 更新: 终于!多亏了@abbath,我才得到了答案。我在GitHub中创建了一个要
终于!多亏了@abbath,我才得到了答案。我在GitHub中创建了一个要点,您可以找到。我对这个主题也不熟悉,但我希望它能帮助我目前所发现的内容。您的图像(LUT)是一个3D阵列的表示,请想象一个64x64x64立方体。此表示是二维的,一个平面是64x64正方形。你需要64块这个平面,这就是为什么png中有8x8个正方形。 如果仔细观察,左上角的正方形在X轴上有红色(R表示RGB),在Y轴上有绿色(G)。蓝色(B)是Z轴(我想象它向上),它不能在2D中表示,所以它出现在接下来的64x64正方形上。在最后一个(右下角)正方形上,您可以看到它大部分是蓝色的,其中红色和绿色坐标为0 所以下一个问题是如何用这个LUT投影图像。我已经在Java中试用过,我认为您将不得不丢失一些信息,因为64x64x64远小于256x256x256,在这种情况下,每个像素颜色值必须除以4 步骤如下:
public位图applyEffectToBitmap(位图src、位图lutbramp){
//android特定代码,将LUT图像的像素存储在int数组中
int lutWidth=lutBitmap.getWidth();
int-lutColors[]=new-int[lutWidth*lutBitmap.getHeight();
getPixels(lutColor,0,lutWidth,0,0,lutWidth,lutBitmap.getHeight());
//android特定代码,将源图像的像素存储在int数组中
int srcWidth=src.getWidth();
int srchheight=src.getHeight();
int[]pix=新int[srcWidth*srcHeight];
getPixels(像素,0,srcWidth,0,0,srcWidth,srcHeight);
int R,G,B;
//现在我们可以遍历源图像的像素
对于(int y=0;y>16)和0xff)/4;
intg=((pix[index]>>8)和0xff)/4;
intb=(pix[索引]&0xff)/4;
//神奇之处就在这里:上面的第三步:蓝色像素描述了
//您需要从哪个正方形的列和行获取像素
//然后简单地加上r和green值得到坐标
int lutX=(b%8)*64+r;
int-lutY=(b/8)*64+g;
int-lutIndex=lutY*lutWidth+lutX;
//与上面得到的像素相同,但现在来自LutColor int数组
R=((lutColors[lutIndex]>>16)和0xff);
G=((lutColors[lutIndex]>>8)和0xff);
B=((lutColors[lutIndex])&0xff);
//用过滤后的值覆盖pix数组,在我的例子中alpha是256,但您可以使用原始alpha
pix[索引]=0xff000000|(r> p>我尝试在C++中做类似的事情。3D LUT通常有3列值,通常在0到1之间。列分别是R G B,它们代表值的映射。如果打开这些大小为nxnxn的文件中的一个,则将每个值读入相应的R数组或G数组或B数组。然后在内部重新创建映射,您将迭代并使用双/浮点键和值填充rgb贴图
for every b
for every g
for every r
// r g and b are indices
index = b * n^2 + g * n + r
Rmap.push((r + 1)/n, Rarray[index])
// Same for g and b
Gmap.push((g + 1)/n, Garray[index]
Bmap.push((b + 1)/n, Barray[index]
一旦有了映射,就可以对图像中的每个像素应用查找。假设图像的最大颜色为255,则取(r,g,b)/每个像素的255,然后应用查找,然后转换回*255。据我所知,计算无法查找的值的惯例是执行三线性插值。我还没有太多成功,但这是我的两美分。谢谢你的回答。我有一些问题:你说的获取相应的值是什么意思LUT中的像素
?如果我的图像大于LUT怎么办?如何检查B值
?以及在执行步骤后,如何使用结果更改图像的当前像素(63,0)
?您的图像可以有任何大小,您必须遍历图像的每一个像素。因此,如果您有全高清图像,您必须遍历1080*1920像素。在一次迭代中,您将有一个像素值。获取该像素的r、g和b值。它们将小于256,但需要小于64,因此将所有三个值除以4.现在一个像素有三个值,每个值在64以下。然后是y
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;
}
for every b
for every g
for every r
// r g and b are indices
index = b * n^2 + g * n + r
Rmap.push((r + 1)/n, Rarray[index])
// Same for g and b
Gmap.push((g + 1)/n, Garray[index]
Bmap.push((b + 1)/n, Barray[index]