试图解压缩 BC1 纹理压缩的加扰块
scrambled block trying to decompress BC1 texture compression
我一直在尝试在 Java 中实现 BC1 (DXT1) 解压缩算法。一切似乎都非常精确,但我 运行 遇到了一些围绕 t运行sparent 块的问题。我一直试图解决它几个小时但没有成功。
简而言之,解压所有块后,除了 t运行sparent 周围的块外,一切看起来都很好。在开发过程中,我一直在检查用 C++ 编写的 DirectXTex (texconv) 的结果。
这是我与 DirectXTex 对比的结果:
这是我使用的代码:
BufferedImage decompress(byte[] buffer, int width, int height)
和实施:
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int[] scanline = new int[4 * width]; //stores 4 horizontal lines (width/4 blocks)
RGBA[] blockPalette = new RGBA[4]; //stores RGBA values of current block
int bufferOffset = 0;
for (int row = 0; row < height / 4; row++) {
for (int col = 0; col < width / 4; col++) {
short rgb0 = Short.reverseBytes(Bytes.getShort(buffer, bufferOffset));
short rgb1 = Short.reverseBytes(Bytes.getShort(buffer, bufferOffset + 2));
int bitmap = Integer.reverseBytes(Bytes.getInt(buffer, bufferOffset + 4));
bufferOffset += 8;
blockPalette[0] = R5G6B5.decode(rgb0);
blockPalette[1] = R5G6B5.decode(rgb1);
if(rgb0 <= rgb1) {
int c2r = (blockPalette[0].getRed() + blockPalette[1].getRed()) / 2;
int c2g = (blockPalette[0].getGreen() + blockPalette[1].getGreen()) / 2;
int c2b = (blockPalette[0].getBlue() + blockPalette[1].getBlue()) / 2;
blockPalette[2] = new RGBA(c2r, c2g, c2b, 255);
blockPalette[3] = new RGBA(0, 0, 0, 0);
} else {
int c2r = (2 * blockPalette[0].getRed() + blockPalette[1].getRed()) / 3;
int c2g = (2 * blockPalette[0].getGreen() + blockPalette[1].getGreen()) / 3;
int c2b = (2 * blockPalette[0].getBlue() + blockPalette[1].getBlue()) / 3;
int c3r = (blockPalette[0].getRed() + 2 * blockPalette[1].getRed()) / 3;
int c3g = (blockPalette[0].getGreen() + 2 * blockPalette[1].getGreen()) / 3;
int c3b = (blockPalette[0].getBlue() + 2 * blockPalette[1].getBlue()) / 3;
blockPalette[2] = new RGBA(c2r, c2g, c2b, 255);
blockPalette[3] = new RGBA(c3r, c3g, c3b, 255);
}
for (int i = 0; i < 16; i++, bitmap >>= 2) {
int pi = (i / 4) * width + (col * 4 + i % 4);
int index = bitmap & 3;
scanline[pi] = A8R8G8B8.encode(blockPalette[index]);
}
}
//copy scanline to buffered image
result.setRGB(0, row * 4, width, 4, scanline, 0, width);
}
return result;
有谁知道问题出在哪里?我一直在按照规格说明执行完全相同的步骤:Block Compression (Direct3D 10)
难道blockPalette[2].set(c2r, c2g, c2b);
应该是blockPalette[2].set(c2r, c2g, c2b, 255);
? (在两个位置)
对于那些感兴趣的人,我发现问题在于比较短值。
我刚刚改变了:
if(rgb0 <= rgb1) {
要么
if(Short.compareUnsigned(rgb0, rgb1) <= 0) {
或
if((rgb0 & 0xffff) <= (rgb1 & 0xffff)) {
这确保颜色值作为无符号短裤(正整数)进行比较。
我一直在尝试在 Java 中实现 BC1 (DXT1) 解压缩算法。一切似乎都非常精确,但我 运行 遇到了一些围绕 t运行sparent 块的问题。我一直试图解决它几个小时但没有成功。
简而言之,解压所有块后,除了 t运行sparent 周围的块外,一切看起来都很好。在开发过程中,我一直在检查用 C++ 编写的 DirectXTex (texconv) 的结果。
这是我与 DirectXTex 对比的结果:
这是我使用的代码:
BufferedImage decompress(byte[] buffer, int width, int height)
和实施:
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int[] scanline = new int[4 * width]; //stores 4 horizontal lines (width/4 blocks)
RGBA[] blockPalette = new RGBA[4]; //stores RGBA values of current block
int bufferOffset = 0;
for (int row = 0; row < height / 4; row++) {
for (int col = 0; col < width / 4; col++) {
short rgb0 = Short.reverseBytes(Bytes.getShort(buffer, bufferOffset));
short rgb1 = Short.reverseBytes(Bytes.getShort(buffer, bufferOffset + 2));
int bitmap = Integer.reverseBytes(Bytes.getInt(buffer, bufferOffset + 4));
bufferOffset += 8;
blockPalette[0] = R5G6B5.decode(rgb0);
blockPalette[1] = R5G6B5.decode(rgb1);
if(rgb0 <= rgb1) {
int c2r = (blockPalette[0].getRed() + blockPalette[1].getRed()) / 2;
int c2g = (blockPalette[0].getGreen() + blockPalette[1].getGreen()) / 2;
int c2b = (blockPalette[0].getBlue() + blockPalette[1].getBlue()) / 2;
blockPalette[2] = new RGBA(c2r, c2g, c2b, 255);
blockPalette[3] = new RGBA(0, 0, 0, 0);
} else {
int c2r = (2 * blockPalette[0].getRed() + blockPalette[1].getRed()) / 3;
int c2g = (2 * blockPalette[0].getGreen() + blockPalette[1].getGreen()) / 3;
int c2b = (2 * blockPalette[0].getBlue() + blockPalette[1].getBlue()) / 3;
int c3r = (blockPalette[0].getRed() + 2 * blockPalette[1].getRed()) / 3;
int c3g = (blockPalette[0].getGreen() + 2 * blockPalette[1].getGreen()) / 3;
int c3b = (blockPalette[0].getBlue() + 2 * blockPalette[1].getBlue()) / 3;
blockPalette[2] = new RGBA(c2r, c2g, c2b, 255);
blockPalette[3] = new RGBA(c3r, c3g, c3b, 255);
}
for (int i = 0; i < 16; i++, bitmap >>= 2) {
int pi = (i / 4) * width + (col * 4 + i % 4);
int index = bitmap & 3;
scanline[pi] = A8R8G8B8.encode(blockPalette[index]);
}
}
//copy scanline to buffered image
result.setRGB(0, row * 4, width, 4, scanline, 0, width);
}
return result;
有谁知道问题出在哪里?我一直在按照规格说明执行完全相同的步骤:Block Compression (Direct3D 10)
难道blockPalette[2].set(c2r, c2g, c2b);
应该是blockPalette[2].set(c2r, c2g, c2b, 255);
? (在两个位置)
对于那些感兴趣的人,我发现问题在于比较短值。
我刚刚改变了:
if(rgb0 <= rgb1) {
要么
if(Short.compareUnsigned(rgb0, rgb1) <= 0) {
或
if((rgb0 & 0xffff) <= (rgb1 & 0xffff)) {
这确保颜色值作为无符号短裤(正整数)进行比较。