public static void ExportDDS(Texture2D texture, Stream destination, Stream source, long length)
        {
            DDSContainerParameters @params = new DDSContainerParameters()
            {
                DataLength          = length,
                MipMapCount         = texture.MipCount,
                Width               = texture.Width,
                Height              = texture.Height,
                IsPitchOrLinearSize = texture.DDSIsPitchOrLinearSize(),
                PixelFormatFlags    = texture.DDSPixelFormatFlags(),
                FourCC              = (DDSFourCCType)texture.DDSFourCC(),
                RGBBitCount         = texture.DDSRGBBitCount(),
                RBitMask            = texture.DDSRBitMask(),
                GBitMask            = texture.DDSGBitMask(),
                BBitMask            = texture.DDSBBitMask(),
                ABitMask            = texture.DDSABitMask(),
                Caps = texture.DDSCaps(),
            };

            EndianType endianess = Texture2D.IsSwapBytes(texture.File.Platform, texture.TextureFormat) ? EndianType.BigEndian : EndianType.LittleEndian;

            using (EndianReader sourceReader = new EndianReader(source, endianess))
            {
                DDSContainer.ExportDDS(sourceReader, destination, @params);
            }
        }
Exemple #2
0
 public static void DecompressRGB(Stream source, Stream destination, DDSContainerParameters @params)
 {
     using (BinaryReader reader = new BinaryReader(source))
     {
         DecompressRGBA(reader, destination, @params, false);
     }
 }
Exemple #3
0
 public static void DecompressDXT1(Stream source, Stream destination, DDSContainerParameters @params)
 {
     using (BinaryReader sourceReader = new BinaryReader(source))
     {
         DecompressDXT1(sourceReader, destination, @params);
     }
 }
Exemple #4
0
        public static long GetDecompressedSize(DDSContainerParameters @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);
        }
 public void CopyTo(DDSContainerParameters dest)
 {
     dest.DataLength          = DataLength;
     dest.MipMapCount         = MipMapCount;
     dest.Width               = Width;
     dest.Height              = Height;
     dest.IsPitchOrLinearSize = IsPitchOrLinearSize;
     dest.PixelFormatFlags    = PixelFormatFlags;
     dest.FourCC              = FourCC;
     dest.RGBBitCount         = RGBBitCount;
     dest.RBitMask            = RBitMask;
     dest.GBitMask            = GBitMask;
     dest.BBitMask            = BBitMask;
     dest.ABitMask            = ABitMask;
     dest.Caps = Caps;
 }
Exemple #6
0
        private static int GetBytesPerPixel(DDSContainerParameters @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);
            }
        }
Exemple #7
0
        public static Bitmap DDSTextureToBitmap(Texture2D texture, byte[] data)
        {
            DDSContainerParameters @params = new DDSContainerParameters()
            {
                DataLength          = data.LongLength,
                MipMapCount         = texture.MipCount,
                Width               = texture.Width,
                Height              = texture.Height,
                IsPitchOrLinearSize = texture.DDSIsPitchOrLinearSize(),
                PixelFormatFlags    = texture.DDSPixelFormatFlags(),
                FourCC              = (DDSFourCCType)texture.DDSFourCC(),
                RGBBitCount         = texture.DDSRGBBitCount(),
                RBitMask            = texture.DDSRBitMask(),
                GBitMask            = texture.DDSGBitMask(),
                BBitMask            = texture.DDSBBitMask(),
                ABitMask            = texture.DDSABitMask(),
                Caps = texture.DDSCaps(),
            };

            int width  = @params.Width;
            int height = @params.Height;
            int size   = width * height * 4;

            byte[] buffer = new byte[size];
            using (MemoryStream destination = new MemoryStream(buffer))
            {
                using (MemoryStream source = new MemoryStream(data))
                {
                    EndianType endianess = Texture2D.IsSwapBytes(texture.File.Platform, texture.TextureFormat) ? EndianType.BigEndian : EndianType.LittleEndian;
                    using (EndianReader sourceReader = new EndianReader(source, endianess))
                    {
                        DecompressDDS(sourceReader, destination, @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);
                return(bitmap);
            }
        }
        public static DirectBitmap DDSTextureToBitmap(Texture2D texture, byte[] data)
        {
            DDSContainerParameters @params = new DDSContainerParameters()
            {
                DataLength          = data.LongLength,
                MipMapCount         = texture.MipCount,
                Width               = texture.Width,
                Height              = texture.Height,
                IsPitchOrLinearSize = texture.DDSIsPitchOrLinearSize(),
                PixelFormatFlags    = texture.DDSPixelFormatFlags(),
                FourCC              = (DDSFourCCType)texture.DDSFourCC(),
                RGBBitCount         = texture.DDSRGBBitCount(),
                RBitMask            = texture.DDSRBitMask(),
                GBitMask            = texture.DDSGBitMask(),
                BBitMask            = texture.DDSBBitMask(),
                ABitMask            = texture.DDSABitMask(),
                Caps = texture.DDSCaps(),
            };

            int          width  = @params.Width;
            int          height = @params.Height;
            DirectBitmap bitmap = new DirectBitmap(width, height);

            try
            {
                using (MemoryStream destination = new MemoryStream(bitmap.Bits))
                {
                    using (MemoryStream source = new MemoryStream(data))
                    {
                        using (EndianReader sourceReader = new EndianReader(source))
                        {
                            DecompressDDS(sourceReader, destination, @params);
                        }
                    }
                    return(bitmap);
                }
            }
            catch
            {
                bitmap.Dispose();
                throw;
            }
        }
        private static void DecompressDDS(BinaryReader reader, Stream destination, DDSContainerParameters @params)
        {
            if (@params.PixelFormatFlags.IsFourCC())
            {
                switch (@params.FourCC)
                {
                case DDSFourCCType.DXT1:
                    DDSDecompressor.DecompressDXT1(reader, destination, @params);
                    break;

                case DDSFourCCType.DXT3:
                    DDSDecompressor.DecompressDXT3(reader, destination, @params);
                    break;

                case DDSFourCCType.DXT5:
                    DDSDecompressor.DecompressDXT5(reader, destination, @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(reader, destination, @params);
                    }
                    else
                    {
                        DDSDecompressor.DecompressRGB(reader, destination, @params);
                    }
                }
            }
        }
Exemple #10
0
        private static int GetRGBABytesPerPixel(DDSContainerParameters @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);
            }
        }
Exemple #11
0
        public static void DecompressDXT1(BinaryReader sourceReader, Stream destination, DDSContainerParameters @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);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #12
0
        private static void DecompressRGBA(BinaryReader sourceReader, Stream destination, DDSContainerParameters @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);
                    }
                }
            }
        }
Exemple #13
0
 public static void DecompressRGBA(BinaryReader sourceReader, Stream destination, DDSContainerParameters @params)
 {
     DecompressRGBA(sourceReader, destination, @params, true);
 }
Exemple #14
0
        public static void DecompressDXT5(BinaryReader sourceReader, Stream destination, DDSContainerParameters @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);
                                }
                            }
                        }
                    }
                }
            }
        }