/// <summary> /// Decodes the given block /// </summary> /// <param name="inBlock">Block to decode</param> /// <param name="has1bitAlpha">Set if block contains DXT1 1-bit alpha (COMPRESSED_RGBA_S3TC_DXT1_EXT)</param> /// <param name="isDXT1">Set if block should be decoded as DXT1, else it will be decoded as DXT3/5</param> /// <returns></returns> private static byte[] DecodeColorBlock(DXT1Block inBlock, bool has1bitAlpha, bool isDXT1) { byte[] outData = new byte[(4 * 4) * 4]; byte[,] colors = new byte[4, 4]; UnpackRgb565(inBlock.Color0, out colors[0, 2], out colors[0, 1], out colors[0, 0]); UnpackRgb565(inBlock.Color1, out colors[1, 2], out colors[1, 1], out colors[1, 0]); colors[0, 3] = 255; colors[1, 3] = 255; if (isDXT1 && inBlock.Color0 <= inBlock.Color1) { colors[2, 0] = (byte)((colors[0, 0] + colors[1, 0]) / 2); colors[2, 1] = (byte)((colors[0, 1] + colors[1, 1]) / 2); colors[2, 2] = (byte)((colors[0, 2] + colors[1, 2]) / 2); colors[2, 3] = 255; colors[3, 0] = 0; colors[3, 1] = 0; colors[3, 2] = 0; colors[3, 3] = (byte)((has1bitAlpha && inBlock.Color0 <= inBlock.Color1) ? 0 : 0xFF); } else { colors[2, 0] = (byte)((2 * colors[0, 0] + colors[1, 0]) / 3); colors[2, 1] = (byte)((2 * colors[0, 1] + colors[1, 1]) / 3); colors[2, 2] = (byte)((2 * colors[0, 2] + colors[1, 2]) / 3); colors[2, 3] = 255; colors[3, 0] = (byte)((colors[0, 0] + 2 * colors[1, 0]) / 3); colors[3, 1] = (byte)((colors[0, 1] + 2 * colors[1, 1]) / 3); colors[3, 2] = (byte)((colors[0, 2] + 2 * colors[1, 2]) / 3); colors[3, 3] = 255; } for (int by = 0; by < 4; by++) { for (int bx = 0; bx < 4; bx++) { byte code = inBlock.Bits[(by * 4) + bx]; for (int c = 0; c < 4; c++) { outData[(((by * 4) + bx) * 4) + c] = colors[code, c]; } } } return(outData); }
public DXT3Block(EndianBinaryReader reader, DXTxRGTCBlockLayout blockLayout) { switch (blockLayout) { case DXTxRGTCBlockLayout.Normal: Alpha = reader.ReadUInt64(); Color = new DXT1Block(reader, blockLayout); break; case DXTxRGTCBlockLayout.PSP: Color = new DXT1Block(reader, blockLayout); Alpha = reader.ReadUInt64(); break; default: throw new Exception("Unknown block layout"); } }
public DXT5Block(EndianBinaryReader reader, DXTxRGTCBlockLayout blockLayout) { byte bits_5, bits_4, bits_3, bits_2, bits_1, bits_0; switch (blockLayout) { case DXTxRGTCBlockLayout.Normal: Alpha0 = reader.ReadByte(); Alpha1 = reader.ReadByte(); bits_5 = reader.ReadByte(); bits_4 = reader.ReadByte(); bits_3 = reader.ReadByte(); bits_2 = reader.ReadByte(); bits_1 = reader.ReadByte(); bits_0 = reader.ReadByte(); Bits = DXTxRGTC.ExtractBits((((ulong)bits_0 << 40) | ((ulong)bits_1 << 32) | ((ulong)bits_2 << 24) | ((ulong)bits_3 << 16) | ((ulong)bits_4 << 8) | (ulong)bits_5), 3); Color = new DXT1Block(reader, blockLayout); break; case DXTxRGTCBlockLayout.PSP: Color = new DXT1Block(reader, blockLayout); Alpha0 = reader.ReadByte(); Alpha1 = reader.ReadByte(); bits_5 = reader.ReadByte(); bits_4 = reader.ReadByte(); bits_3 = reader.ReadByte(); bits_2 = reader.ReadByte(); bits_1 = reader.ReadByte(); bits_0 = reader.ReadByte(); Bits = DXTxRGTC.ExtractBits((((ulong)bits_0 << 40) | ((ulong)bits_1 << 32) | ((ulong)bits_2 << 24) | ((ulong)bits_3 << 16) | ((ulong)bits_4 << 8) | (ulong)bits_5), 3); break; default: throw new Exception("Unknown block layout"); } }
private static byte[] DecodeDXT1Block(EndianBinaryReader reader, PixelDataFormat inputFormat, DXTxRGTCBlockLayout blockLayout, DXTxRGTCSignedness signedness) { DXT1Block inBlock = new DXT1Block(reader, blockLayout); return(DecodeColorBlock(inBlock, (inputFormat & PixelDataFormat.MaskChannels) != PixelDataFormat.ChannelsRgb, true)); }