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