Ejemplo n.º 1
0
        /// <summary>
        /// Decodes DXT data to ARGB.
        /// </summary>
        private static byte[] DecodeDXTToARGB(int DXTVersion, byte[] compressedData, uint width, uint height, DDSPixelFormat pixelFormat, uint mipmapCount)
        {
            bool alphaFlag     = Utils.ContainsBitFlags(pixelFormat.flags, (uint)DDSPixelFormatFlags.AlphaPixels);
            bool containsAlpha = alphaFlag || ((pixelFormat.RGBBitCount == 32) && (pixelFormat.ABitMask != 0));

            var reader = new UnityBinaryReader(new MemoryStream(compressedData));
            var argb   = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)width, (int)height, 4)];

            int mipMapWidth   = (int)width;
            int mipMapHeight  = (int)height;
            int baseARGBIndex = 0;

            for (int mipMapIndex = 0; mipMapIndex < mipmapCount; mipMapIndex++)
            {
                for (int rowIndex = 0; rowIndex < mipMapHeight; rowIndex += 4)
                {
                    for (int columnIndex = 0; columnIndex < mipMapWidth; columnIndex += 4)
                    {
                        Color32[] colors = null;

                        // Doing a switch instead of using a delegate for speed.
                        switch (DXTVersion)
                        {
                        case 1:
                            colors = DecodeDXT1TexelBlock(reader, containsAlpha);
                            break;

                        case 3:
                            colors = DecodeDXT3TexelBlock(reader);
                            break;

                        case 5:
                            colors = DecodeDXT5TexelBlock(reader);
                            break;

                        default:
                            throw new NotImplementedException("Tried decoding a DDS file using an unsupported DXT format: DXT" + DXTVersion.ToString());
                        }

                        CopyDecodedTexelBlock(colors, argb, baseARGBIndex, rowIndex, columnIndex, mipMapWidth, mipMapHeight);
                    }
                }

                baseARGBIndex += (mipMapWidth * mipMapHeight * 4);

                mipMapWidth  /= 2;
                mipMapHeight /= 2;
            }

            return(argb);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Decodes DXT data to ARGB.
        /// </summary>
        static byte[] DecodeDXTToARGB(int DXTVersion, byte[] compressedData, uint width, uint height, DDSPixelFormat pixelFormat, uint mipmapCount)
        {
            var alphaFlag     = Utils.ContainsBitFlags((int)pixelFormat.dwFlags, (int)DDSPixelFormats.AlphaPixels);
            var containsAlpha = alphaFlag || (pixelFormat.dwRGBBitCount == 32 && pixelFormat.dwABitMask != 0);

            using (var r = new BinaryFileReader(new MemoryStream(compressedData)))
            {
                var argb          = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)width, (int)height, 4)];
                var mipMapWidth   = (int)width;
                var mipMapHeight  = (int)height;
                var baseARGBIndex = 0;
                for (var mipMapIndex = 0; mipMapIndex < mipmapCount; mipMapIndex++)
                {
                    for (var rowIndex = 0; rowIndex < mipMapHeight; rowIndex += 4)
                    {
                        for (var columnIndex = 0; columnIndex < mipMapWidth; columnIndex += 4)
                        {
                            if (r.Position == r.BaseStream.Length)
                            {
                                return(argb);
                            }
                            Color32[] colors = null;
                            switch (DXTVersion) // Doing a switch instead of using a delegate for speed.
                            {
                            case 1: colors = DecodeDXT1TexelBlock(r, containsAlpha); break;

                            case 3: colors = DecodeDXT3TexelBlock(r); break;

                            case 5: colors = DecodeDXT5TexelBlock(r); break;

                            default: throw new NotImplementedException($"Tried decoding a DDS file using an unsupported DXT format: DXT {DXTVersion}");
                            }
                            CopyDecodedTexelBlock(colors, argb, baseARGBIndex, rowIndex, columnIndex, mipMapWidth, mipMapHeight);
                        }
                    }
                    baseARGBIndex += mipMapWidth * mipMapHeight * 4;
                    mipMapWidth   /= 2;
                    mipMapHeight  /= 2;
                }
                return(argb);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Extracts a DDS file's texture format and pixel data.
        /// </summary>
        static void ExtractDDSTextureFormatAndData(DDSHeader header, GenericReader r, out bool hasMipmaps, out uint DDSMipmapLevelCount, out TextureFormat textureFormat, out int bytesPerPixel, out byte[] textureData)
        {
            hasMipmaps = Utils.ContainsBitFlags((int)header.dwCaps, (int)DDSCaps.Mipmap);
            // Non-mipmapped textures still have one mipmap level: the texture itself.
            DDSMipmapLevelCount = hasMipmaps ? header.dwMipMapCount : 1;
            // If the DDS file contains uncompressed data.
            if (Utils.ContainsBitFlags((int)header.ddspf.dwFlags, (int)DDSPixelFormats.RGB))
            {
                // some permutation of RGB
                if (!Utils.ContainsBitFlags((int)header.ddspf.dwFlags, (int)DDSPixelFormats.AlphaPixels))
                {
                    throw new NotImplementedException("Unsupported DDS file pixel format.");
                }
                // some permutation of RGBA
                else
                {
                    // There should be 32 bits per pixel.
                    if (header.ddspf.dwRGBBitCount != 32)
                    {
                        throw new FileFormatException("Invalid DDS file pixel format.");
                    }
                    // BGRA32
                    if (header.ddspf.dwBBitMask == 0x000000FF && header.ddspf.dwGBitMask == 0x0000FF00 && header.ddspf.dwRBitMask == 0x00FF0000 && header.ddspf.dwABitMask == 0xFF000000)
                    {
                        textureFormat = TextureFormat.BGRA32;
                        bytesPerPixel = 4;
                    }
                    // ARGB32
                    else if (header.ddspf.dwABitMask == 0x000000FF && header.ddspf.dwRBitMask == 0x0000FF00 && header.ddspf.dwGBitMask == 0x00FF0000 && header.ddspf.dwBBitMask == 0xFF000000)
                    {
                        textureFormat = TextureFormat.ARGB32;
                        bytesPerPixel = 4;
                    }
                    else
                    {
                        throw new NotImplementedException("Unsupported DDS file pixel format.");
                    }

                    if (!hasMipmaps)
                    {
                        textureData = new byte[header.dwPitchOrLinearSize * header.dwHeight];
                    }
                    // Create a data buffer to hold all mipmap levels down to 1x1.
                    else
                    {
                        textureData = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)header.dwWidth, (int)header.dwHeight, bytesPerPixel)];
                    }
                    r.ReadRestOfBytes(textureData, 0);
                }
            }
            else if ("DXT1".EqualsASCIIBytes(header.ddspf.dwFourCC))
            {
                textureFormat = TextureFormat.ARGB32;
                bytesPerPixel = 4;
                var compressedTextureData = r.ReadRestOfBytes();
                textureData = DecodeDXT1ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.ddspf, DDSMipmapLevelCount);
            }
            else if ("DXT3".EqualsASCIIBytes(header.ddspf.dwFourCC))
            {
                textureFormat = TextureFormat.ARGB32;
                bytesPerPixel = 4;
                var compressedTextureData = r.ReadRestOfBytes();
                textureData = DecodeDXT3ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.ddspf, DDSMipmapLevelCount);
            }
            else if ("DXT5".EqualsASCIIBytes(header.ddspf.dwFourCC))
            {
                textureFormat = TextureFormat.ARGB32;
                bytesPerPixel = 4;
                var compressedTextureData = r.ReadRestOfBytes();
                textureData = DecodeDXT5ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.ddspf, DDSMipmapLevelCount);
            }
            else
            {
                throw new NotImplementedException("Unsupported DDS file pixel format.");
            }
        }