/// <summary> /// Creates a new <see cref="Sprite"/> from an indexed bitmap. /// </summary> /// <param name="bmp"></param> public Sprite(Bitmap bmp) { // TODO: maybe help the user out and index their image for them if (bmp.PixelFormat != PixelFormat.Format4bppIndexed && bmp.PixelFormat != PixelFormat.Format8bppIndexed) { throw new Exception($"Source image is not indexed! {bmp.PixelFormat}"); } // ensure bitmap size if (bmp.Width % 8 != 0 || bmp.Height % 8 != 0) { throw new Exception("Source image dimensions are not divisible by 8!"); } // lock the bits of the bitmap BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); // create tiles int width = bmp.Width / 8; int height = bmp.Height / 8; tiles = new Tile[width * height]; for (int i = 0; i < tiles.Length; i++) { tiles[i] = new Tile(); } // copy pixel data if (bmp.PixelFormat == PixelFormat.Format4bppIndexed) { //palette = new Palette(16); bitDepth = BitDepth.Four; // copy the source data to a byte buffer byte[] buffer = new byte[bmp.Width * bmp.Height / 2]; Marshal.Copy(bmpData.Scan0, buffer, 0, buffer.Length); // copy pixel data int x = 0; // current x-position in tile int y = 0; // current y-position in tile int a = 0; // current x-position of tile int b = 0; // current y-position of tile for (int i = 0; i < bmp.Width * bmp.Height / 2; i++) { // 4BPP: two pixels per byte tiles[a + b * width].SetPixel(x++, y, buffer[i] >> 4); // left tiles[a + b * width].SetPixel(x++, y, buffer[i] & 0xF); // right // move forward positions if (x >= 8) { x = 0; a++; } if (a >= width) { a = 0; y++; } if (y >= 8) { y = 0; b++; } } } else if (bmp.PixelFormat == PixelFormat.Format8bppIndexed) { // above, modified for 8BPP (one pixel per byte) //palette = new Palette(256); bitDepth = BitDepth.Eight; byte[] buffer = new byte[bmp.Width * bmp.Height]; Marshal.Copy(bmpData.Scan0, buffer, 0, buffer.Length); int x = 0; int y = 0; int a = 0; int b = 0; for (int i = 0; i < bmp.Width * bmp.Height; i++) { tiles[a + b * width].SetPixel(x++, y, buffer[i]); if (x >= 8) { x = 0; a++; } if (a >= width) { a = 0; y++; } if (y >= 8) { y = 0; b++; } } } // unlock the bitmap bmp.UnlockBits(bmpData); }
/// <summary> /// Creates a new <see cref="Sprite"/> of the given size (in tiles) and bit depth. /// </summary> /// <param name="width">The width in tiles.</param> /// <param name="height">The height in tiles.</param> /// <param name="bitDepth">The bit depth.</param> public Sprite(int width, int height, BitDepth bitDepth) { this.tiles = new Tile[width * height]; this.bitDepth = bitDepth; }
/// <summary> /// Creates a new <see cref="Sprite"/> for the given tiles and bit depth. /// </summary> /// <param name="tiles">The source tile data.</param> /// <param name="bitDepth">The bit depth.</param> public Sprite(Tile[] tiles, BitDepth bitDepth) { this.tiles = tiles; this.bitDepth = bitDepth; }
/// <summary> /// Initializes a new instance of the <see cref="Palette"/> class /// for the specified bit depth. /// </summary> /// <param name="color">The color to repeat.</param> /// <param name="bitDepth">The bit depth.</param> public Palette(GbaColor color, BitDepth bitDepth) : this(color, (int)bitDepth) { }