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];
            }
        }
Example #2
0
        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);
 }