using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CSharpImageLibrary.DDS { public class DDS_BlockHelpers { //From https://github.com/KFreon/CSharpImageLibrary/blob/master/CSharpImageLibrary/DDS/DDS_BlockHelpers.cs internal static void Decompress8BitBlock(byte[] source, int sourceStart, byte[] destination, int decompressedStart, int decompressedLineLength, bool isSigned) { byte min = source[sourceStart]; byte max = source[sourceStart + 1]; byte[] Colours = Build8BitPalette(min, max, isSigned); // KFreon: Decompress pixels ulong bitmask = (ulong)source[sourceStart + 2] << 0 | (ulong)source[sourceStart + 3] << 8 | (ulong)source[sourceStart + 4] << 16 | // KFreon: Read all 6 compressed bytes into single. (ulong)source[sourceStart + 5] << 24 | (ulong)source[sourceStart + 6] << 32 | (ulong)source[sourceStart + 7] << 40; // KFreon: Bitshift and mask compressed data to get 3 bit indicies, and retrieve indexed colour of pixel. for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int index = i * 4 + j; int destPos = decompressedStart + j * 4 + (i * decompressedLineLength); destination[destPos] = Colours[bitmask >> (index * 3) & 0x7]; } } } /// /// Builds palette for 8 bit channel. /// /// First main colour (often actually minimum) /// Second main colour (often actually maximum) /// true = sets signed alpha range (-254 -- 255), false = 0 -- 255 /// 8 byte colour palette. internal static byte[] Build8BitPalette(byte min, byte max, bool isSigned) { byte[] Colours = new byte[8]; Colours[0] = min; Colours[1] = max; // KFreon: Choose which type of interpolation is required if (min > max) { // KFreon: Interpolate other colours Colours[2] = (byte)((6d * min + 1d * max) / 7d); // NO idea what the +3 is...not in the Microsoft spec, but seems to be everywhere else. Colours[3] = (byte)((5d * min + 2d * max) / 7d); Colours[4] = (byte)((4d * min + 3d * max) / 7d); Colours[5] = (byte)((3d * min + 4d * max) / 7d); Colours[6] = (byte)((2d * min + 5d * max) / 7d); Colours[7] = (byte)((1d * min + 6d * max) / 7d); } else { // KFreon: Interpolate other colours and add Opacity or something... Colours[2] = (byte)((4d * min + 1d * max) / 5d); Colours[3] = (byte)((3d * min + 2d * max) / 5d); Colours[4] = (byte)((2d * min + 3d * max) / 5d); Colours[5] = (byte)((1d * min + 4d * max) / 5d); Colours[6] = (byte)(isSigned ? -254 : 0); // KFreon: snorm and unorm have different alpha ranges Colours[7] = 255; } return Colours; } } }