我正在尝试将png颜色表应用于图像,但无法匹配从png到目标图像的像素。
颜色表是64 ^ 3的png
根据我对bigt图像中每个像素的理解,需要在颜色表中使用类似的值。这似乎将颜色限制为262144 = 64 x 64 x 64.但我不确定这是我得到的效果,结果是一个完全黑色的图像,这意味着没有价值,或非常奇怪的外观颜色。
这是我的代码
// The table is 64 x 64 x 64
float size = 64.0;
// This is the original image
// This function returns a pixel value inside a 3d space
// and the `rgb` method will return a vector with the rgb values
vec3 source_image = sample(src_i, samplerCoord(src_i)).rgb;
// Here I take the pixel value of the image for the red channel
// and multiply it by 64.0, then divide by 255.0 for the 8-bit image
float x = floor(floor(source_image.r * size)/255.0);
// The same thing for the green value on the y axis
float y = floor(floor(source_image.g * size)/255.0);
// Match a value from the image in the color table
vec3 color = sample(src_l, vec2(x, y)).rgb;
src_i.r = color.r;
src_i.g = color.g;
// The blue should be on the z axis, or the nth tile, so I think for this
// case it will be easier to convert the color table to one long row
src_i.b = floor(floor(source_image.b * size)/255.0);
// The image is black
原始图像
预期结果
如果我乘以255(这似乎是正确的),那么我得到这个结果
float x = floor(source_image.r * 255.0);
float y = floor(source_image.g * 255.0);
如果你能指出数学有什么问题,我真的很感激
查找表不是64 * 64 * 64,而是8 * 8栅格中的64 * 64。由texture2D
读取的颜色通道在[0,1]范围内,纹理坐标也在[0,1]范围内。
vec2 tiles = vec2(8.0);
vec2 tileSize = vec2(64.0);
vec3 imageColor = texture(src_i, samplerCoord(src_i)).rgb;
图块的索引被编码为蓝色通道。有64个图块,第一个图块的索引为0,最后一个图块的索引为63.这意味着[0,1]范围内的蓝色通道必须映射到范围[0,63]:
float index = imageColor.b * (tiles.x * tiles.y - 1.0);
形成该线性瓦片索引,必须计算2维瓦片索引在[0,8]范围内:
vec2 tileIndex;
tileIndex.y = floor(index / tiles.x);
tileIndex.x = floor(index - tileIndex.y * tiles.x);
纹理缩小功能(GL_TEXTURE_MIN_FILTER
)和纹理放大功能(GL_TEXTURE_MAG_FILTER
应设置为GL_LINEAR
。这会导致每个图块上的颜色可以进行线性插值。
每个图块都有64x64纹素。左下纹素的相对坐标是(0.5 / 64.0,0.5 / 64.0),右上纹素的相对坐标是(63.5 / 64.0,63.5 / 64.0)。
范围[0,1]中的红色和绿色通道必须映射到[0.5 / 64.0,63.5 / 64.0]范围:
vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);
最后,计算范围[0,1] c中颜色查找表的纹理坐标:
vec2 tableUV = tileIndex / tiles + tileUV / tiles;
解码片段着色器中颜色的最终代码可能如下所示:
vec2 tiles = vec2(8.0, 8.0);
vec2 tileSize = vec2(64.0);
vec4 imageColor = texture(src_i, samplerCoord(src_i));
float index = imageColor.b * (tiles.x * tiles.y - 1.0);
vec2 tileIndex;
tileIndex.y = floor(index / tiles.x);
tileIndex.x = floor(index - tileIndex.y * tiles.x);
vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);
vec2 tableUV = tileIndex / tiles + tileUV / tiles;
vec3 lookUpColor = texture(src_l, tableUV).rgb;
通过在表的2个瓦片之间进行插值,可以进一步改进该算法。计算蓝色通道下面的图块索引和蓝色通道上方图块的索引:
float index = imageColor.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;
最后使用mix
函数在两个图块的颜色之间进行插值:
vec3 lookUpColor_1 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor_2 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor = mix(lookUpColor_1, lookUpColor_2, index-index_min);
最终代码:
vec2 tiles = vec2(8.0, 8.0);
vec2 tileSize = vec2(64.0);
vec4 imageColor = texture(src_i, samplerCoord(src_i));
float index = imageColor.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;
vec2 tileIndex_min;
tileIndex_min.y = floor(index_min / tiles.x);
tileIndex_min.x = floor(index_min - tileIndex_min.y * tiles.x);
vec2 tileIndex_max;
tileIndex_max.y = floor(index_max / tiles.x);
tileIndex_max.x = floor(index_max - tileIndex_max.y * tiles.x);
vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);
vec2 tableUV_1 = tileIndex_min / tiles + tileUV / tiles;
vec2 tableUV_2 = tileIndex_max / tiles + tileUV / tiles;
vec3 lookUpColor_1 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor_2 = texture(src_l, tableUV_2).rgb;
vec3 lookUpColor = mix(lookUpColor_1, lookUpColor_2, index-index_min);
查看比较原始图像(左上角)和颜色查找修改图像(右下角)的图像:
在颜色表中找到相应位置的计算似乎是关闭的。我认为你必须首先在正确的“红绿色平面”(由输入的蓝色通道确定,考虑到由于地图中8x8布局引起的8步幅)中找到偏移量,然后才能找到将此偏移量添加到x
和y
值的计算中。
但是,我建议你先检查一下内置的CIColorCube
filter,因为它确实是你想要实现的。