/// <summary> /// Decompresses an image. /// </summary> /// <param name="width">The width of the image to decompress.</param> /// <param name="height">The height of the image to decompress.</param> /// <param name="data">The compressed image data.</param> /// <param name="flags">The compression flags.</param> /// <returns>Returns the decompressed image as a byte array in the 32Bit RGBA-Format.</returns> internal static byte[] DecompressImage(int width, int height, byte[] data, DxtFlags flags) { var rgba = new byte[width * height * 4]; // initialise the block input var sourceBlock_pos = 0; var bytesPerBlock = (flags & DxtFlags.DXT1) != 0 ? 8 : 16; var targetRGBA = new byte[4 * 16]; // loop over blocks for (var y = 0; y < height; y += 4) { for (var x = 0; x < width; x += 4) { // decompress the block var targetRGBA_pos = 0; if (data.Length == sourceBlock_pos) { continue; } Decompress(targetRGBA, data, sourceBlock_pos, flags); // Write the decompressed pixels to the correct image locations for (var py = 0; py < 4; py++) { for (var px = 0; px < 4; px++) { var sx = x + px; var sy = y + py; if (sx < width && sy < height) { var targetPixel = 4 * ((width * sy) + sx); rgba[targetPixel + 0] = targetRGBA[targetRGBA_pos + 0]; rgba[targetPixel + 1] = targetRGBA[targetRGBA_pos + 1]; rgba[targetPixel + 2] = targetRGBA[targetRGBA_pos + 2]; rgba[targetPixel + 3] = targetRGBA[targetRGBA_pos + 3]; targetRGBA_pos += 4; } else { // Ignore that pixel targetRGBA_pos += 4; } } } sourceBlock_pos += bytesPerBlock; } } return(rgba); }
private static void Decompress(byte[] rgba, byte[] block, int blockIndex, DxtFlags flags) { // get the block locations var colorBlockIndex = blockIndex; if ((flags & (DxtFlags.DXT3 | DxtFlags.DXT5)) != 0) { colorBlockIndex += 8; } // decompress color DecompressColor(rgba, block, colorBlockIndex, (flags & DxtFlags.DXT1) != 0); // decompress alpha separately if necessary if ((flags & DxtFlags.DXT3) != 0) { DecompressAlphaDxt3(rgba, block, blockIndex); } else if ((flags & DxtFlags.DXT5) != 0) { DecompressAlphaDxt5(rgba, block, blockIndex); } }