Пример #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(Stream destination, Stream source, 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);

            using (BinaryReader binReader = new BinaryReader(source, Encoding.UTF8, true))
            {
                long pixelCount = @params.BitMapDepth * @params.Height * @params.Width;
                for (int i = 0; i < pixelCount; i++)
                {
                    ushort pixel = binReader.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
        private static void ExportRGBA32ToDDS(Stream destination, Stream source, DDSConvertParameters @params)
        {
            DDSConvertParameters bgraParams = new DDSConvertParameters();

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

            using (BinaryReader binReader = new BinaryReader(source, Encoding.UTF8, true))
            {
                long pixelCount = @params.BitMapDepth * @params.Height * @params.Width;
                for (int i = 0; i < pixelCount; i++)
                {
                    byte R = binReader.ReadByte();
                    byte G = binReader.ReadByte();
                    byte B = binReader.ReadByte();
                    byte A = binReader.ReadByte();
                    destination.WriteByte(B);                         // B
                    destination.WriteByte(G);                         // G
                    destination.WriteByte(R);                         // R
                    destination.WriteByte(A);                         // A
                }
            }
        }
Пример #4
0
 public static void ExportBitmap(byte[] buffer, int offset, Stream source, DDSConvertParameters @params)
 {
     using (MemoryStream stream = new MemoryStream(buffer))
     {
         stream.Position = offset;
         ExportBitmap(stream, source, @params);
     }
 }
Пример #5
0
 public static void ExportDDSHeader(byte[] buffer, int offset, DDSConvertParameters @params)
 {
     using (MemoryStream stream = new MemoryStream(buffer))
     {
         stream.Position = offset;
         ExportDDSHeader(stream, @params);
     }
 }
Пример #6
0
        private static void DecompressRGBA(Stream destination, Stream source, 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;

            using (BinaryReader reader = new BinaryReader(source, Encoding.Default, true))
            {
                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(reader, 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);
                        }
                    }
                }
            }
        }
Пример #7
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);
        }
Пример #8
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);
            }
        }
Пример #9
0
        public static void ExportBitmap(Stream destination, Stream source, DDSConvertParameters @params)
        {
            int width  = @params.Width;
            int height = @params.Height;
            int size   = width * height * 4;

            byte[] buffer = new byte[size];
            using (MemoryStream memStream = new MemoryStream(buffer))
            {
                ExportBitmapData(memStream, source, @params);
                Bitmap     bitmap  = new Bitmap(width, height, PixelFormat.Format32bppArgb);
                Rectangle  rect    = new Rectangle(0, 0, width, height);
                BitmapData bitData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
                IntPtr     pointer = bitData.Scan0;
                Marshal.Copy(buffer, 0, pointer, size);
                bitmap.UnlockBits(bitData);

                bitmap.Save(destination, ImageFormat.Png);
            }
        }
Пример #10
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);
            }
        }
Пример #11
0
        private static void ExportBitmapData(Stream destination, Stream source, DDSConvertParameters @params)
        {
            if (@params.PixelFormatFlags.IsFourCC())
            {
                switch (@params.FourCC)
                {
                case DDSFourCCType.DXT1:
                    DDSDecompressor.DecompressDXT1(destination, source, @params);
                    break;

                case DDSFourCCType.DXT5:
                    DDSDecompressor.DecompressDXT5(destination, source, @params);
                    break;

                default:
                    throw new NotImplementedException(@params.FourCC.ToString());
                }
            }
            else
            {
                if (@params.PixelFormatFlags.IsLuminace())
                {
                    throw new NotSupportedException("Luminace isn't supported");
                }
                else
                {
                    if (@params.PixelFormatFlags.IsAlphaPixels())
                    {
                        DDSDecompressor.DecompressRGBA(destination, source, @params);
                    }
                    else
                    {
                        DDSDecompressor.DecompressRGB(destination, source, @params);
                    }
                }
            }
        }
Пример #12
0
 public static void ExportDDS(Stream destination, Stream source, DDSConvertParameters @params)
 {
     if (IsRGBA32(@params))
     {
         ExportRGBA32ToDDS(destination, source, @params);
     }
     else if (IsARGB32(@params))
     {
         ExportARGB32ToDDS(destination, source, @params);
     }
     else if (IsRGBA16(@params))
     {
         ExportRGBA16ToDDS(destination, source, @params);
     }
     else if (IsAlpha8(@params))
     {
         ExportAlpha8ToDDS(destination, source, @params);
     }
     else if (IsR8(@params))
     {
         ExportR8ToDDS(destination, source, @params);
     }
     else if (IsR16(@params))
     {
         ExportR16ToDDS(destination, source, @params);
     }
     else if (IsRG16(@params))
     {
         ExportRG16ToDDS(destination, source, @params);
     }
     else
     {
         ExportDDSHeader(destination, @params);
         source.CopyStream(destination, @params.DataLength);
     }
 }
Пример #13
0
        private static void ExportRGBA16ToDDS(Stream destination, Stream source, DDSConvertParameters @params)
        {
            DDSConvertParameters bgraParams = new DDSConvertParameters();

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

            using (BinaryReader binReader = new BinaryReader(source, Encoding.UTF8, true))
            {
                long pixelCount = @params.BitMapDepth * @params.Height * @params.Width;
                for (int i = 0; i < pixelCount; i++)
                {
                    int pixel = binReader.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));
                }
            }
        }
Пример #14
0
        public static void DecompressDXT1(Stream destination, Stream source, 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;

            using (BinaryReader reader = new BinaryReader(source, Encoding.Default, true))
            {
                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  = reader.ReadUInt16();
                            ushort color1  = reader.ReadUInt16();
                            uint   bitMask = reader.ReadUInt32();

                            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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #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
        public static void DecompressDXT5(Stream destination, Stream source, 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;

            using (BinaryReader reader = new BinaryReader(source, Encoding.Default, true))
            {
                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)
                        {
                            alphas[0] = reader.ReadByte();
                            alphas[1] = reader.ReadByte();
                            reader.Read(alphaMask, 0, alphaMask.Length);

                            colors[0] = DxtcRead2bColor(reader);
                            colors[1] = DxtcRead2bColor(reader);
                            uint bitmask = reader.ReadUInt32();

                            // 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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #18
0
 public static void DecompressRGBA(Stream destination, Stream source, DDSConvertParameters @params)
 {
     DecompressRGBA(destination, source, @params, true);
 }