private unsafe DDSBitmap UncompressDXT1(byte *data, int w, int h) { DDSBitmap res = new DDSBitmap(w, h); int blockCountX = (w + 3) / 4; int blockCountY = (h + 3) / 4; for (int j = 0; j < blockCountY; j++) { //byte[] blockStorage = r.ReadBytes(blockCountX * 16); for (int i = 0; i < blockCountX; i++) { DecompressBlockDXT1(i * 4, j * 4, w, h, data, res); data += 8; } } return(res); }
private DDSBitmap readLinearImage(byte[] data, int w, int h, int bitCount) { Action <int, int, BinaryReader, DDSBitmap> setPixel; if (bitCount == 16) { setPixel = (x, y, reader, resource) => { resource.SetPixel(x, y, Color.FromShort(reader.ReadUInt16())); }; } else if (bitCount == 32) { setPixel = (x, y, reader, resource) => { resource.SetPixel(x, y, reader.ReadInt32()); }; } else { throw new NotSupportedException(); } DDSBitmap res = new DDSBitmap(w, h); using (MemoryStream ms = new MemoryStream(data)) { using (BinaryReader r = new BinaryReader(ms)) { for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { setPixel(x, y, r, res); } } } } return(res); }
unsafe void DecompressBlockDXT5(int x, int y, int width, int height, byte *blockStorage, DDSBitmap image) { byte alpha0 = blockStorage[0]; byte alpha1 = blockStorage[1]; ushort alphaCode2 = *((ushort *)(blockStorage + 2)); uint alphaCode1 = *((uint *)(blockStorage + 4)); ushort color0 = *((ushort *)(blockStorage + 8)); ushort color1 = *((ushort *)(blockStorage + 10)); int temp; temp = (color0 >> 11) * 255 + 16; byte r0 = (byte)((temp / 32 + temp) / 32); temp = ((color0 & 0x07E0) >> 5) * 255 + 32; byte g0 = (byte)((temp / 64 + temp) / 64); temp = (color0 & 0x001F) * 255 + 16; byte b0 = (byte)((temp / 32 + temp) / 32); temp = (color1 >> 11) * 255 + 16; byte r1 = (byte)((temp / 32 + temp) / 32); temp = ((color1 & 0x07E0) >> 5) * 255 + 32; byte g1 = (byte)((temp / 64 + temp) / 64); temp = (color1 & 0x001F) * 255 + 16; byte b1 = (byte)((temp / 32 + temp) / 32); uint code = *((uint *)(blockStorage + 12)); for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { int alphaCodeIndex = 3 * (4 * j + i); int alphaCode; if (alphaCodeIndex <= 12) { alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07; } else if (alphaCodeIndex == 15) { alphaCode = (int)((alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06)); } else { alphaCode = (int)((alphaCode1 >> (alphaCodeIndex - 16)) & 0x07); } byte finalAlpha; if (alphaCode == 0) { finalAlpha = alpha0; } else if (alphaCode == 1) { finalAlpha = alpha1; } else { if (alpha0 > alpha1) { finalAlpha = (byte)(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7); } else { if (alphaCode == 6) { finalAlpha = 0; } else if (alphaCode == 7) { finalAlpha = 255; } else { finalAlpha = (byte)(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5); } } } byte colorCode = (byte)((code >> 2 * (4 * j + i)) & 0x03); int finalColor = 0; switch (colorCode) { case 0: finalColor = Color.FromArgb(finalAlpha, r0, g0, b0); break; case 1: finalColor = Color.FromArgb(finalAlpha, r1, g1, b1); break; case 2: finalColor = Color.FromArgb(finalAlpha, (byte)((2 * r0 + r1) / 3), (byte)((2 * g0 + g1) / 3), (byte)((2 * b0 + b1) / 3)); break; case 3: finalColor = Color.FromArgb(finalAlpha, (byte)((r0 + 2 * r1) / 3), (byte)((g0 + 2 * g1) / 3), (byte)((b0 + 2 * b1) / 3)); break; } if (x + i < width && y + j < height) { image.SetPixel(x + i, y + j, finalColor); } //image[(y + j)*width + (x + i)] = finalColor; } } }
private unsafe void DecompressBlockDXT1(int x, int y, int width, int height, byte *blockStorage, DDSBitmap image) { ushort color0 = *((ushort *)(blockStorage)); ushort color1 = *((ushort *)(blockStorage + 2)); int temp; temp = (color0 >> 11) * 255 + 16; byte r0 = (byte)((temp / 32 + temp) / 32); temp = ((color0 & 0x07E0) >> 5) * 255 + 32; byte g0 = (byte)((temp / 64 + temp) / 64); temp = (color0 & 0x001F) * 255 + 16; byte b0 = (byte)((temp / 32 + temp) / 32); temp = (color1 >> 11) * 255 + 16; byte r1 = (byte)((temp / 32 + temp) / 32); temp = ((color1 & 0x07E0) >> 5) * 255 + 32; byte g1 = (byte)((temp / 64 + temp) / 64); temp = (color1 & 0x001F) * 255 + 16; byte b1 = (byte)((temp / 32 + temp) / 32); uint code = *((uint *)(blockStorage + 4)); for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { int finalColor = 0; byte positionCode = (byte)((code >> 2 * (4 * j + i)) & 0x03); if (color0 > color1) { switch (positionCode) { case 0: finalColor = Color.FromArgb(255, r0, g0, b0); break; case 1: finalColor = Color.FromArgb(255, r1, g1, b1); break; case 2: finalColor = Color.FromArgb(255, (byte)((2 * r0 + r1) / 3), (byte)((2 * g0 + g1) / 3), (byte)((2 * b0 + b1) / 3)); break; case 3: finalColor = Color.FromArgb(255, (byte)((r0 + 2 * r1) / 3), (byte)((g0 + 2 * g1) / 3), (byte)((b0 + 2 * b1) / 3)); break; } } else { switch (positionCode) { case 0: finalColor = Color.FromArgb(255, r0, g0, b0); break; case 1: finalColor = Color.FromArgb(255, r1, g1, b1); break; case 2: finalColor = Color.FromArgb(255, (byte)((r0 + r1) / 2), (byte)((g0 + g1) / 2), (byte)((b0 + b1) / 2)); break; case 3: finalColor = Color.FromArgb(255, 0, 0, 0); break; } } if (x + i < width && y + j < height) { image.SetPixel(x + i, y + j, finalColor); } } } }