示例#1
0
 public static void ExportDDSHeader(Stream destination, DDSConvertParameters @params)
 {
     using (BinaryWriter binWriter = new BinaryWriter(destination, Encoding.UTF8, true))
     {
         binWriter.Write(MagicNumber);
         binWriter.Write(HeaderSize);
         binWriter.Write((uint)@params.DFlags);
         binWriter.Write(@params.Height);
         binWriter.Write(@params.Width);
         binWriter.Write(@params.PitchOrLinearSize);
         binWriter.Write(@params.Depth);
         binWriter.Write(@params.MipMapCount);
         // read alphabitdepth?
         for (int i = 0; i < 11; i++)                 // reserved
         {
             binWriter.Write(0);
         }
         DDSPixelFormat pixelFormat = new DDSPixelFormat()
         {
             Flags       = @params.PixelFormatFlags,
             FourCC      = @params.FourCC,
             RGBBitCount = @params.RGBBitCount,
             RBitMask    = @params.RBitMask,
             GBitMask    = @params.GBitMask,
             BBitMask    = @params.BBitMask,
             ABitMask    = @params.ABitMask,
         };
         pixelFormat.Write(binWriter);
         binWriter.Write((uint)@params.Caps);
         binWriter.Write((uint)Caps2);
         binWriter.Write(0);                 // caps3
         binWriter.Write(0);                 // caps4
         binWriter.Write(0);                 // reserved (texturestage?)
     }
 }
