Example #1
0
        private static void DecodeTexture(FTexture2DMipMap mip, EPixelFormat format, out byte[] data, out SKColorType colorType)
        {
            switch (format)
            {
            case EPixelFormat.PF_DXT1:
                data      = DXTDecoder.DXT1(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_DXT5:
                data      = DXTDecoder.DXT5(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ASTC_8x8:
                data = ASTCDecoder.RGBA8888(
                    mip.Data.Data,
                    FormatHelper.GetBlockWidth(format),
                    FormatHelper.GetBlockHeight(format),
                    FormatHelper.GetBlockDepth(format),
                    mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_BC4:
                data      = BCDecoder.BC4(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC5:
                data      = BCDecoder.BC5(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC6H:
                // BC6H doesn't work no matter the pixel format, the closest we can get is either
                // Rgb565 DETEX_PIXEL_FORMAT_FLOAT_RGBX16 or Rgb565 DETEX_PIXEL_FORMAT_FLOAT_BGRX16

                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, true,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_FLOAT_RGBX16);
                colorType = SKColorType.Rgb565;
                break;

            case EPixelFormat.PF_BC7:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_ETC1:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC1,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGB:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGBA:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC,
                                               outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_B8G8R8A8:
                data      = mip.Data.Data;
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_G8:
                data      = mip.Data.Data;
                colorType = SKColorType.Gray8;
                break;

            case EPixelFormat.PF_FloatRGBA:
                data      = mip.Data.Data;
                colorType = SKColorType.RgbaF16;
                break;

            default: throw new NotImplementedException($"Unknown pixel format: {format}");
            }
        }
Example #2
0
        public static void DecodeTexture(FTexture2DMipMap mip, EPixelFormat format, bool isNormalMap, out byte[] data, out SKColorType colorType)
        {
            switch (format)
            {
            case EPixelFormat.PF_DXT1:
                data      = DXTDecoder.DXT1(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_DXT5:
                data      = DXTDecoder.DXT5(mip.Data.Data, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ASTC_4x4:
            case EPixelFormat.PF_ASTC_6x6:
            case EPixelFormat.PF_ASTC_8x8:
            case EPixelFormat.PF_ASTC_10x10:
            case EPixelFormat.PF_ASTC_12x12:
                data = ASTCDecoder.RGBA8888(
                    mip.Data.Data,
                    FormatHelper.GetBlockWidth(format),
                    FormatHelper.GetBlockHeight(format),
                    FormatHelper.GetBlockDepth(format),
                    mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;

                if (isNormalMap)
                {
                    // UE4 drops blue channel for normal maps before encoding, restore it
                    unsafe
                    {
                        var offset = 0;
                        fixed(byte *d = data)
                        {
                            for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
                            {
                                d[offset + 2] = BCDecoder.GetZNormal(d[offset], d[offset + 1]);
                                offset       += 4;
                            }
                        }
                    }
                }

                break;

            case EPixelFormat.PF_BC4:
                data      = BCDecoder.BC4(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC5:
                data      = BCDecoder.BC5(mip.Data.Data, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_BC6H:
                // BC6H doesn't work no matter the pixel format, the closest we can get is either
                // Rgb565 DETEX_PIXEL_FORMAT_FLOAT_RGBX16 or Rgb565 DETEX_PIXEL_FORMAT_FLOAT_BGRX16

                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, true,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_FLOAT_RGBX16);
                colorType = SKColorType.Rgb565;
                break;

            case EPixelFormat.PF_BC7:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC1:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC1,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGB:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_ETC2_RGBA:
                data = Detex.DecodeDetexLinear(mip.Data.Data, mip.SizeX, mip.SizeY, false,
                                               DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC,
                                               DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8);
                colorType = SKColorType.Rgba8888;
                break;

            case EPixelFormat.PF_R16F:
            case EPixelFormat.PF_R16F_FILTER:
                unsafe
                {
                    fixed(byte *d = mip.Data.Data)
                    {
                        data = ConvertRawR16DataToRGB888X(mip.SizeX, mip.SizeY, d, mip.SizeX * 2);     // 2 BPP
                    }
                }

                colorType = SKColorType.Rgb888x;
                break;

            case EPixelFormat.PF_B8G8R8A8:
                data      = mip.Data.Data;
                colorType = SKColorType.Bgra8888;
                break;

            case EPixelFormat.PF_G8:
                data      = mip.Data.Data;
                colorType = SKColorType.Gray8;
                break;

            case EPixelFormat.PF_FloatRGBA:
                unsafe
                {
                    fixed(byte *d = mip.Data.Data)
                    {
                        data = ConvertRawR16G16B16A16FDataToRGBA8888(mip.SizeX, mip.SizeY, d, mip.SizeX * 8, false);     // 8 BPP
                    }
                }

                colorType = SKColorType.Rgba8888;
                break;

            default: throw new NotImplementedException($"Unknown pixel format: {format}");
            }
        }
Example #3
0
        public static void DecodeTexturePlaystation(FTexture2DMipMap mip, EPixelFormat format, bool isNormalMap, out byte[] data, out SKColorType colorType)
        {
            switch (format)
            {
            case EPixelFormat.PF_DXT5:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 16;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                var d = PlatformDeswizzlers.DeswizzlePS4(mip.Data.Data, mip.SizeX, mip.SizeY, 4, 4, 16);
                data      = DXTDecoder.DXT5(d, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;
            }

            case EPixelFormat.PF_DXT1:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 8;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                var d = PlatformDeswizzlers.DeswizzlePS4(mip.Data.Data, mip.SizeX, mip.SizeY, 4, 4, 8);
                data      = DXTDecoder.DXT1(d, mip.SizeX, mip.SizeY, mip.SizeZ);
                colorType = SKColorType.Rgba8888;
                break;
            }

            case EPixelFormat.PF_B8G8R8A8:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 4;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                data      = PlatformDeswizzlers.DeswizzlePS4(mip.Data.Data, mip.SizeX, mip.SizeY, 1, 1, 4);
                colorType = SKColorType.Bgra8888;
                break;
            }

            case EPixelFormat.PF_G8:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 1;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                data      = PlatformDeswizzlers.DeswizzlePS4(mip.Data.Data, mip.SizeX, mip.SizeY, 1, 1, 1);
                colorType = SKColorType.Gray8;
                break;
            }

            case EPixelFormat.PF_BC5:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 16;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                var d = PlatformDeswizzlers.DeswizzlePS4(mip.Data.Data, mip.SizeX, mip.SizeY, 4, 4, 16);
                data      = BCDecoder.BC5(d, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;
            }

            case EPixelFormat.PF_BC4:
            {
                var uBlockSize  = mip.SizeX / 4;
                var vBlockSize  = mip.SizeY / 4;
                var totalBlocks = mip.Data.Data.Length / 8;

                if (uBlockSize * vBlockSize > totalBlocks)
                {
                    throw new ParserException($"Texture unable to be untiled: {format}");
                }

                var d = PlatformDeswizzlers.DeswizzlePS4(mip.Data.Data, mip.SizeX, mip.SizeY, 4, 4, 8);
                data      = BCDecoder.BC4(d, mip.SizeX, mip.SizeY);
                colorType = SKColorType.Rgb888x;
                break;
            }

            default:
            {
                TextureDecoder.DecodeTexture(mip, format, isNormalMap, out data, out colorType);
                break;
            }
            }
        }