internal static void DxtcReadColor(ushort data, ref Colour8888 op) { byte r, g, b; b = (byte)(data & 0x1f); g = (byte)((data & 0x7E0) >> 5); r = (byte)((data & 0xF800) >> 11); op.red = (byte)(r << 3 | r >> 2); op.green = (byte)(g << 2 | g >> 3); op.blue = (byte)(b << 3 | r >> 2); }
private static unsafe byte[] DecompressRXGB(DDSStruct header, byte[] data, PixelFormat pixelFormat) { // allocate bitmap int bpp = (int)(Helper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount)); int bps = (int)(header.width * bpp * Helper.PixelFormatToBpc(pixelFormat)); int sizeofplane = (int)(bps * header.height); int width = (int)header.width; int height = (int)header.height; int depth = (int)header.depth; byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp]; Colour565 color_0 = new Colour565(); Colour565 color_1 = new Colour565(); Colour8888[] colours = new Colour8888[4]; byte[] alphas = new byte[8]; fixed(byte *bytePtr = data) { byte *temp = bytePtr; for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { if (y >= height || x >= width) { break; } alphas[0] = temp[0]; alphas[1] = temp[1]; byte *alphamask = temp + 2; temp += 8; Helper.DxtcReadColors(temp, ref color_0, ref color_1); temp += 4; uint bitmask = ((uint *)temp)[1]; temp += 4; colours[0].red = (byte)(color_0.red << 3); colours[0].green = (byte)(color_0.green << 2); colours[0].blue = (byte)(color_0.blue << 3); colours[0].alpha = 0xFF; colours[1].red = (byte)(color_1.red << 3); colours[1].green = (byte)(color_1.green << 2); colours[1].blue = (byte)(color_1.blue << 3); colours[1].alpha = 0xFF; // Four-color block: derive the other two colors. // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 // These 2-bit codes correspond to the 2-bit fields // stored in the 64-bit block. colours[2].blue = (byte)((2 * colours[0].blue + colours[1].blue + 1) / 3); colours[2].green = (byte)((2 * colours[0].green + colours[1].green + 1) / 3); colours[2].red = (byte)((2 * colours[0].red + colours[1].red + 1) / 3); colours[2].alpha = 0xFF; colours[3].blue = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3); colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3); colours[3].red = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3); colours[3].alpha = 0xFF; int k = 0; for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++, k++) { int select = (int)((bitmask & (0x03 << k * 2)) >> k * 2); Colour8888 col = colours[select]; // only put pixels out < width or height if (((x + i) < width) && ((y + j) < height)) { uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp); rawData[offset + 0] = col.red; rawData[offset + 1] = col.green; rawData[offset + 2] = col.blue; } } } // 8-alpha or 6-alpha block? if (alphas[0] > alphas[1]) { // 8-alpha block: derive the other six alphas. // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. alphas[2] = (byte)((6 * alphas[0] + 1 * alphas[1] + 3) / 7); // bit code 010 alphas[3] = (byte)((5 * alphas[0] + 2 * alphas[1] + 3) / 7); // bit code 011 alphas[4] = (byte)((4 * alphas[0] + 3 * alphas[1] + 3) / 7); // bit code 100 alphas[5] = (byte)((3 * alphas[0] + 4 * alphas[1] + 3) / 7); // bit code 101 alphas[6] = (byte)((2 * alphas[0] + 5 * alphas[1] + 3) / 7); // bit code 110 alphas[7] = (byte)((1 * alphas[0] + 6 * alphas[1] + 3) / 7); // bit code 111 } else { // 6-alpha block. // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. alphas[2] = (byte)((4 * alphas[0] + 1 * alphas[1] + 2) / 5); // Bit code 010 alphas[3] = (byte)((3 * alphas[0] + 2 * alphas[1] + 2) / 5); // Bit code 011 alphas[4] = (byte)((2 * alphas[0] + 3 * alphas[1] + 2) / 5); // Bit code 100 alphas[5] = (byte)((1 * alphas[0] + 4 * alphas[1] + 2) / 5); // Bit code 101 alphas[6] = 0x00; // Bit code 110 alphas[7] = 0xFF; // Bit code 111 } // Note: Have to separate the next two loops, // it operates on a 6-byte system. // First three bytes uint bits = *((uint *)alphamask); for (int j = 0; j < 2; j++) { for (int i = 0; i < 4; i++) { // only put pixels out < width or height if (((x + i) < width) && ((y + j) < height)) { uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp + 3); rawData[offset] = alphas[bits & 0x07]; } bits >>= 3; } } // Last three bytes bits = *((uint *)&alphamask[3]); for (int j = 2; j < 4; j++) { for (int i = 0; i < 4; i++) { // only put pixels out < width or height if (((x + i) < width) && ((y + j) < height)) { uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp + 3); rawData[offset] = alphas[bits & 0x07]; } bits >>= 3; } } } } } } return(rawData); }
private static unsafe byte[] DecompressDXT1(DDSStruct header, byte[] data, PixelFormat pixelFormat) { // allocate bitmap int bpp = (int)(Helper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount)); int bps = (int)(header.width * bpp * Helper.PixelFormatToBpc(pixelFormat)); int sizeofplane = (int)(bps * header.height); int width = (int)header.width; int height = (int)header.height; int depth = (int)header.depth; // DXT1 decompressor byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp]; Colour8888[] colours = new Colour8888[4]; colours[0].alpha = 0xFF; colours[1].alpha = 0xFF; colours[2].alpha = 0xFF; fixed(byte *bytePtr = data) { byte *temp = bytePtr; for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { ushort colour0 = *((ushort *)temp); ushort colour1 = *((ushort *)(temp + 2)); Helper.DxtcReadColor(colour0, ref colours[0]); Helper.DxtcReadColor(colour1, ref colours[1]); uint bitmask = ((uint *)temp)[1]; temp += 8; if (colour0 > colour1) { // Four-color block: derive the other two colors. // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 // These 2-bit codes correspond to the 2-bit fields // stored in the 64-bit block. colours[2].blue = (byte)((2 * colours[0].blue + colours[1].blue + 1) / 3); colours[2].green = (byte)((2 * colours[0].green + colours[1].green + 1) / 3); colours[2].red = (byte)((2 * colours[0].red + colours[1].red + 1) / 3); //colours[2].alpha = 0xFF; colours[3].blue = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3); colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3); colours[3].red = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3); colours[3].alpha = 0xFF; } else { // Three-color block: derive the other color. // 00 = color_0, 01 = color_1, 10 = color_2, // 11 = transparent. // These 2-bit codes correspond to the 2-bit fields // stored in the 64-bit block. colours[2].blue = (byte)((colours[0].blue + colours[1].blue) / 2); colours[2].green = (byte)((colours[0].green + colours[1].green) / 2); colours[2].red = (byte)((colours[0].red + colours[1].red) / 2); //colours[2].alpha = 0xFF; colours[3].blue = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3); colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3); colours[3].red = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3); colours[3].alpha = 0x00; } for (int j = 0, k = 0; j < 4; j++) { for (int i = 0; i < 4; i++, k++) { int select = (int)((bitmask & (0x03 << k * 2)) >> k * 2); Colour8888 col = colours[select]; if (((x + i) < width) && ((y + j) < height)) { uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp); rawData[offset + 0] = (byte)col.red; rawData[offset + 1] = (byte)col.green; rawData[offset + 2] = (byte)col.blue; rawData[offset + 3] = (byte)col.alpha; } } } } } } } return(rawData); }
private static unsafe byte[] DecompressDXT3(DDSStruct header, byte[] data, PixelFormat pixelFormat) { // allocate bitmap int bpp = (int)(Helper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount)); int bps = (int)(header.width * bpp * Helper.PixelFormatToBpc(pixelFormat)); int sizeofplane = (int)(bps * header.height); int width = (int)header.width; int height = (int)header.height; int depth = (int)header.depth; // DXT3 decompressor byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp]; Colour8888[] colours = new Colour8888[4]; fixed(byte *bytePtr = data) { byte *temp = bytePtr; for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { byte *alpha = temp; temp += 8; Helper.DxtcReadColors(temp, ref colours); temp += 4; uint bitmask = ((uint *)temp)[1]; temp += 4; // Four-color block: derive the other two colors. // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 // These 2-bit codes correspond to the 2-bit fields // stored in the 64-bit block. colours[2].blue = (byte)((2 * colours[0].blue + colours[1].blue + 1) / 3); colours[2].green = (byte)((2 * colours[0].green + colours[1].green + 1) / 3); colours[2].red = (byte)((2 * colours[0].red + colours[1].red + 1) / 3); //colours[2].alpha = 0xFF; colours[3].blue = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3); colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3); colours[3].red = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3); //colours[3].alpha = 0xFF; for (int j = 0, k = 0; j < 4; j++) { for (int i = 0; i < 4; k++, i++) { int select = (int)((bitmask & (0x03 << k * 2)) >> k * 2); if (((x + i) < width) && ((y + j) < height)) { uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp); rawData[offset + 0] = (byte)colours[select].red; rawData[offset + 1] = (byte)colours[select].green; rawData[offset + 2] = (byte)colours[select].blue; } } } for (int j = 0; j < 4; j++) { //ushort word = (ushort)(alpha[2 * j] + 256 * alpha[2 * j + 1]); ushort word = (ushort)(alpha[2 * j] | (alpha[2 * j + 1] << 8)); for (int i = 0; i < 4; i++) { if (((x + i) < width) && ((y + j) < height)) { uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp + 3); rawData[offset] = (byte)(word & 0x0F); rawData[offset] = (byte)(rawData[offset] | (rawData[offset] << 4)); } word >>= 4; } } } } } } return(rawData); }