private void CreateBannerImage() { if (bannerBitmap != null) { bannerBitmap.Dispose(); } ushort[] DecodedImageData = DecodeBNRImage(ImageData); //C4.DecodeC4(ImageData, 96, 32); uint[] PixelData = new uint[96 * 32]; for (int i = 0; i < DecodedImageData.Length; i++) { PixelData[i] = RGB5A3.ToARGB8(DecodedImageData[i]); } byte[] BitmapSourceData = new byte[4 * 96 * 32]; for (int i = 0; i < PixelData.Length; i++) { int idx = i * 4; BitmapSourceData[idx + 3] = (byte)((PixelData[i] >> 24) & 0xFF); BitmapSourceData[idx + 2] = (byte)((PixelData[i] >> 16) & 0xFF); BitmapSourceData[idx + 1] = (byte)((PixelData[i] >> 8) & 0xFF); BitmapSourceData[idx + 0] = (byte)((PixelData[i] >> 0) & 0xFF); } bannerBitmap = BitmapUtilities.CreateBitmap(BitmapSourceData, 96, 32); bannerImage = bannerBitmap.ToBitmapSource(); }
public BTI(int[] Imported_Data, int Width, int Height) { // Generate "Default" BTI Header (minus Palette & Image/Palette offsets) Header = new BTI_Header { Width = (ushort)Width, Height = (ushort)Height }; // Generate Palette and Convert Image to Palette Index List <ushort> Palette_List = new List <ushort>(); byte[] Converted_Data = new byte[Imported_Data.Length]; for (int i = 0; i < Imported_Data.Length; i++) { int Current_Int = Imported_Data[i]; ushort Pixel = RGB5A3.ToRGB5A3((byte)(Current_Int >> 24), (byte)(Current_Int >> 16), (byte)(Current_Int >> 8), (byte)(Current_Int >> 0)); if (!Palette_List.Contains(Pixel)) { Palette_List.Add(Pixel); } int Palette_Idx = Palette_List.IndexOf(Pixel); if (Palette_Idx < 0 || Palette_Idx > 255) { Console.WriteLine("Palette index was out of bounds!"); throw new IndexOutOfRangeException("Palette Index was outside of it's alloted bounds! Value: " + Palette_Idx); } Converted_Data[i] = (byte)Palette_Idx; } Palette = Palette_List.ToArray(); // Turn Converted Data into C8 Encoded Data byte[] Encoded_Data = null; switch (Header.Image_Format) { case ImageFormat.C4: Encoded_Data = Images.C4.EncodeC4(Imported_Data, Palette, Width, Height, ColorFormat.RGB5A3); break; case ImageFormat.C8: Encoded_Data = Images.C8.EncodeC8(Imported_Data, Palette, Width, Height); break; } // Write Image Offset & Data Header.Image_Data_Offset = 0x20; Image_Data = Encoded_Data; // Write Palette Offset & Count Header.Palette_Offset = (uint)(0x20 + Encoded_Data.Length); Header.Palette_Entry_Count = (ushort)Palette.Length; }
public static uint[] ToArgb8Palette(byte[] data) { var output = new uint[16]; for (int i = 0, idx = 0; i < 16; i++, idx += 2) { output[i] = RGB5A3.ToARGB8((ushort)(data[idx] << 8 | data[idx + 1])); } return(output); }
public static uint[] ToArgb8Palette(ushort[] palette) { var output = new uint[16]; for (var i = 0; i < 16; i++) { output[i] = RGB5A3.ToARGB8(palette[i]); } return(output); }
private static byte[] C4ImageSubroutineEncode(int[] ImageData, ushort[] Palette, int Width, int Height, bool UsesBlocks = true) { int[] RGB8Palette = new int[Palette.Length]; for (int i = 0; i < RGB8Palette.Length; i++) { RGB8Palette[i] = (int)RGB5A3.ToARGB8(Palette[i]); } byte[] C4Data = new byte[ImageData.Length]; for (int i = 0; i < C4Data.Length; i++) { C4Data[i] = ColorUtilities.ClosestColorRGB(ImageData[i], RGB8Palette); } return(Utilities.Utilities.CondenseNibbles(UsesBlocks ? BlockFormat.Encode(C4Data, Width, Height, 8, 8) : C4Data)); }
private static byte[] C8ImageSubroutineEncode(int[] ImageData, ushort[] Palette, int Width, int Height) { int[] RGB8Palette = new int[Palette.Length]; for (int i = 0; i < RGB8Palette.Length; i++) { RGB8Palette[i] = (int)RGB5A3.ToARGB8(Palette[i]); } byte[] C8Data = new byte[ImageData.Length]; for (int i = 0; i < C8Data.Length; i++) { C8Data[i] = Utilities.ColorUtilities.ClosestColorRGB(ImageData[i], RGB8Palette); } return(BlockFormat.Encode(C8Data, Width, Height, 8, 4)); }
public static int[] GetRGBA8Palette(ushort[] rawPalette, ColorFormat colorFormat) { if (rawPalette == null) { throw new ArgumentNullException($"{nameof(rawPalette)} cannot be null!"); } var palette = new int[rawPalette.Length]; switch (colorFormat) { case ColorFormat.RGB565: for (var i = 0; i < palette.Length; i++) { palette[i] = (int)RGB565.ToARGB8(rawPalette[i]); } break; case ColorFormat.RGB5A1: for (var i = 0; i < palette.Length; i++) { palette[i] = (int)RGB5.ToARGB8(rawPalette[i]); } break; case ColorFormat.RGB5A3: for (var i = 0; i < palette.Length; i++) { palette[i] = (int)RGB5A3.ToARGB8(rawPalette[i]); } break; case ColorFormat.RGBA4: for (var i = 0; i < palette.Length; i++) { palette[i] = (int)RGBA4.ToARGB8(rawPalette[i]); } break; } return(palette); }
private static int[] C8ImageSubroutineDecode(byte[] C8ImageData, ushort[] Palette, int Width, int Height) { int[] RGB8Palette = new int[Palette.Length]; for (int i = 0; i < RGB8Palette.Length; i++) { RGB8Palette[i] = (int)RGB5A3.ToARGB8(Palette[i]); } byte[] UnscrambledData = BlockFormat.Decode(C8ImageData, Width, Height, 8, 4); int[] ImageData = new int[UnscrambledData.Length]; for (int i = 0; i < ImageData.Length; i++) { ImageData[i] = RGB8Palette[UnscrambledData[i]]; } return(ImageData); }
public static int[] Decode(ushort[] rgba16Data, int width, int height) { var dataOut = new int[width * height]; var position = 0; rgba16Data = SwizzleUtil.Unswizzle(rgba16Data, width, height, 4, 4); for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { dataOut[position] = (int)RGB5A3.ToARGB8(rgba16Data[position]); position++; } } return(dataOut); }
private static int[] C4ImageSubroutineDecode(byte[] C4ImageData, ushort[] Palette, int Width, int Height, bool UsesBlocks = true) { C4ImageData = Utilities.Utilities.SeparateNibbles(C4ImageData); int[] RGB8Palette = new int[Palette.Length]; for (int i = 0; i < RGB8Palette.Length; i++) { RGB8Palette[i] = (int)RGB5A3.ToARGB8(Palette[i]); } byte[] UnscrambledData = UsesBlocks ? BlockFormat.Decode(C4ImageData, Width, Height, 8, 8) : C4ImageData; int[] ImageData = new int[UnscrambledData.Length]; for (int i = 0; i < ImageData.Length; i++) { ImageData[i] = RGB8Palette[UnscrambledData[i]]; } return(ImageData); }
public BTI(byte[] data) { Data = data; Header = new BTI_Header(data); Bitmap_Data = new byte[Header.Width * Header.Height * 4]; if (Header.Image_Format == ImageFormat.RGB565 || Header.Image_Format == ImageFormat.RGB5A3) { ushort[] PixelData = new ushort[(data.Length - 0x20) / 2]; for (int i = 0, idx = 0x20; i < PixelData.Length; i++, idx += 2) { PixelData[i] = (ushort)((data[idx] << 8) | data[idx + 1]); } // Decode Block Format PixelData = SwizzleUtil.Unswizzle(PixelData, Header.Width, Header.Height, 4, 4); Bitmap_Data = new byte[PixelData.Length * 4]; for (int i = 0, idx = 0; i < PixelData.Length; i++, idx += 4) { byte A = 0, R = 0, G = 0, B = 0; if (Header.Image_Format == ImageFormat.RGB5A3) { RGB5A3.ToARGB8(PixelData[i], out A, out R, out G, out B); } else { A = 0xFF; RGB565.ToARGB8(PixelData[i], out R, out G, out B); } Bitmap_Data[idx] = B; Bitmap_Data[idx + 1] = G; Bitmap_Data[idx + 2] = R; Bitmap_Data[idx + 3] = A; } } else if (Header.Image_Format == ImageFormat.RGBA8) { } else { switch (Header.Palette_Format) { case PixelFormat.RGB565: case PixelFormat.RGB5A3: Palette = new ushort[Header.Palette_Entry_Count]; for (int i = 0; i < Header.Palette_Entry_Count; i++) { int offset = (int)(Header.Palette_Offset + i * 2); Palette[i] = (ushort)((Data[offset] << 8) | Data[offset + 1]); } break; } switch (Header.Image_Format) { case ImageFormat.I4: Image_Data = Data.Skip((int)Header.Image_Data_Offset).Take(((Header.Width * Header.Height) + 1) / 2).ToArray(); Buffer.BlockCopy(I4.DecodeI4(Image_Data, Header.Width, Header.Height), 0, Bitmap_Data, 0, Bitmap_Data.Length); break; case ImageFormat.I8: Image_Data = Data.Skip((int)Header.Image_Data_Offset).Take(Header.Width * Header.Height).ToArray(); Buffer.BlockCopy(I8.DecodeI8(Image_Data, Header.Width, Header.Height), 0, Bitmap_Data, 0, Bitmap_Data.Length); break; case ImageFormat.IA4: Image_Data = Data.Skip((int)Header.Image_Data_Offset).Take(Header.Width * Header.Height).ToArray(); Buffer.BlockCopy(IA4.DecodeIA4(Image_Data, Header.Width, Header.Height, Color.White), 0, Bitmap_Data, 0, Bitmap_Data.Length); break; case ImageFormat.IA8: Image_Data = Data.Skip((int)Header.Image_Data_Offset).Take((Header.Width * Header.Height) * 2).ToArray(); Buffer.BlockCopy(IA8.DecodeIA8(Image_Data, Header.Width, Header.Height), 0, Bitmap_Data, 0, Bitmap_Data.Length); break; case ImageFormat.C4: Image_Data = Data.Skip((int)Header.Image_Data_Offset).Take((Header.Width * Header.Height) / 2).ToArray(); Buffer.BlockCopy(C4.DecodeC4(Image_Data, Palette, Header.Width, Header.Height, (ColorFormat)Header.Palette_Format), 0, Bitmap_Data, 0, Bitmap_Data.Length); break; case ImageFormat.C8: Image_Data = Data.Skip((int)Header.Image_Data_Offset).Take(Header.Width * Header.Height).ToArray(); int Index = 0; for (int blockY = 0; blockY < Header.Height; blockY += 4) { for (int blockX = 0; blockX < Header.Width; blockX += 8) { for (int Y = 0; Y < 4; Y++) { for (int X = 0; X < 8; X++) { ushort Pixel = Palette[Image_Data[Index]]; int New_Index = Header.Width * (blockY + Y) + blockX + X; byte A = 0, R = 0, G = 0, B = 0; switch (Header.Palette_Format) { case PixelFormat.RGB565: RGB565.ToARGB8(Pixel, out R, out G, out B); A = 0xFF; break; case PixelFormat.RGB5A3: RGB5A3.ToARGB8(Pixel, out A, out R, out G, out B); break; default: throw new NotImplementedException("Pixel format is not implemented!"); } Bitmap_Data[New_Index * 4] = B; Bitmap_Data[New_Index * 4 + 1] = G; Bitmap_Data[New_Index * 4 + 2] = R; Bitmap_Data[New_Index * 4 + 3] = A; Index++; } } } } break; default: throw new NotImplementedException("Image Format is not implemented!"); } } Bitmap_Image = Utilities.BitmapUtilities.CreateBitmap(Bitmap_Data, Header.Width, Header.Height); }