public void Create(long Key, byte[] Data, GalImage Image) { int Handle = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, Handle); const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length); if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format)) { InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format); GL.CompressedTexImage2D( TextureTarget.Texture2D, Level, InternalFmt, Image.Width, Image.Height, Border, Data.Length, Data); } else { //TODO: Use KHR_texture_compression_astc_hdr when available if (IsAstc(Image.Format)) { int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format); int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format); Data = ASTCDecoder.DecodeToRGBA8888( Data, TextureBlockWidth, TextureBlockHeight, 1, Image.Width, Image.Height, 1); Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask); } (PixelInternalFormat InternalFmt, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); GL.TexImage2D( TextureTarget.Texture2D, Level, InternalFmt, Image.Width, Image.Height, Border, Format, Type, Data); } }
/// <summary> /// Decodes a byte array of image data given the source image in bytes, width, height, and DXGI format. /// </summary> /// <param name="byte[]">The byte array of the image</param> /// <param name="Width">The width of the image in pixels.</param> /// <param name="Height">The height of the image in pixels.</param> /// <param name=" DDS.DXGI_FORMAT">The image format.</param> /// <returns>Returns a byte array of decoded data. </returns> public static byte[] DecodeBlock(byte[] data, uint Width, uint Height, TEX_FORMAT Format, PlatformSwizzle PlatformSwizzle = PlatformSwizzle.None) { if (data == null) { throw new Exception($"Data is null!"); } if (Format <= 0) { throw new Exception($"Invalid Format!"); } if (data.Length <= 0) { throw new Exception($"Data is empty!"); } if (Width <= 0) { throw new Exception($"Invalid width size {Width}!"); } if (Height <= 0) { throw new Exception($"Invalid height size {Height}!"); } if (PlatformSwizzle == PlatformSwizzle.Platform_3DS && !IsCompressed(Format)) { return(CTR_3DS.DecodeBlock(data, (int)Width, (int)Height, Format)); } if (Format == TEX_FORMAT.R32G8X24_FLOAT) { return(ConvertBgraToRgba(DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, DDS.DXGI_FORMAT.DXGI_FORMAT_R32G8X24_TYPELESS))); } if (Format == TEX_FORMAT.BC5_SNORM) { return(ConvertBgraToRgba(DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true, true))); } if (IsCompressed(Format)) { return(ConvertBgraToRgba(DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format))); } else { //If blue channel becomes first, do not swap them! // if (Format.ToString().StartsWith("B") || Format == TEX_FORMAT.B5G6R5_UNORM) // return DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format); if (IsAtscFormat(Format)) { return(ConvertBgraToRgba(ASTCDecoder.DecodeToRGBA8888(data, (int)GetBlockWidth(Format), (int)GetBlockHeight(Format), 1, (int)Width, (int)Height, 1))); } else { return(ConvertBgraToRgba(DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format))); } } }
public bool Decode(TexFormat format, byte[] input, int width, int height, out byte[] output) { output = null; if (format.ToString().StartsWith("ASTC")) { var x = (int)TextureFormatHelper.GetBlockWidth(format); var y = (int)TextureFormatHelper.GetBlockHeight(format); var z = (int)TextureFormatHelper.GetBlockDepth(format); output = ASTCDecoder.DecodeToRGBA8888(input, x, y, z, width, height, 1); } return(output != null); }
private static GalTexture ConvertAstcTextureToRgba(GalTexture Texture) { int TextureBlockWidth = GetAstcBlockWidth(Texture.Format); int TextureBlockHeight = GetAstcBlockHeight(Texture.Format); Texture.Data = ASTCDecoder.DecodeToRGBA8888( Texture.Data, TextureBlockWidth, TextureBlockHeight, 1, Texture.Width, Texture.Height, 1); Texture.Format = GalTextureFormat.A8B8G8R8; return(Texture); }
public void Create(long Key, byte[] Data, GalTexture Texture) { int Handle = GL.GenTexture(); TextureCache.AddOrUpdate(Key, new TCE(Handle, Texture), (uint)Data.Length); GL.BindTexture(TextureTarget.Texture2D, Handle); const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; if (IsCompressedTextureFormat(Texture.Format)) { InternalFormat InternalFmt = OGLEnumConverter.GetCompressedTextureFormat(Texture.Format); GL.CompressedTexImage2D( TextureTarget.Texture2D, Level, InternalFmt, Texture.Width, Texture.Height, Border, Data.Length, Data); } else { if (Texture.Format >= GalTextureFormat.Astc2D4x4) { int TextureBlockWidth = GetAstcBlockWidth(Texture.Format); int TextureBlockHeight = GetAstcBlockHeight(Texture.Format); Data = ASTCDecoder.DecodeToRGBA8888( Data, TextureBlockWidth, TextureBlockHeight, 1, Texture.Width, Texture.Height, 1); Texture.Format = GalTextureFormat.A8B8G8R8; } const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba; (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(Texture.Format); GL.TexImage2D( TextureTarget.Texture2D, Level, InternalFmt, Texture.Width, Texture.Height, Border, Format, Type, Data); } int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Texture.XSource); int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Texture.YSource); int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Texture.ZSource); int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Texture.WSource); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA); }
public static SKImage DecodeImage(byte[] sequence, int width, int height, int depth, EPixelFormat format) { byte[] data; SKColorType colorType; switch (format) { case EPixelFormat.PF_DXT5: data = DXTDecoder.DecodeDXT5(sequence, width, height, depth); colorType = SKColorType.Rgba8888; break; case EPixelFormat.PF_DXT1: data = DXTDecoder.DecodeDXT1(sequence, width, height, depth); colorType = SKColorType.Rgba8888; break; case EPixelFormat.PF_ASTC_8x8: var x = (int)TextureFormatHelper.GetBlockWidth(format); var y = (int)TextureFormatHelper.GetBlockHeight(format); var z = (int)TextureFormatHelper.GetBlockDepth(format); data = ASTCDecoder.DecodeToRGBA8888(sequence, x, y, z, width, height, 1); colorType = SKColorType.Rgba8888; break; case EPixelFormat.PF_B8G8R8A8: data = sequence; colorType = SKColorType.Bgra8888; break; case EPixelFormat.PF_BC5: data = BCDecoder.DecodeBC5(sequence, width, height); colorType = SKColorType.Rgb888x; break; case EPixelFormat.PF_BC4: data = BCDecoder.DecodeBC4(sequence, width, height); colorType = SKColorType.Rgb888x; break; case EPixelFormat.PF_G8: data = sequence; colorType = SKColorType.Gray8; break; case EPixelFormat.PF_FloatRGBA: data = sequence; colorType = SKColorType.RgbaF16; break; case EPixelFormat.PF_BC7: data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false, inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC, outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8); colorType = SKColorType.Rgb888x; break; case EPixelFormat.PF_BC6H: data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: true, inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT, outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8); // Not sure whether that works, would actually be DETEX_PIXEL_FORMAT_FLOAT_RGBX32 data = Detex.DecodeBC6H(sequence, width, height); colorType = SKColorType.Rgb888x; break; case EPixelFormat.PF_ETC1: data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: 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(sequence, width, height, isFloat: 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(sequence, width, height, isFloat: false, inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC, outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8); colorType = SKColorType.Rgba8888; break; default: throw new NotImplementedException($"Cannot decode {format} format"); } using var bitmap = new SKBitmap(new SKImageInfo(width, height, colorType, SKAlphaType.Unpremul)); unsafe { fixed(byte *p = data) { bitmap.SetPixels(new IntPtr(p)); } } return(SKImage.FromBitmap(bitmap)); }
/// <summary> /// Decodes a byte array of image data given the source image in bytes, width, height, and DXGI format. /// </summary> /// <param name="byte[]">The byte array of the image</param> /// <param name="Width">The width of the image in pixels.</param> /// <param name="Height">The height of the image in pixels.</param> /// <param name=" DDS.DXGI_FORMAT">The image format.</param> /// <returns>Returns a byte array of decoded data. </returns> public static byte[] DecodeBlock(byte[] data, uint Width, uint Height, TEX_FORMAT Format, byte[] paletteData, ImageParameters parameters, PALETTE_FORMAT PaletteFormat = PALETTE_FORMAT.None, PlatformSwizzle PlatformSwizzle = PlatformSwizzle.None) { if (data == null) { throw new Exception($"Data is null!"); } if (Format <= 0) { throw new Exception($"Invalid Format!"); } if (data.Length <= 0) { throw new Exception($"Data is empty!"); } if (Width <= 0) { throw new Exception($"Invalid width size {Width}!"); } if (Height <= 0) { throw new Exception($"Invalid height size {Height}!"); } byte[] imageData = new byte[0]; bool DontSwapRG = false; if (PlatformSwizzle == PlatformSwizzle.Platform_3DS) { imageData = CTR_3DS.DecodeBlock(data, (int)Width, (int)Height, Format); DontSwapRG = true; } else if (PlatformSwizzle == PlatformSwizzle.Platform_Gamecube) { imageData = Decode_Gamecube.DecodeData(data, paletteData, Width, Height, Format, PaletteFormat); } else { if (Format == TEX_FORMAT.R32G8X24_FLOAT) { imageData = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, DDS.DXGI_FORMAT.DXGI_FORMAT_R32G8X24_TYPELESS); } if (Format == TEX_FORMAT.BC5_SNORM) { imageData = DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true, true); } if (Format == TEX_FORMAT.L8) { return(RGBAPixelDecoder.Decode(data, (int)Width, (int)Height, Format)); } if (Format == TEX_FORMAT.LA8) { return(RGBAPixelDecoder.Decode(data, (int)Width, (int)Height, Format)); } if (Format == TEX_FORMAT.R5G5B5A1_UNORM) { return(RGBAPixelDecoder.Decode(data, (int)Width, (int)Height, Format)); } if (IsCompressed(Format)) { imageData = DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format); } else { if (IsAtscFormat(Format)) { imageData = ASTCDecoder.DecodeToRGBA8888(data, (int)GetBlockWidth(Format), (int)GetBlockHeight(Format), 1, (int)Width, (int)Height, 1); } else { imageData = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format); } // imageData = RGBAPixelDecoder.Decode(data, (int)Width, (int)Height, Format); } } if (parameters.DontSwapRG || DontSwapRG) { return(imageData); } else { return(ConvertBgraToRgba(imageData)); } }
public static SKImage DecodeImage(byte[] sequence, int width, int height, int depth, EPixelFormat format) { byte[] data; SKColorType colorType; switch (format) { case EPixelFormat.PF_DXT5: data = DXTDecoder.DecodeDXT5(sequence, width, height, depth); colorType = SKColorType.Rgba8888; break; case EPixelFormat.PF_DXT1: data = DXTDecoder.DecodeDXT1(sequence, width, height, depth); colorType = SKColorType.Rgba8888; break; case EPixelFormat.PF_ASTC_8x8: var x = (int)TextureFormatHelper.GetBlockWidth(format); var y = (int)TextureFormatHelper.GetBlockHeight(format); var z = (int)TextureFormatHelper.GetBlockDepth(format); data = ASTCDecoder.DecodeToRGBA8888(sequence, x, y, z, width, height, 1); colorType = SKColorType.Rgba8888; break; case EPixelFormat.PF_B8G8R8A8: data = sequence; colorType = SKColorType.Bgra8888; break; case EPixelFormat.PF_BC5: data = BCDecoder.DecodeBC5(sequence, width, height); colorType = SKColorType.Bgra8888; break; case EPixelFormat.PF_BC4: data = BCDecoder.DecodeBC4(sequence, width, height); colorType = SKColorType.Bgra8888; break; case EPixelFormat.PF_G8: data = sequence; colorType = SKColorType.Gray8; break; case EPixelFormat.PF_FloatRGBA: data = sequence; colorType = SKColorType.RgbaF16; break; default: throw new NotImplementedException($"Cannot decode {format} format"); } using var bitmap = new SKBitmap(new SKImageInfo(width, height, colorType, SKAlphaType.Unpremul)); unsafe { fixed(byte *p = data) { bitmap.SetPixels(new IntPtr(p)); } } return(SKImage.FromBitmap(bitmap)); }