public byte[] GenerateMipsAndCompress(Bitmap bitmap, TEX_FORMAT Format, float alphaRef = 0.5f) { byte[] DecompressedData = BitmapExtension.ImageToByte(bitmap); DecompressedData = ConvertBgraToRgba(DecompressedData); Bitmap Image = BitmapExtension.GetBitmap(DecompressedData, bitmap.Width, bitmap.Height); List <byte[]> mipmaps = new List <byte[]>(); mipmaps.Add(STGenericTexture.CompressBlock(DecompressedData, bitmap.Width, bitmap.Height, Format, alphaRef)); for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) { if (Image.Width / 2 > 0 && Image.Height / 2 > 0) { Image = BitmapExtension.Resize(Image, Image.Width / 2, Image.Height / 2); mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format, alphaRef)); } } Image.Dispose(); return(Utils.CombineByteArray(mipmaps.ToArray())); }
public static Bitmap DecompressBC1(Byte[] data, int width, int height, bool IsSRGB) { int W = (width + 3) / 4; int H = (height + 3) / 4; byte[] Output = new byte[W * H * 64]; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 8; byte[] Tile = BCnDecodeTile(data, IOffs, true); int TOffset = 0; for (int TY = 0; TY < 4; TY++) { for (int TX = 0; TX < 4; TX++) { int OOffset = (X * 4 + TX + (Y * 4 + TY) * W * 4) * 4; Output[OOffset + 0] = Tile[TOffset + 0]; Output[OOffset + 1] = Tile[TOffset + 1]; Output[OOffset + 2] = Tile[TOffset + 2]; Output[OOffset + 3] = Tile[TOffset + 3]; TOffset += 4; } } } } return(BitmapExtension.GetBitmap(Output, W * 4, H * 4)); }
public static Bitmap DecodeBlockGetBitmap(byte[] data, uint Width, uint Height, TEX_FORMAT Format) { Bitmap bitmap = BitmapExtension.GetBitmap(DecodeBlock(data, Width, Height, Format), (int)Width, (int)Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); return(bitmap); }
public static Bitmap DecodeR8G8(Byte[] data, int width, int height) { byte[] Output = new byte[width * height * 4]; int OOffset = 0; int W = (width + 3) / 4; int H = (height + 3) / 4; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 2; Output[OOffset + 1] = data[IOffs + 1]; Output[OOffset + 2] = data[IOffs + 0]; Output[OOffset + 3] = 0xff; OOffset += 4; } } return(BitmapExtension.GetBitmap(Output, width, height)); }
public override void SetImageData(Bitmap bitmap, int ArrayLevel) { byte[] Data = BitmapExtension.ImageToByte(bitmap); Width = (uint)bitmap.Width; Height = (uint)bitmap.Height; ImageData = DDSCompressor.EncodePixelBlock(Data, bitmap.Width, bitmap.Width, DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); }
/// <summary> /// Gets a <see cref="Bitmap"/> given an array and mip index. /// </summary> /// <param name="ArrayIndex">The index of the surface/array. Cubemaps will have 6</param> /// <param name="MipLevel">The index of the mip level.</param> /// <returns></returns> public Bitmap GetBitmap(int ArrayIndex = 0, int MipLevel = 0) { if (Surfaces.Count == 0) { throw new Exception($"Surfaces are empty on texture {Text}! Failed to get bitmap!"); } Bitmap bitmap = BitmapExtension.GetBitmap(DecodeBlock(Surfaces[ArrayIndex].mipmaps[MipLevel], Width, Height, Format), (int)Width, (int)Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); return(bitmap); }
public static Bitmap DecompressBC3(Byte[] data, int width, int height, bool IsSRGB) { int W = (width + 3) / 4; int H = (height + 3) / 4; byte[] Output = new byte[W * H * 64]; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 16; byte[] Tile = BCnDecodeTile(data, IOffs + 8, false); byte[] Alpha = new byte[8]; Alpha[0] = data[IOffs + 0]; Alpha[1] = data[IOffs + 1]; CalculateBC3Alpha(Alpha); int AlphaLow = Get32(data, IOffs + 2); int AlphaHigh = Get16(data, IOffs + 6); ulong AlphaCh = (uint)AlphaLow | (ulong)AlphaHigh << 32; int TOffset = 0; for (int TY = 0; TY < 4; TY++) { for (int TX = 0; TX < 4; TX++) { int OOffset = (X * 4 + TX + (Y * 4 + TY) * W * 4) * 4; byte AlphaPx = Alpha[(AlphaCh >> (TY * 12 + TX * 3)) & 7]; Output[OOffset + 0] = Tile[TOffset + 0]; Output[OOffset + 1] = Tile[TOffset + 1]; Output[OOffset + 2] = Tile[TOffset + 2]; Output[OOffset + 3] = AlphaPx; TOffset += 4; } } } } return(BitmapExtension.GetBitmap(Output, W * 4, H * 4)); }
public static Bitmap DecompressBC4(Byte[] data, int width, int height, bool IsSNORM) { int W = (width + 3) / 4; int H = (height + 3) / 4; byte[] Output = new byte[W * H * 64]; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 8; byte[] Red = new byte[8]; Red[0] = data[IOffs + 0]; Red[1] = data[IOffs + 1]; CalculateBC3Alpha(Red); int RedLow = Get32(data, IOffs + 2); int RedHigh = Get16(data, IOffs + 6); ulong RedCh = (uint)RedLow | (ulong)RedHigh << 32; int TOffset = 0; int TW = Math.Min(width - X * 4, 4); int TH = Math.Min(height - Y * 4, 4); for (int TY = 0; TY < 4; TY++) { for (int TX = 0; TX < 4; TX++) { int OOffset = (X * 4 + TX + (Y * 4 + TY) * W * 4) * 4; byte RedPx = Red[(RedCh >> (TY * 12 + TX * 3)) & 7]; Output[OOffset + 0] = RedPx; Output[OOffset + 1] = RedPx; Output[OOffset + 2] = RedPx; Output[OOffset + 3] = 255; TOffset += 4; } } } } return(BitmapExtension.GetBitmap(Output, W * 4, H * 4)); }
private void LoadBitmap(Bitmap Image) { Image = BitmapExtension.SwapBlueRedChannels(Image); Format = TEX_FORMAT.R8G8B8A8_UNORM; Width = (uint)Image.Width; Height = (uint)Image.Height; MipCount = 1; ImageData = GenerateMipsAndCompress(Image, MipCount, Format); if (ImageData == null || ImageData.Length <= 0) { throw new Exception("Image failed to encode!"); } }
public static byte[] GenerateMipsAndCompress(Bitmap bitmap, uint MipCount, TEX_FORMAT Format, float alphaRef = 0.5f, STCompressionMode CompressionMode = STCompressionMode.Fast) { byte[] DecompressedData = BitmapExtension.ImageToByte(bitmap); DecompressedData = ConvertBgraToRgba(DecompressedData); Bitmap Image = BitmapExtension.GetBitmap(DecompressedData, bitmap.Width, bitmap.Height); List <byte[]> mipmaps = new List <byte[]>(); for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) { int width = Math.Max(1, bitmap.Width >> mipLevel); int height = Math.Max(1, bitmap.Height >> mipLevel); Image = BitmapExtension.Resize(Image, width, height); mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, Format, alphaRef, CompressionMode)); } Image.Dispose(); return(Utils.CombineByteArray(mipmaps.ToArray())); }
/* public static byte[] CompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format, float AlphaRef) * { * return DirectXTex.ImageCompressor.Compress(data, width, height, (int)format, AlphaRef); * }*/ public static Bitmap DecompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format, bool GetBitmap) { byte[] output = null; switch (format) { case DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM: case DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB: output = CSharpImageLibrary.DDS.Dxt.DecompressDxt1(data, (int)width, (int)height); break; case DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM: case DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB: output = CSharpImageLibrary.DDS.Dxt.DecompressDxt5(data, (int)width, (int)height); break; case DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM: case DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM: output = CSharpImageLibrary.DDS.Dxt.DecompressDxt4(data, (int)width, (int)height); break; case DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM: case DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM: output = CSharpImageLibrary.DDS.Dxt.DecompressDxt4(data, (int)width, (int)height); break; case DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM: case DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB: output = CSharpImageLibrary.DDS.Dxt.DecompressBc7(data, (int)width, (int)height); break; default: output = DecompressBlock(data, width, height, format); break; } return(BitmapExtension.GetBitmap(output, (int)width, (int)height)); }
public static Bitmap DecodeR8G8B8A8(Byte[] data, int width, int height) { byte[] Output = new byte[width * height * 4]; int OOffset = 0; for (int Y = 0; Y < height; Y++) { for (int X = 0; X < width; X++) { int IOffs = OOffset; Output[OOffset + 0] = data[IOffs + 2]; Output[OOffset + 1] = data[IOffs + 1]; Output[OOffset + 2] = data[IOffs + 0]; Output[OOffset + 3] = data[IOffs + 3]; OOffset += 4; } } return(BitmapExtension.GetBitmap(Output, width, height)); }
public static Bitmap ColorComponentSelector(Bitmap image, STChannelType R, STChannelType G, STChannelType B, STChannelType A) { BitmapExtension.ColorSwapFilter color = new BitmapExtension.ColorSwapFilter(); if (R == STChannelType.Red) { color.CompRed = BitmapExtension.ColorSwapFilter.Red.Red; } if (R == STChannelType.Green) { color.CompRed = BitmapExtension.ColorSwapFilter.Red.Green; } if (R == STChannelType.Blue) { color.CompRed = BitmapExtension.ColorSwapFilter.Red.Blue; } if (R == STChannelType.Alpha) { color.CompRed = BitmapExtension.ColorSwapFilter.Red.Alpha; } if (R == STChannelType.One) { color.CompRed = BitmapExtension.ColorSwapFilter.Red.One; } if (R == STChannelType.Zero) { color.CompRed = BitmapExtension.ColorSwapFilter.Red.Zero; } if (G == STChannelType.Red) { color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Red; } if (G == STChannelType.Green) { color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Green; } if (G == STChannelType.Blue) { color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Blue; } if (G == STChannelType.Alpha) { color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Alpha; } if (G == STChannelType.One) { color.CompGreen = BitmapExtension.ColorSwapFilter.Green.One; } if (G == STChannelType.Zero) { color.CompGreen = BitmapExtension.ColorSwapFilter.Green.Zero; } if (B == STChannelType.Red) { color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Red; } if (B == STChannelType.Green) { color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Green; } if (B == STChannelType.Blue) { color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Blue; } if (B == STChannelType.Alpha) { color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Alpha; } if (B == STChannelType.One) { color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.One; } if (B == STChannelType.Zero) { color.CompBlue = BitmapExtension.ColorSwapFilter.Blue.Zero; } if (A == STChannelType.Red) { color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Red; } if (A == STChannelType.Green) { color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Green; } if (A == STChannelType.Blue) { color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Blue; } if (A == STChannelType.Alpha) { color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Alpha; } if (A == STChannelType.One) { color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.One; } if (A == STChannelType.Zero) { color.CompAlpha = BitmapExtension.ColorSwapFilter.Alpha.Zero; } return(BitmapExtension.SwapRGB(image, color)); }
public static Bitmap DecompressBC5(Byte[] data, int width, int height, bool IsSNORM) { int W = (width + 3) / 4; int H = (height + 3) / 4; byte[] Output = new byte[W * H * 64]; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 16; byte[] Red = new byte[8]; byte[] Green = new byte[8]; Red[0] = data[IOffs + 0]; Red[1] = data[IOffs + 1]; Green[0] = data[IOffs + 8]; Green[1] = data[IOffs + 9]; if (IsSNORM == true) { CalculateBC3AlphaS(Red); CalculateBC3AlphaS(Green); } else { CalculateBC3Alpha(Red); CalculateBC3Alpha(Green); } int RedLow = Get32(data, IOffs + 2); int RedHigh = Get16(data, IOffs + 6); int GreenLow = Get32(data, IOffs + 10); int GreenHigh = Get16(data, IOffs + 14); ulong RedCh = (uint)RedLow | (ulong)RedHigh << 32; ulong GreenCh = (uint)GreenLow | (ulong)GreenHigh << 32; int TW = Math.Min(width - X * 4, 4); int TH = Math.Min(height - Y * 4, 4); if (IsSNORM == true) { for (int TY = 0; TY < TH; TY++) { for (int TX = 0; TX < TW; TX++) { int Shift = TY * 12 + TX * 3; int OOffset = ((Y * 4 + TY) * width + (X * 4 + TX)) * 4; byte RedPx = Red[(RedCh >> Shift) & 7]; byte GreenPx = Green[(GreenCh >> Shift) & 7]; if (IsSNORM == true) { RedPx += 0x80; GreenPx += 0x80; } float NX = (RedPx / 255f) * 2 - 1; float NY = (GreenPx / 255f) * 2 - 1; float NZ = (float)Math.Sqrt(1 - (NX * NX + NY * NY)); Output[OOffset + 0] = Clamp((NZ + 1) * 0.5f); Output[OOffset + 1] = Clamp((NY + 1) * 0.5f); Output[OOffset + 2] = Clamp((NX + 1) * 0.5f); Output[OOffset + 3] = 0xff; } } } else { for (int TY = 0; TY < TH; TY++) { for (int TX = 0; TX < TW; TX++) { int Shift = TY * 12 + TX * 3; int OOffset = ((Y * 4 + TY) * width + (X * 4 + TX)) * 4; byte RedPx = Red[(RedCh >> Shift) & 7]; byte GreenPx = Green[(GreenCh >> Shift) & 7]; Output[OOffset + 0] = 255; Output[OOffset + 1] = GreenPx; Output[OOffset + 2] = RedPx; Output[OOffset + 3] = 255; } } } } } return(BitmapExtension.GetBitmap(Output, W * 4, H * 4)); }
/// <summary> /// Gets a <see cref="Bitmap"/> given an array and mip index. /// </summary> /// <param name="ArrayIndex">The index of the surface/array. Cubemaps will have 6</param> /// <param name="MipLevel">The index of the mip level.</param> /// <returns></returns> public Bitmap GetBitmap(int ArrayLevel = 0, int MipLevel = 0) { uint width = Math.Max(1, Width >> MipLevel); uint height = Math.Max(1, Height >> MipLevel); byte[] data = GetImageData(ArrayLevel, MipLevel); try { if (data == null) { throw new Exception("Data is null!"); } if (Format == TEX_FORMAT.BC5_SNORM) { return(DDSCompressor.DecompressBC5(data, (int)width, (int)height, true)); } Bitmap bitmap = BitmapExtension.GetBitmap(DecodeBlock(data, width, height, Format), (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); return(bitmap); } catch (Exception ex) { Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex); try { if (Format == TEX_FORMAT.BC1_UNORM) { return(DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, false)); } else if (Format == TEX_FORMAT.BC1_UNORM_SRGB) { return(DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, true)); } else if (Format == TEX_FORMAT.BC3_UNORM_SRGB) { return(DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, false)); } else if (Format == TEX_FORMAT.BC3_UNORM) { return(DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, true)); } else if (Format == TEX_FORMAT.BC4_UNORM) { return(DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, false)); } else if (Format == TEX_FORMAT.BC4_SNORM) { return(DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, true)); } else if (Format == TEX_FORMAT.BC5_UNORM) { return(DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, false)); } else { Runtime.OpenTKInitialized = true; LoadOpenGLTexture(); return(RenderableTex.GLTextureToBitmap(RenderableTex)); } } catch { Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex); } return(null); } /* try * { * Bitmap bitmap = BitmapExtension.GetBitmap(DecodeBlock(data, width, height, Format), * (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); * * return bitmap; * } * catch (Exception ex) * { * MessageBox.Show($"Failed to texture {Text} \n{DebugInfo()}\n {ex.ToString()}"); * return null; * }*/ }
/// <summary> /// Gets a <see cref="Bitmap"/> given an array and mip index. /// </summary> /// <param name="ArrayIndex">The index of the surface/array. Cubemaps will have 6</param> /// <param name="MipLevel">The index of the mip level.</param> /// <returns></returns> public Bitmap GetBitmap(int ArrayLevel = 0, int MipLevel = 0) { uint width = Math.Max(1, Width >> MipLevel); uint height = Math.Max(1, Height >> MipLevel); byte[] data = GetImageData(ArrayLevel, MipLevel); try { if (data == null) { throw new Exception("Data is null!"); } if (PlatformSwizzle == PlatformSwizzle.Platform_3DS && !IsCompressed(Format)) { var Image = BitmapExtension.GetBitmap(ConvertBgraToRgba(CTR_3DS.DecodeBlock(data, (int)width, (int)height, Format)), (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Image.RotateFlip(RotateFlipType.RotateNoneFlipY); //It's upside down for some reason so flip it return(Image); } switch (Format) { case TEX_FORMAT.R4G4_UNORM: return(BitmapExtension.GetBitmap(R4G4.Decompress(data, (int)width, (int)height, false), (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)); case TEX_FORMAT.BC5_SNORM: return(DDSCompressor.DecompressBC5(data, (int)width, (int)height, true)); case TEX_FORMAT.ETC1: return(BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, false), (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)); case TEX_FORMAT.ETC1_A4: return(BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, true), (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)); default: return(BitmapExtension.GetBitmap(DecodeBlock(data, width, height, Format), (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)); } } catch (Exception ex) { Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex); try { if (Format == TEX_FORMAT.BC1_UNORM) { return(DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, false)); } else if (Format == TEX_FORMAT.BC1_UNORM_SRGB) { return(DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, true)); } else if (Format == TEX_FORMAT.BC3_UNORM_SRGB) { return(DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, false)); } else if (Format == TEX_FORMAT.BC3_UNORM) { return(DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, true)); } else if (Format == TEX_FORMAT.BC4_UNORM) { return(DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, false)); } else if (Format == TEX_FORMAT.BC4_SNORM) { return(DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, true)); } else if (Format == TEX_FORMAT.BC5_UNORM) { return(DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, false)); } else { if (Runtime.UseOpenGL) { Runtime.OpenTKInitialized = true; LoadOpenGLTexture(); return(RenderableTex.GLTextureToBitmap(RenderableTex)); } } } catch { Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex); } return(null); } }
public static Bitmap DecompressBlock(Byte[] data, int width, int height, DDS.DXGI_FORMAT format, bool GetBitmap) { return(BitmapExtension.GetBitmap(DirectXTex.ImageCompressor.Decompress(data, width, height, (int)format), width, height)); }