public static void Compress8BitBlock(byte[] source, int sourcePosition, int sourceLineLength, byte[] destination, int destPosition, int channel, bool isSigned, DDSFormatDetails formatDetails) { // KFreon: Get min and max byte min = 255; byte max = 0; int channelBitSize = channel * formatDetails.ComponentSize; int count = sourcePosition + channelBitSize; byte[] sourceTexel = new byte[16]; int sourceTexelInd = 0; for (int i = 1; i <= 4; i++) { for (int j = 0; j < 4; j++) { byte color = formatDetails.ReadByte(source, count); sourceTexel[sourceTexelInd++] = color; // Cache source if (color > max) { max = color; } else if (color < min) { min = color; } count += 4 * formatDetails.ComponentSize; // skip to next entry in channel } count = sourcePosition + channelBitSize + sourceLineLength * i; } // Build Palette byte[] Colors = Build8BitPalette(min, max, isSigned); // Compress Pixels ulong line = 0; sourceTexelInd = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int ind = (i << 2) + j; byte color = sourceTexel[sourceTexelInd++]; int index = GetClosestValue(Colors, color); line |= (ulong)index << (ind * 3); } } byte[] compressed = BitConverter.GetBytes(line); destination[destPosition] = min; destination[destPosition + 1] = max; for (int i = 2; i < 8; i++) { destination[destPosition + i] = compressed[i - 2]; } }
static void WriteUncompressedPixel(byte[] source, int sourceStart, int[] sourceInds, DDSFormatDetails sourceFormatDetails, uint[] masks, byte[] destination, int destStart, int[] destInds, DDSFormatDetails destFormatDetails, bool oneChannel, bool twoChannel, bool requiresSignedAdjust) { if (twoChannel) // No large components - silly spec... { byte red = sourceFormatDetails.ReadByte(source, sourceStart); byte alpha = sourceFormatDetails.ReadByte(source, sourceStart + 3 * sourceFormatDetails.ComponentSize); destination[destStart] = masks[3] > masks[2] ? red : alpha; destination[destStart + 1] = masks[3] > masks[2] ? alpha : red; } else if (oneChannel) // No large components - silly spec... { byte blue = sourceFormatDetails.ReadByte(source, sourceStart); byte green = sourceFormatDetails.ReadByte(source, sourceStart + 1 * sourceFormatDetails.ComponentSize); byte red = sourceFormatDetails.ReadByte(source, sourceStart + 2 * sourceFormatDetails.ComponentSize); byte alpha = sourceFormatDetails.ReadByte(source, sourceStart + 3 * sourceFormatDetails.ComponentSize); destination[destStart] = (byte)(blue * 0.082 + green * 0.6094 + blue * 0.3086); // Weightings taken from ATI Compressonator. Dunno if this changes things much. } else { // Handle weird conditions where array isn't long enough... if (sourceInds[3] + sourceStart >= source.Length) { return; } for (int i = 0; i < 4; i++) { uint mask = masks[i]; if (mask != 0) { destFormatDetails.WriteColor(source, sourceStart + sourceInds[i], sourceFormatDetails, destination, destStart + destInds[i]); } } // Signed adjustments - Only happens for bytes for now. V8U8 if (requiresSignedAdjust) { destination[destStart + destInds[2]] += 128; destination[destStart + destInds[1]] += 128; } } }
void WriteByte(byte[] source, int sourceStart, DDSFormatDetails sourceFormatDetails, byte[] destination, int destStart) { destination[destStart] = sourceFormatDetails.ReadByte(source, sourceStart); }