示例#2
0
        private static void ExportR16ToDDS(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
        {
            DDSConvertParameters bgraParams = new DDSConvertParameters();

            @params.CopyTo(bgraParams);
            bgraParams.RGBBitCount = 32;
            bgraParams.RBitMask    = 0xFF0000;
            bgraParams.GBitMask    = 0xFF00;
            bgraParams.BBitMask    = 0xFF;
            bgraParams.ABitMask    = 0xFF000000;
            ExportDDSHeader(destination, bgraParams);

            long pixelCount = @params.BitMapDepth * @params.Height * @params.Width;

            for (int i = 0; i < pixelCount; i++)
            {
                ushort pixel = sourceReader.ReadUInt16();
                float  f     = Half.ToHalf(pixel);
                byte   R     = (byte)Math.Ceiling(f * 255.0);
                destination.WriteByte(0);                       // B
                destination.WriteByte(0);                       // G
                destination.WriteByte(R);                       // R
                destination.WriteByte(0xFF);                    // A
            }
        }
示例#3
0
 public static void ExportDDS(Stream source, Stream destination, DDSConvertParameters @params)
 {
     using (BinaryReader sourceReader = new BinaryReader(source))
     {
         ExportDDS(sourceReader, destination, @params);
     }
 }
示例#4
0
 public static void DecompressRGB(Stream source, Stream destination, DDSConvertParameters @params)
 {
     using (BinaryReader reader = new BinaryReader(source))
     {
         DecompressRGBA(reader, destination, @params, false);
     }
 }
示例#5
0
 public static void DecompressDXT1(Stream source, Stream destination, DDSConvertParameters @params)
 {
     using (BinaryReader sourceReader = new BinaryReader(source))
     {
         DecompressDXT1(sourceReader, destination, @params);
     }
 }
示例#6
0
        private static void ExportARGB32ToDDS(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
        {
            DDSConvertParameters bgraParams = new DDSConvertParameters();

            @params.CopyTo(bgraParams);
            bgraParams.RBitMask = 0xFF0000;
            bgraParams.GBitMask = 0xFF00;
            bgraParams.BBitMask = 0xFF;
            bgraParams.ABitMask = 0xFF000000;
            ExportDDSHeader(destination, bgraParams);

            long pixelCount = @params.BitMapDepth * @params.Height * @params.Width;

            for (int i = 0; i < pixelCount; i++)
            {
                byte A = sourceReader.ReadByte();
                byte R = sourceReader.ReadByte();
                byte G = sourceReader.ReadByte();
                byte B = sourceReader.ReadByte();
                destination.WriteByte(B);                     // B
                destination.WriteByte(G);                     // G
                destination.WriteByte(R);                     // R
                destination.WriteByte(A);                     // A
            }
        }
示例#7
0
 public static void ExportDDSHeader(byte[] buffer, int offset, DDSConvertParameters @params)
 {
     using (MemoryStream stream = new MemoryStream(buffer))
     {
         stream.Position = offset;
         ExportDDSHeader(stream, @params);
     }
 }
示例#8
0
        public static long GetDecompressedSize(DDSConvertParameters @params)
        {
            int  width       = @params.Width;
            int  height      = @params.Height;
            int  depth       = @params.BitMapDepth;
            int  bpp         = GetRGBABytesPerPixel(@params);
            int  bpc         = GetBytesPerColor(@params);
            int  bps         = width * bpp * bpc;
            long sizeOfPlane = bps * height;

            return(depth * sizeOfPlane + height * bps + width * bpp);
        }
示例#9
0
        private static int GetBytesPerPixel(DDSConvertParameters @params)
        {
            if (@params.PixelFormatFlags.IsFourCC())
            {
                switch (@params.FourCC)
                {
                case DDSFourCCType.DXT1:
                case DDSFourCCType.DXT2:
                case DDSFourCCType.DXT3:
                case DDSFourCCType.DXT4:
                case DDSFourCCType.DXT5:
                    return(4);

                case DDSFourCCType.ATI1:
                    return(1);

                case DDSFourCCType.ATI2:
                case DDSFourCCType.RXGB:
                    return(3);

                case DDSFourCCType.oNULL:
                    return(2);

                case DDSFourCCType.DollarNULL:
                case DDSFourCCType.qNULL:
                case DDSFourCCType.sNULL:
                    return(8);

                case DDSFourCCType.tNULL:
                    return(16);

                case DDSFourCCType.pNULL:
                case DDSFourCCType.rNULL:
                    return(4);

                default:
                    throw new Exception($"Unsupported CCType {@params.FourCC}");
                }
            }
            else
            {
                return(@params.RGBBitCount / 8);
            }
        }
示例#10
0
 public static void ExportDDS(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
 {
     if (IsRGBA32(@params))
     {
         ExportRGBA32ToDDS(sourceReader, destination, @params);
     }
     else if (IsARGB32(@params))
     {
         ExportARGB32ToDDS(sourceReader, destination, @params);
     }
     else if (IsRGBA16(@params))
     {
         ExportRGBA16ToDDS(sourceReader, destination, @params);
     }
     else if (IsAlpha8(@params))
     {
         ExportAlpha8ToDDS(sourceReader, destination, @params);
     }
     else if (IsR8(@params))
     {
         ExportR8ToDDS(sourceReader, destination, @params);
     }
     else if (IsR16(@params))
     {
         ExportR16ToDDS(sourceReader, destination, @params);
     }
     else if (IsRG16(@params))
     {
         ExportRG16ToDDS(sourceReader, destination, @params);
     }
     else
     {
         ExportDDSHeader(destination, @params);
         for (int i = 0; i < @params.DataLength; i += 2)
         {
             ushort value  = sourceReader.ReadUInt16();
             byte   value0 = unchecked ((byte)(value >> 0));
             byte   value1 = unchecked ((byte)(value >> 8));
             destination.WriteByte(value0);
             destination.WriteByte(value1);
         }
     }
 }
示例#11
0
        private static int GetRGBABytesPerPixel(DDSConvertParameters @params)
        {
            if (@params.PixelFormatFlags.IsFourCC())
            {
                switch (@params.FourCC)
                {
                case DDSFourCCType.DXT1:
                case DDSFourCCType.DXT2:
                case DDSFourCCType.DXT3:
                case DDSFourCCType.DXT4:
                case DDSFourCCType.DXT5:
                    return(4);

                default:
                    throw new Exception($"Unsupported CCType {@params.FourCC}");
                }
            }
            else
            {
                return(4);
            }
        }
示例#12
0
        private static void ExportRGBA16ToDDS(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
        {
            DDSConvertParameters bgraParams = new DDSConvertParameters();

            @params.CopyTo(bgraParams);
            bgraParams.RBitMask = 0xF00;
            bgraParams.BBitMask = 0xF;
            ExportDDSHeader(destination, bgraParams);

            long pixelCount = @params.BitMapDepth * @params.Height * @params.Width;

            for (int i = 0; i < pixelCount; i++)
            {
                int pixel = sourceReader.ReadUInt16();
                int c1    = (0x00F0 & pixel) >> 4;                  // B
                int c2    = (0x0F00 & pixel) >> 4;                  // G
                destination.WriteByte((byte)(c1 | c2));
                c1 = (0xF000 & pixel) >> 12;                        // R
                c2 = (0x000F & pixel) << 4;                         // A
                destination.WriteByte((byte)(c1 | c2));
            }
        }
示例#13
0
        public static void DecompressDXT5(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
        {
            int  depth       = @params.BitMapDepth;
            int  width       = @params.Width;
            int  height      = @params.Height;
            int  bpp         = GetRGBABytesPerPixel(@params);
            int  bpc         = GetBytesPerColor(@params);
            int  bps         = width * bpp * bpc;
            long sizeOfPlane = bps * height;

            Color8888[] colors    = new Color8888[4];
            ushort[]    alphas    = new ushort[8];
            byte[]      alphaMask = new byte[6];

            long position = destination.Position;

            for (int z = 0; z < depth; z++)
            {
                // mirror Y
                for (int y = height - 1; y >= 0; y -= 4)
                {
                    for (int x = 0; x < width; x += 4)
                    {
                        ushort alpha = sourceReader.ReadUInt16();
                        alphas[0] = unchecked ((byte)(alpha >> 0));
                        alphas[1] = unchecked ((byte)(alpha >> 8));

                        ushort alphaMask0 = sourceReader.ReadUInt16();
                        ushort alphaMask1 = sourceReader.ReadUInt16();
                        ushort alphaMask2 = sourceReader.ReadUInt16();
                        alphaMask[0] = unchecked ((byte)(alphaMask0 >> 0));
                        alphaMask[1] = unchecked ((byte)(alphaMask0 >> 8));
                        alphaMask[2] = unchecked ((byte)(alphaMask1 >> 0));
                        alphaMask[3] = unchecked ((byte)(alphaMask1 >> 8));
                        alphaMask[4] = unchecked ((byte)(alphaMask2 >> 0));
                        alphaMask[5] = unchecked ((byte)(alphaMask2 >> 8));

                        colors[0] = DxtcRead2bColor(sourceReader);
                        colors[1] = DxtcRead2bColor(sourceReader);

                        uint bitMask0 = sourceReader.ReadUInt16();
                        uint bitMask1 = sourceReader.ReadUInt16();
                        uint bitMask  = (bitMask0 << 0) | (bitMask1 << 16);

                        // Four-color block: derive the other two colors.
                        // 00 = color_0, 01 = color_1, 10 = color_2, 11	= color_3
                        // These 2-bit codes correspond to the 2-bit fields
                        // stored in the 64-bit block.
                        colors[2].Blue  = unchecked ((byte)((2 * colors[0].Blue + colors[1].Blue + 1) / 3));
                        colors[2].Green = unchecked ((byte)((2 * colors[0].Green + colors[1].Green + 1) / 3));
                        colors[2].Red   = unchecked ((byte)((2 * colors[0].Red + colors[1].Red + 1) / 3));

                        colors[3].Blue  = unchecked ((byte)((colors[0].Blue + 2 * colors[1].Blue + 1) / 3));
                        colors[3].Green = unchecked ((byte)((colors[0].Green + 2 * colors[1].Green + 1) / 3));
                        colors[3].Red   = unchecked ((byte)((colors[0].Red + 2 * colors[1].Red + 1) / 3));

                        int bitIndex = 0;
                        for (int ly = 0; ly < 4; ly++)
                        {
                            for (int lx = 0; lx < 4; lx++, bitIndex++)
                            {
                                int       colorIndex = (int)((bitMask & (0x03 << bitIndex * 2)) >> bitIndex * 2);
                                Color8888 col        = colors[colorIndex];
                                // only put pixels out < width or height
                                if ((x + lx) < width && (y - ly) < height && (y - ly) >= 0)
                                {
                                    // mirror Y
                                    long offset = z * sizeOfPlane + (y - ly) * bps + (x + lx) * bpp;
                                    destination.Position = position + offset;

                                    destination.WriteByte(col.Red);
                                    destination.WriteByte(col.Green);
                                    destination.WriteByte(col.Blue);
                                }
                            }
                        }

                        // 8-alpha or 6-alpha block?
                        if (alphas[0] > alphas[1])
                        {
                            // 8-alpha block:  derive the other six alphas.
                            // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
                            alphas[2] = unchecked ((ushort)((6 * alphas[0] + 1 * alphas[1] + 3) / 7));                            // bit code 010
                            alphas[3] = unchecked ((ushort)((5 * alphas[0] + 2 * alphas[1] + 3) / 7));                            // bit code 011
                            alphas[4] = unchecked ((ushort)((4 * alphas[0] + 3 * alphas[1] + 3) / 7));                            // bit code 100
                            alphas[5] = unchecked ((ushort)((3 * alphas[0] + 4 * alphas[1] + 3) / 7));                            // bit code 101
                            alphas[6] = unchecked ((ushort)((2 * alphas[0] + 5 * alphas[1] + 3) / 7));                            // bit code 110
                            alphas[7] = unchecked ((ushort)((1 * alphas[0] + 6 * alphas[1] + 3) / 7));                            // bit code 111
                        }
                        else
                        {
                            // 6-alpha block.
                            // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
                            alphas[2] = unchecked ((ushort)((4 * alphas[0] + 1 * alphas[1] + 2) / 5)); // Bit code 010
                            alphas[3] = unchecked ((ushort)((3 * alphas[0] + 2 * alphas[1] + 2) / 5)); // Bit code 011
                            alphas[4] = unchecked ((ushort)((2 * alphas[0] + 3 * alphas[1] + 2) / 5)); // Bit code 100
                            alphas[5] = unchecked ((ushort)((1 * alphas[0] + 4 * alphas[1] + 2) / 5)); // Bit code 101
                            alphas[6] = 0x00;                                                          // Bit code 110
                            alphas[7] = 0xFF;                                                          // Bit code 111
                        }

                        // Note: Have to separate the next two loops,
                        // it operates on a 6-byte system.

                        // First three bytes
                        //uint bits = (uint)(alphamask[0]);
                        uint bits = unchecked ((uint)((alphaMask[0]) | (alphaMask[1] << 8) | (alphaMask[2] << 16)));
                        for (int ly = 0; ly < 2; ly++)
                        {
                            for (int lx = 0; lx < 4; lx++, bits >>= 3)
                            {
                                // only put pixels out < width or height
                                if ((x + lx) < width && (y - ly) < height && (y - ly) >= 0)
                                {
                                    byte alphaValue = unchecked ((byte)alphas[bits & 0x07]);
                                    // mirror Y
                                    long offset = z * sizeOfPlane + (y - ly) * bps + (x + lx) * bpp + 3;
                                    destination.Position = position + offset;
                                    destination.WriteByte(alphaValue);
                                }
                            }
                        }

                        // Last three bytes
                        //bits = (uint)(alphamask[3]);
                        bits = unchecked ((uint)((alphaMask[3]) | (alphaMask[4] << 8) | (alphaMask[5] << 16)));
                        for (int ly = 2; ly < 4; ly++)
                        {
                            for (int lx = 0; lx < 4; lx++, bits >>= 3)
                            {
                                // only put pixels out < width or height
                                if ((x + lx) < width && (y - ly) < height && (y - ly) >= 0)
                                {
                                    byte alphaValue = unchecked ((byte)alphas[bits & 0x07]);
                                    // mirror Y
                                    long offset = z * sizeOfPlane + (y - ly) * bps + (x + lx) * bpp + 3;
                                    destination.Position = position + offset;
                                    destination.WriteByte(alphaValue);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#14
0
 public static void DecompressRGBA(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
 {
     DecompressRGBA(sourceReader, destination, @params, true);
 }
示例#15
0
 private static bool IsRG16(DDSConvertParameters @params)
 {
     return(@params.RBitMask == 0xFF && @params.GBitMask == 0xFF00 && @params.BBitMask == 0 && @params.ABitMask == 0);
 }
示例#16
0
 private static bool IsAlpha8(DDSConvertParameters @params)
 {
     return(@params.RBitMask == 0 && @params.GBitMask == 0 && @params.BBitMask == 0 && @params.ABitMask == 0xFF);
 }
示例#17
0
        private static void DecompressRGBA(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params, bool isAlpha)
        {
            int  depth       = @params.BitMapDepth;
            int  width       = @params.Width;
            int  height      = @params.Height;
            int  bpp         = GetRGBABytesPerPixel(@params);
            int  bpc         = GetBytesPerColor(@params);
            int  bps         = width * bpp * bpc;
            long sizeOfPlane = bps * height;

            int       pixelSize = (@params.RGBBitCount + 7) / 8;
            ColorMask rMask     = ComputeMaskParams(@params.RBitMask);
            ColorMask gMask     = ComputeMaskParams(@params.GBitMask);
            ColorMask bMask     = ComputeMaskParams(@params.BBitMask);
            ColorMask aMask     = ComputeMaskParams(@params.ABitMask);

            long position = destination.Position;

            for (int z = 0; z < depth; z++)
            {
                // mirror Y
                for (int j = height - 1; j >= 0; j--)
                {
                    long offset = z * sizeOfPlane + j * bps;
                    destination.Position = position + offset;

                    for (int i = 0; i < width; i++)
                    {
                        uint pixel      = ReadPixel(sourceReader, pixelSize);
                        uint pixelColor = pixel & @params.RBitMask;
                        byte red        = unchecked ((byte)(((pixelColor >> rMask.Shift1) * rMask.Mult) >> rMask.Shift2));
                        pixelColor = pixel & @params.GBitMask;
                        byte green = unchecked ((byte)(((pixelColor >> gMask.Shift1) * gMask.Mult) >> gMask.Shift2));
                        pixelColor = pixel & @params.BBitMask;
                        byte blue = unchecked ((byte)(((pixelColor >> bMask.Shift1) * bMask.Mult) >> bMask.Shift2));

                        byte alpha = 0xFF;
                        if (isAlpha)
                        {
                            pixelColor = pixel & @params.ABitMask;
                            alpha      = unchecked ((byte)(((pixelColor >> aMask.Shift1) * aMask.Mult) >> aMask.Shift2));
                        }

                        destination.WriteByte(blue);
                        destination.WriteByte(green);
                        destination.WriteByte(red);
                        destination.WriteByte(alpha);
                    }
                }
            }
        }
示例#18
0
        public static void DecompressDXT1(BinaryReader sourceReader, Stream destination, DDSConvertParameters @params)
        {
            int  depth       = @params.BitMapDepth;
            int  width       = @params.Width;
            int  height      = @params.Height;
            int  bpp         = GetRGBABytesPerPixel(@params);
            int  bpc         = GetBytesPerColor(@params);
            int  bps         = width * bpp * bpc;
            long sizeOfPlane = bps * height;

            Color8888[] colors = new Color8888[4];

            long position = destination.Position;

            for (int z = 0; z < depth; z++)
            {
                // mirror Y
                for (int y = height - 1; y >= 0; y -= 4)
                {
                    for (int x = 0; x < width; x += 4)
                    {
                        ushort color0 = sourceReader.ReadUInt16();
                        ushort color1 = sourceReader.ReadUInt16();

                        uint bitMask0 = sourceReader.ReadUInt16();
                        uint bitMask1 = sourceReader.ReadUInt16();
                        uint bitMask  = (bitMask0 << 0) | (bitMask1 << 16);

                        colors[0] = DxtcRead3bColor(color0);
                        colors[1] = DxtcRead3bColor(color1);

                        if (color0 > color1)
                        {
                            // Four-color block: derive the other two colors.
                            // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
                            // These 2-bit codes correspond to the 2-bit fields
                            // stored in the 64-bit block.
                            colors[2].Blue  = unchecked ((byte)((2 * colors[0].Blue + colors[1].Blue + 1) / 3));
                            colors[2].Green = unchecked ((byte)((2 * colors[0].Green + colors[1].Green + 1) / 3));
                            colors[2].Red   = unchecked ((byte)((2 * colors[0].Red + colors[1].Red + 1) / 3));

                            colors[2].Alpha = 0xFF;
                            colors[3].Alpha = 0xFF;
                        }
                        else
                        {
                            // Three-color block: derive the other color.
                            // 00 = color_0,  01 = color_1,  10 = color_2,
                            // 11 = transparent.
                            // These 2-bit codes correspond to the 2-bit fields
                            // stored in the 64-bit block.
                            colors[2].Blue  = unchecked ((byte)((colors[0].Blue + colors[1].Blue) / 2));
                            colors[2].Green = unchecked ((byte)((colors[0].Green + colors[1].Green) / 2));
                            colors[2].Red   = unchecked ((byte)((colors[0].Red + colors[1].Red) / 2));

                            colors[2].Alpha = 0xFF;
                            colors[3].Alpha = 0x0;
                        }

                        colors[3].Blue  = unchecked ((byte)((colors[0].Blue + 2 * colors[1].Blue + 1) / 3));
                        colors[3].Green = unchecked ((byte)((colors[0].Green + 2 * colors[1].Green + 1) / 3));
                        colors[3].Red   = unchecked ((byte)((colors[0].Red + 2 * colors[1].Red + 1) / 3));

                        int bitIndex = 0;
                        for (int ly = 0; ly < 4; ly++)
                        {
                            for (int lx = 0; lx < 4; lx++, bitIndex++)
                            {
                                int       colorIndex = unchecked ((int)((bitMask & (3 << bitIndex * 2)) >> bitIndex * 2));
                                Color8888 color      = colors[colorIndex];
                                if ((x + lx) < width && (y - ly) < height && (y - ly) >= 0)
                                {
                                    // mirror Y
                                    long offset = z * sizeOfPlane + (y - ly) * bps + (x + lx) * bpp;
                                    destination.Position = position + offset;

                                    destination.WriteByte(color.Red);
                                    destination.WriteByte(color.Green);
                                    destination.WriteByte(color.Blue);
                                    destination.WriteByte(color.Alpha);
                                }
                            }
                        }
                    }
                }
            }
        }