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}"); } }
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}"); } }
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; } } }