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); }