private void choosePalette_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.Title = "Select file"; openFileDialog1.CheckFileExists = true; openFileDialog1.CheckPathExists = true; openFileDialog1.Filter = "Nitro Palette (*.nbfp)|*.nbfp"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { activeNbfp = new nbfpfile(); activeNbfp.form1 = form1; activeNbfp.filepath = openFileDialog1.FileName; activeNbfp.filebytes = File.ReadAllBytes(activeNbfp.filepath); activeNbfp.Load(); } }
private void importFromPNG_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.Title = "Select image file"; openFileDialog1.CheckFileExists = true; openFileDialog1.CheckPathExists = true; openFileDialog1.Filter = "PNG image (*.png)|*.png"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { activeNbfc = new nbfcTilesetFile(); activeNbfs = new mpbfile(); activeNbfp = new nbfpfile(); // activeNbfs.editorForm = this; Bitmap image = (Bitmap)Image.FromFile(openFileDialog1.FileName); //check dimensions if (image.Width % 8 != 0) { MessageBox.Show("Image width must be a multiple of 8.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } if (image.Height % 8 != 0) { MessageBox.Show("Image height must be a multiple of 8.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } //check palette List <Color> palette = new List <Color>(); for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { Color newColour = image.GetPixel(x, y); if (!palette.Contains(newColour)) { palette.Add(newColour); } if (palette.Count > 256) { MessageBox.Show("The image must not have more than 256 colours.", "Too many colours", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } } if (palette.Count < 256 && !palette.Contains(Color.FromArgb(0xFF, 0xFF, 0x00, 0xFF)) && !palette.Contains(Color.FromArgb(0x00, 0xFF, 0x00, 0xFF))) //if there's space for it, sneakily add the magenta alpha anyway { palette.Add(Color.FromArgb(0xFF, 0xFF, 0x00, 0xFF)); } MessageBox.Show("Alpha colour is enforced as RGB 0xFF00FF (a bright magenta). If you want transparency in your image, use this colour.", "Notice", MessageBoxButtons.OK, MessageBoxIcon.Information); TSBAlphaColour = Color.FromArgb(0xFF, 0xFF, 0x00, 0xFF); //swap the alpha colour to the start for (int c = 0; c < palette.Count; c++) { if ((palette[c].R & 0xF8) == (TSBAlphaColour.R & 0xF8) && (palette[c].G & 0xF8) == (TSBAlphaColour.G & 0xF8) && (palette[c].B & 0xF8) == (TSBAlphaColour.B & 0xF8)) { //swap the first slot colour here, and put the alpha colour in the first slot instead palette[c] = palette[0]; palette[0] = TSBAlphaColour; break; } } //truncate colours TSBAlphaColour = Color.FromArgb(0xFF, TSBAlphaColour.R & 0xF8, TSBAlphaColour.G & 0xF8, TSBAlphaColour.B & 0xF8); for (int c = 0; c < palette.Count; c++) { palette[c] = Color.FromArgb(0xFF, palette[c].R & 0xF8, palette[c].G & 0xF8, palette[c].B & 0xF8); } //turn image into tiles activeNbfp.palette = palette.ToArray(); byte[] NBFCimage = (form1.ImageToNBFC(image, 8, activeNbfp.palette)); NBFCimage.Reverse(); List <Tile> tiles = new List <Tile>(); int width_in_tiles = image.Width / 8; int height_in_tiles = image.Height / 8; int pos = 0; List <Tile> uniqueTiles = new List <Tile>(); for (int y = 0; y < height_in_tiles; y++) { for (int x = 0; x < width_in_tiles; x++) { //make a new tile from the current pos in the image Tile newTile = new Tile(); for (int i = 7; i >= 0; i--) { Array.Copy(NBFCimage, pos + (image.Width * i), newTile.tileImage, 8 * i, 8); } //now that we have the tile, compare it to the other tiles for (int t = 0; t < tiles.Count; t++) { if (tiles[t].hasSimilarTile) //only use tiles that aren't already references to other tiles { continue; } int tileSimilarlity = AreTilesSimilar(newTile, tiles[t]); if (tileSimilarlity > 0) //if they are similar (i.e. identical but one of them is a mirror of the other) { newTile.hasSimilarTile = true; newTile.SimilarTile = tiles[t]; if (tileSimilarlity == 1) //then they are just the same tile { } else if (tileSimilarlity == 2) //then they are the same but one of them is X flipped { newTile.flipX = true; } else if (tileSimilarlity == 3) //then they are the same but one of them is Y flipped { newTile.flipY = true; } else if (tileSimilarlity == 4) //then they are the same but one of them is flipped on both X and Y { newTile.flipX = true; newTile.flipY = true; } break; } } if (!newTile.hasSimilarTile) { uniqueTiles.Add(newTile); } tiles.Add(newTile); pos += 8; } if (pos % image.Width == 0) { pos += image.Width * 7; } } //now we should have a list of tiles, some of which are mirrors of each other if applicable activeNbfc.filebytes = new byte[uniqueTiles.Count * 64]; //now write palette to nbfp activeNbfp.filebytes = new byte[0x200]; for (int c = 0; c < palette.Count; c++) { ushort ABGR1555Colour = form1.ColorToABGR1555(palette[c]); activeNbfp.filebytes[(c * 2)] = (byte)ABGR1555Colour; activeNbfp.filebytes[(c * 2) + 1] = (byte)(ABGR1555Colour >> 8); } //now write tiles to tsb, but only the ones that are their own tile and not just referencing another one int tileWritingPos = 0x00; for (int t = 0; t < uniqueTiles.Count; t++) { if (!uniqueTiles[t].hasSimilarTile) //only process it if it's a master tile { foreach (Byte b in uniqueTiles[t].tileImage) { activeNbfc.filebytes[tileWritingPos] = b; tileWritingPos++; } } } //MPB activeNbfs.filebytes = new byte[tiles.Count * 2]; for (int t = 0; t < tiles.Count; t++) { ushort tileDescriptor = 0; if (tiles[t].hasSimilarTile) { //then write a reference to the similar tile instead tileDescriptor = (ushort)uniqueTiles.IndexOf(tiles[t].SimilarTile); if (tiles[t].flipX) { tileDescriptor |= 0x0400; } if (tiles[t].flipY) { tileDescriptor |= 0x0800; } } else //otherwise, just write this tile normally { tileDescriptor = (ushort)uniqueTiles.IndexOf(tiles[t]); } activeNbfs.filebytes[(t * 2)] = (byte)tileDescriptor; activeNbfs.filebytes[(t * 2) + 1] = (byte)(tileDescriptor >> 8); } LoadBoth(); } }