public Color[] Decompress(byte[] blockData) { Debug.Assert(blockData.Length == BlockFormat.BC2ByteSize); var block = BC2BlockData.FromBytes(blockData); var colorTable = BC1ColorTable.Create(block.Color0, block.Color1); var colors = new Color[BlockFormat.TexelCount]; for (int i = 0; i < colors.Length; ++i) { int index = block.ColorIndexes[i]; int alpha = block.ColorAlphas[i]; // Convert 4-bit alpha to 8-bit by shifting the bits left and ORing // with the most significant bits to calculate the remaining values alpha = (alpha << 4) | (alpha & 0x0F); var color16 = colorTable[index]; var color32 = Color.FromArgb(alpha, ColorUtility.To32Bit(color16)); colors[i] = color32; } return(colors); }
/// <summary> /// Instantiates a <see cref="BC2BlockData"/> from compressed BC2 block data. /// </summary> /// <param name="bytes">The data of a BC2 compressed block.</param> public static BC2BlockData FromBytes(byte[] bytes) { Debug.Assert(bytes.Length == BlockFormat.BC2ByteSize, "Mismatching number of bytes for format."); byte[,] alphas = new byte[4, 2]; alphas[0, 0] = bytes[0]; alphas[0, 1] = bytes[1]; alphas[1, 0] = bytes[2]; alphas[1, 1] = bytes[3]; alphas[2, 0] = bytes[4]; alphas[2, 1] = bytes[5]; alphas[3, 0] = bytes[6]; alphas[3, 1] = bytes[7]; byte c0Low = bytes[8]; byte c0Hi = bytes[9]; byte c1Low = bytes[10]; byte c1Hi = bytes[11]; byte[] indexes = new byte[4]; indexes[0] = bytes[12]; indexes[1] = bytes[13]; indexes[2] = bytes[14]; indexes[3] = bytes[15]; var block = new BC2BlockData(); block.Color0 = Color565.FromValue((ushort)((c0Hi << 8) | c0Low)); block.Color1 = Color565.FromValue((ushort)((c1Hi << 8) | c1Low)); for (int p = 0, row = 0; p < BlockFormat.TexelCount; p += BlockFormat.Dimension, ++row) { int a = p; int b = p + 1; int c = p + 2; int d = p + 3; block.ColorIndexes[a] = indexes[row] & 0x03; block.ColorIndexes[b] = (indexes[row] >> 2) & 0x03; block.ColorIndexes[c] = (indexes[row] >> 4) & 0x03; block.ColorIndexes[d] = (indexes[row] >> 6) & 0x03; block.ColorAlphas[a] = (byte)(alphas[row, 1] & 0x0F); block.ColorAlphas[b] = (byte)((alphas[row, 1] & 0xF0) >> 4); block.ColorAlphas[c] = (byte)(alphas[row, 0] & 0x0F); block.ColorAlphas[d] = (byte)((alphas[row, 0] & 0xF0) >> 4); } return(block); }
public byte[] Compress(Color[] colors) { Debug.Assert(colors.Length == BlockFormat.TexelCount); var colorSpace = new ColorSpace(colors); var colorTable = BC1ColorTable.Create(colorSpace.MaxColor, colorSpace.MinColor); var block = new BC2BlockData(); block.Color0 = colorTable[0]; block.Color1 = colorTable[1]; for (int i = 0; i < colors.Length; ++i) { var color32 = colors[i]; var color16 = ColorUtility.To16Bit(color32); block.ColorIndexes[i] = ColorUtility.GetIndexOfClosestColor(colorTable, color16); block.ColorAlphas[i] = color32.A >> 4; // Convert 8-bit alpha to 4-bit } return(block.ToBytes()); }