using System; using Imaging.DDSReader.Utils; namespace Imaging.DDSReader { internal class Decompressor { internal static byte[] Expand(DDSStruct header, byte[] data, PixelFormat pixelFormat) { System.Diagnostics.Debug.WriteLine(pixelFormat); byte[] rawData = null; switch (pixelFormat) { case PixelFormat.RGBA: rawData = DecompressRGBA(header, data, pixelFormat); break; case PixelFormat.RGB: rawData = DecompressRGB(header, data, pixelFormat); break; case PixelFormat.LUMINANCE: case PixelFormat.LUMINANCE_ALPHA: rawData = DecompressLum(header, data, pixelFormat); break; case PixelFormat.DXT1: rawData = DecompressDXT1(header, data, pixelFormat); break; case PixelFormat.DXT2: rawData = DecompressDXT2(header, data, pixelFormat); break; case PixelFormat.DXT3: rawData = DecompressDXT3(header, data, pixelFormat); break; case PixelFormat.DXT4: rawData = DecompressDXT4(header, data, pixelFormat); break; case PixelFormat.DXT5: rawData = DecompressDXT5(header, data, pixelFormat); break; case PixelFormat.THREEDC: rawData = Decompress3Dc(header, data, pixelFormat); break; case PixelFormat.ATI1N: rawData = DecompressAti1n(header, data, pixelFormat); break; case PixelFormat.RXGB: rawData = DecompressRXGB(header, data, pixelFormat); break; case PixelFormat.R16F: case PixelFormat.G16R16F: case PixelFormat.A16B16G16R16F: case PixelFormat.R32F: case PixelFormat.G32R32F: case PixelFormat.A32B32G32R32F: rawData = DecompressFloat(header, data, pixelFormat); break; default: throw new UnknownFileFormatException(); } return rawData; } private static unsafe byte[] DecompressDXT1(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; 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) { 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[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 { 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[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 byte[] DecompressDXT2(DDSStruct header, byte[] data, PixelFormat pixelFormat) { int width = (int)header.width; int height = (int)header.height; int depth = (int)header.depth; byte[] rawData = DecompressDXT3(header, data, pixelFormat); Helper.CorrectPremult((uint)(width * height * depth), ref rawData); return rawData; } private static unsafe byte[] DecompressDXT3(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; 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; 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[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); 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] | (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; } private static byte[] DecompressDXT4(DDSStruct header, byte[] data, PixelFormat pixelFormat) { int width = (int)header.width; int height = (int)header.height; int depth = (int)header.depth; byte[] rawData = DecompressDXT5(header, data, pixelFormat); Helper.CorrectPremult((uint)(width * height * depth), ref rawData); return rawData; } private static unsafe byte[] DecompressDXT5(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; Colour8888[] colours = new Colour8888[4]; ushort[] alphas = new ushort[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 colours); uint bitmask = ((uint*)temp)[1]; temp += 8; 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[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); int k = 0; for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; k++, i++) { 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] = (byte)col.red; rawData[offset + 1] = (byte)col.green; rawData[offset + 2] = (byte)col.blue; } } } if (alphas[0] > alphas[1]) { alphas[2] = (ushort)((6 * alphas[0] + 1 * alphas[1] + 3) / 7); alphas[3] = (ushort)((5 * alphas[0] + 2 * alphas[1] + 3) / 7); alphas[4] = (ushort)((4 * alphas[0] + 3 * alphas[1] + 3) / 7); alphas[5] = (ushort)((3 * alphas[0] + 4 * alphas[1] + 3) / 7); alphas[6] = (ushort)((2 * alphas[0] + 5 * alphas[1] + 3) / 7); alphas[7] = (ushort)((1 * alphas[0] + 6 * alphas[1] + 3) / 7); } else { alphas[2] = (ushort)((4 * alphas[0] + 1 * alphas[1] + 2) / 5); alphas[3] = (ushort)((3 * alphas[0] + 2 * alphas[1] + 2) / 5); alphas[4] = (ushort)((2 * alphas[0] + 3 * alphas[1] + 2) / 5); alphas[5] = (ushort)((1 * alphas[0] + 4 * alphas[1] + 2) / 5); alphas[6] = 0x00; alphas[7] = 0xFF; } uint bits = (uint)((alphamask[0]) | (alphamask[1] << 8) | (alphamask[2] << 16)); for (int j = 0; j < 2; j++) { 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)alphas[bits & 0x07]; } bits >>= 3; } } bits = (uint)((alphamask[3]) | (alphamask[4] << 8) | (alphamask[5] << 16)); for (int j = 2; j < 4; j++) { 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)alphas[bits & 0x07]; } bits >>= 3; } } } } } } return rawData; } private static unsafe byte[] DecompressRGB(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; uint valMask = (uint)((header.pixelformat.rgbbitcount == 32) ? ~0 : (1 << (int)header.pixelformat.rgbbitcount) - 1); uint pixSize = (uint)(((int)header.pixelformat.rgbbitcount + 7) / 8); int rShift1 = 0; int rMul = 0; int rShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.rbitmask, ref rShift1, ref rMul, ref rShift2); int gShift1 = 0; int gMul = 0; int gShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.gbitmask, ref gShift1, ref gMul, ref gShift2); int bShift1 = 0; int bMul = 0; int bShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.bbitmask, ref bShift1, ref bMul, ref bShift2); int offset = 0; int pixnum = width * height * depth; fixed (byte* bytePtr = data) { byte* temp = bytePtr; while (pixnum-- > 0) { uint px = *((uint*)temp) & valMask; temp += pixSize; uint pxc = px & header.pixelformat.rbitmask; rawData[offset + 0] = (byte)(((pxc >> rShift1) * rMul) >> rShift2); pxc = px & header.pixelformat.gbitmask; rawData[offset + 1] = (byte)(((pxc >> gShift1) * gMul) >> gShift2); pxc = px & header.pixelformat.bbitmask; rawData[offset + 2] = (byte)(((pxc >> bShift1) * bMul) >> bShift2); rawData[offset + 3] = 0xff; offset += 4; } } return rawData; } private static unsafe byte[] DecompressRGBA(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; uint valMask = (uint)((header.pixelformat.rgbbitcount == 32) ? ~0 : (1 << (int)header.pixelformat.rgbbitcount) - 1); uint pixSize = (header.pixelformat.rgbbitcount + 7) / 8; int rShift1 = 0; int rMul = 0; int rShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.rbitmask, ref rShift1, ref rMul, ref rShift2); int gShift1 = 0; int gMul = 0; int gShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.gbitmask, ref gShift1, ref gMul, ref gShift2); int bShift1 = 0; int bMul = 0; int bShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.bbitmask, ref bShift1, ref bMul, ref bShift2); int aShift1 = 0; int aMul = 0; int aShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.alphabitmask, ref aShift1, ref aMul, ref aShift2); int offset = 0; int pixnum = width * height * depth; fixed (byte* bytePtr = data) { byte* temp = bytePtr; while (pixnum-- > 0) { uint px = *((uint*)temp) & valMask; temp += pixSize; uint pxc = px & header.pixelformat.rbitmask; rawData[offset + 0] = (byte)(((pxc >> rShift1) * rMul) >> rShift2); pxc = px & header.pixelformat.gbitmask; rawData[offset + 1] = (byte)(((pxc >> gShift1) * gMul) >> gShift2); pxc = px & header.pixelformat.bbitmask; rawData[offset + 2] = (byte)(((pxc >> bShift1) * bMul) >> bShift2); pxc = px & header.pixelformat.alphabitmask; rawData[offset + 3] = (byte)(((pxc >> aShift1) * aMul) >> aShift2); offset += 4; } } return rawData; } private static unsafe byte[] Decompress3Dc(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; byte[] yColours = new byte[8]; byte[] xColours = new byte[8]; int offset = 0; 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* temp2 = temp + 8; int t1 = yColours[0] = temp[0]; int t2 = yColours[1] = temp[1]; temp += 2; if (t1 > t2) for (int i = 2; i < 8; ++i) yColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 7); else { for (int i = 2; i < 6; ++i) yColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 5); yColours[6] = 0; yColours[7] = 255; } t1 = xColours[0] = temp2[0]; t2 = xColours[1] = temp2[1]; temp2 += 2; if (t1 > t2) for (int i = 2; i < 8; ++i) xColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 7); else { for (int i = 2; i < 6; ++i) xColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 5); xColours[6] = 0; xColours[7] = 255; } int currentOffset = offset; for (int k = 0; k < 4; k += 2) { uint bitmask = ((uint)(temp[0]) << 0) | ((uint)(temp[1]) << 8) | ((uint)(temp[2]) << 16); uint bitmask2 = ((uint)(temp2[0]) << 0) | ((uint)(temp2[1]) << 8) | ((uint)(temp2[2]) << 16); for (int j = 0; j < 2; j++) { if ((y + k + j) < height) { for (int i = 0; i < 4; i++) { if (((x + i) < width)) { int t; byte tx, ty; t1 = currentOffset + (x + i) * 3; rawData[t1 + 1] = ty = yColours[bitmask & 0x07]; rawData[t1 + 0] = tx = xColours[bitmask2 & 0x07]; t = 127 * 128 - (tx - 127) * (tx - 128) - (ty - 127) * (ty - 128); if (t > 0) rawData[t1 + 2] = (byte)(Math.Sqrt(t) + 128); else rawData[t1 + 2] = 0x7F; } bitmask >>= 3; bitmask2 >>= 3; } currentOffset += bps; } } temp += 3; temp2 += 3; } temp += 8; } offset += bps * 4; } } } return rawData; } private static unsafe byte[] DecompressAti1n(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; byte[] colours = new byte[8]; uint offset = 0; 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) { int t1 = colours[0] = temp[0]; int t2 = colours[1] = temp[1]; temp += 2; if (t1 > t2) for (int i = 2; i < 8; ++i) colours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 7); else { for (int i = 2; i < 6; ++i) colours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 5); colours[6] = 0; colours[7] = 255; } uint currOffset = offset; for (int k = 0; k < 4; k += 2) { uint bitmask = ((uint)(temp[0]) << 0) | ((uint)(temp[1]) << 8) | ((uint)(temp[2]) << 16); for (int j = 0; j < 2; j++) { if ((y + k + j) < height) { for (int i = 0; i < 4; i++) { if (((x + i) < width)) { t1 = (int)(currOffset + (x + i)); rawData[t1] = colours[bitmask & 0x07]; } bitmask >>= 3; } currOffset += (uint)bps; } } temp += 3; } } offset += (uint)(bps * 4); } } } return rawData; } private static unsafe byte[] DecompressLum(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; int lShift1 = 0; int lMul = 0; int lShift2 = 0; Helper.ComputeMaskParams(header.pixelformat.rbitmask, ref lShift1, ref lMul, ref lShift2); int offset = 0; int pixnum = width * height * depth; fixed (byte* bytePtr = data) { byte* temp = bytePtr; while (pixnum-- > 0) { byte px = *(temp++); rawData[offset + 0] = (byte)(((px >> lShift1) * lMul) >> lShift2); rawData[offset + 1] = (byte)(((px >> lShift1) * lMul) >> lShift2); rawData[offset + 2] = (byte)(((px >> lShift1) * lMul) >> lShift2); rawData[offset + 3] = (byte)(((px >> lShift1) * lMul) >> lShift2); offset += 4; } } return rawData; } private static unsafe byte[] DecompressRXGB(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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; 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]; 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; } } } if (alphas[0] > alphas[1]) { alphas[2] = (byte)((6 * alphas[0] + 1 * alphas[1] + 3) / 7); alphas[3] = (byte)((5 * alphas[0] + 2 * alphas[1] + 3) / 7); alphas[4] = (byte)((4 * alphas[0] + 3 * alphas[1] + 3) / 7); alphas[5] = (byte)((3 * alphas[0] + 4 * alphas[1] + 3) / 7); alphas[6] = (byte)((2 * alphas[0] + 5 * alphas[1] + 3) / 7); alphas[7] = (byte)((1 * alphas[0] + 6 * alphas[1] + 3) / 7); } else { alphas[2] = (byte)((4 * alphas[0] + 1 * alphas[1] + 2) / 5); alphas[3] = (byte)((3 * alphas[0] + 2 * alphas[1] + 2) / 5); alphas[4] = (byte)((2 * alphas[0] + 3 * alphas[1] + 2) / 5); alphas[5] = (byte)((1 * alphas[0] + 4 * alphas[1] + 2) / 5); alphas[6] = 0x00; alphas[7] = 0xFF; } uint bits = *((uint*)alphamask); for (int j = 0; j < 2; j++) { 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] = alphas[bits & 0x07]; } bits >>= 3; } } bits = *((uint*)&alphamask[3]); for (int j = 2; j < 4; j++) { 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] = alphas[bits & 0x07]; } bits >>= 3; } } } } } } return rawData; } private static unsafe byte[] DecompressFloat(DDSStruct header, byte[] data, PixelFormat pixelFormat) { 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]; int size = 0; fixed (byte* bytePtr = data) { byte* temp = bytePtr; fixed (byte* destPtr = rawData) { byte* destData = destPtr; switch (pixelFormat) { case PixelFormat.R32F: size = width * height * depth * 3; for (int i = 0, j = 0; i < size; i += 3, j++) { ((float*)destData)[i] = ((float*)temp)[j]; ((float*)destData)[i + 1] = 1.0f; ((float*)destData)[i + 2] = 1.0f; } break; case PixelFormat.A32B32G32R32F: Array.Copy(data, rawData, data.Length); break; case PixelFormat.G32R32F: size = width * height * depth * 3; for (int i = 0, j = 0; i < size; i += 3, j += 2) { ((float*)destData)[i] = ((float*)temp)[j]; ((float*)destData)[i + 1] = ((float*)temp)[j + 1]; ((float*)destData)[i + 2] = 1.0f; } break; case PixelFormat.R16F: size = width * height * depth * bpp; Helper.ConvR16ToFloat32((uint*)destData, (ushort*)temp, (uint)size); break; case PixelFormat.A16B16G16R16F: size = width * height * depth * bpp; Helper.ConvFloat16ToFloat32((uint*)destData, (ushort*)temp, (uint)size); break; case PixelFormat.G16R16F: size = width * height * depth * bpp; Helper.ConvG16R16ToFloat32((uint*)destData, (ushort*)temp, (uint)size); break; default: break; } } } return rawData; } } }