public byte[] doRequest(byte type, byte[] data = null, File f = null) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); if (data == null) { bout.writeInt(1); bout.writeByte(type); } else { bout.writeInt(data.Length+1); bout.writeByte(type); bout.write(data); } byte[] aout = bout.getArray(); stream.Write(aout, 0, aout.Length); stream.Flush(); byte[] resp = readBytes(8); ByteArrayInputStream bin = new ByteArrayInputStream(resp); int error = bin.readInt(); int len = bin.readInt(); resp = readBytes(len); if (error == 2) throw new AlreadyEditingException(f); if (error != 0) { ByteArrayInputStream i = new ByteArrayInputStream(resp); string s = i.ReadString(); throw new Exception("Network error: " + s); } return resp; }
public byte[] doRequest(byte type, byte[] data = null, File f = null) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); if (data == null) { bout.writeInt(1); bout.writeByte(type); } else { bout.writeInt(data.Length + 1); bout.writeByte(type); bout.write(data); } byte[] aout = bout.getArray(); stream.Write(aout, 0, aout.Length); stream.Flush(); byte[] resp = readBytes(8); ByteArrayInputStream bin = new ByteArrayInputStream(resp); int error = bin.readInt(); int len = bin.readInt(); resp = readBytes(len); if (error == 2) { throw new AlreadyEditingException(f); } if (error != 0) { ByteArrayInputStream i = new ByteArrayInputStream(resp); string s = i.ReadString(); throw new Exception("Network error: " + s); } return(resp); }
/*public ImageTexeler(Bitmap img, int paletteMaxNum) * { * this.img = img; * * int tx = img.Width / 4; * int ty = img.Height / 4; * palettes = new Color[tx * ty][]; * paletteCounts = new int[tx * ty]; * paletteNumbers = new int[tx, ty]; * paletteDiffs = new float[tx * ty, tx * ty]; * * int palNum = 0; * for (int x = 0; x < tx; x++) * for (int y = 0; y < ty; y++) * { * ImageIndexerFast iif = new ImageIndexerFast(img, x * 4, y * 4); * palettes[palNum] = iif.palette; * paletteNumbers[x, y] = palNum; * paletteCounts[palNum] = 1; * int similar = calcPaletteDiffs(palNum); * /* if (similar != -1) * { * paletteCounts[palNum] = 0; * paletteCounts[similar]++; * paletteNumbers[x, y] = similar; * } * * palNum++; * } * * while (countUsedPalettes() > paletteMaxNum) * { * Console.Out.WriteLine(countUsedPalettes()); * int besta = -1; * int bestb = -1; * float bestDif = float.MaxValue; * * * //Find the two most similar palettes * for (int i = 0; i < palettes.Length; i++) * { * if (paletteCounts[i] == 0) continue; * for (int j = 0; j < palettes.Length; j++) * { * if (i == j) continue; * if (paletteCounts[j] == 0) continue; * * if (paletteDiffs[i, j] < bestDif) * { * bestDif = paletteDiffs[i, j]; * besta = j; * bestb = i; * } * } * } * * //Merge the Palettes!!! * palettes[besta] = palMerge(palettes[besta], palettes[bestb]); * calcPaletteDiffs(besta); * paletteCounts[besta] += paletteCounts[bestb]; * paletteCounts[bestb] = 0; * * for (int x = 0; x < tx; x++) * for (int y = 0; y < ty; y++) * if (paletteNumbers[x, y] == bestb) * paletteNumbers[x, y] = besta; * } * * * * //CREATE THE FINAL PAL * int currNum = 0; * finalPalette = new Color[paletteMaxNum * 4]; * int[] newPalNums = new int[palettes.Length]; * for (int i = 0; i < palettes.Length; i++) * { * if (paletteCounts[i] != 0) * { * transparentToTheEnd(palettes[i]);// * newPalNums[i] = currNum; * Array.Copy(palettes[i], 0, finalPalette, currNum * 4, 4); * currNum++; * } * } * * ByteArrayOutputStream texDat = new ByteArrayOutputStream(); * ByteArrayOutputStream f5Dat = new ByteArrayOutputStream(); * for (int y = 0; y < ty; y++) * for (int x = 0; x < tx; x++) * { * //Find out if texel has transparent. * * bool hasTransparent = false; * for (int yy = 0; yy < 4; yy++) * for (int xx = 0; xx < 4; xx++) * { * Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); * if (coll.A < 128) * hasTransparent = true; * } * * //WRITE THE IMAGE DATA * for (int yy = 0; yy < 4; yy++) * { * byte b = 0; * byte pow = 1; * for (int xx = 0; xx < 4; xx++) * { * Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); * byte col; * if (coll.A < 128) * { * col = 3; * } * else * { * col = (byte)ImageIndexer.closest(coll, palettes[paletteNumbers[x, y]]); * if (col == 3) { col = 2; } * } * b |= (byte)(pow * col); * pow *= 4; * } * texDat.writeByte(b); * } * * * //WRITE THE FORMAT-5 SPECIFIC DATA * ushort dat = (ushort)(newPalNums[paletteNumbers[x, y]] * 2); * if (!hasTransparent || !ContainsTransparent(img)) * { * dat |= 2 << 14; * } * f5Dat.writeUShort(dat); * } * * f5data = f5Dat.getArray(); * texdata = texDat.getArray(); * * }*/ public ImageTexeler(Bitmap img, int paletteMaxNum, ref System.ComponentModel.BackgroundWorker bw, bool color2 = false) { this.color2 = false; color2 = false; //this.color2 = color2; //bool trans = true;//ContainsTransparent(img); Bitmap im = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format64bppPArgb); using (Graphics gr = Graphics.FromImage(im)) { gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gr.DrawImage(img, 0, 0); } this.img = im; LockBitmap iii = new LockBitmap(img); iii.LockBits(); int tx = img.Width / 4; int ty = img.Height / 4; palettes = new List <Color[]>(); //[tx * ty][]; paletteCounts = new List <int>(); //new int[tx * ty]; paletteNumbers = new int[tx, ty]; paletteDiffs = new float[tx * ty, tx *ty]; double add = 18d / (double)(tx * ty); double Progress = 10; int palNum = 0; double percent = 0; double add2 = 100d / (double)(tx * ty); for (int x = 0; x < tx; x++) { for (int y = 0; y < ty; y++) { Bitmap ni = new Bitmap(4, 4 /*, System.Drawing.Imaging.PixelFormat.Format16bppRgb555*/); /*using (Graphics gr = Graphics.FromImage(ni)) * { * //gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; * //gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; * //gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; * //gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; * gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;//.AntiAlias; * gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; * gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; * gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; * * gr.DrawImage(this.img, new Rectangle(0, 0, 4, 4), new Rectangle(x * 4, y * 4, 4, 4), GraphicsUnit.Pixel); * }*/ LockBitmap nn = new LockBitmap(ni); nn.LockBits(); bool haveTransparent = false; for (int x1 = 0; x1 < 4; x1++) { for (int y1 = 0; y1 < 4; y1++) { Color c = iii.GetPixel(x * 4 + x1, y * 4 + y1); nn.SetPixel(x1, y1, c); if (c.A < 128) { haveTransparent = true; //goto end; } } } //end: nn.UnlockBits(); List <Color> pal1 = new List <Color>(); pal1.AddRange(ImageIndexer.createPaletteForImage(ni, 4, haveTransparent)); //if(haveTransparent){pal1.Add(Color.Transparent);} Color[] pal = pal1.ToArray(); //ImageIndexer.createPaletteForImage(ni, 4, false); transparentToTheEnd(pal); //if (haveTransparent) //{ // pal[0] = Color.Transparent; //} //ImageIndexerFast iif = new ImageIndexerFast(img, x * 4, y * 4); int con = contains(palettes.ToArray(), pal); if (con != -1) { paletteNumbers[x, y] = con; //paletteCounts.Add(1); } else { palettes.Add(pal); //[palNum] = pal;//iif.palette; paletteNumbers[x, y] = palettes.Count - 1; paletteCounts.Add(1); //[palNum] = 1; calcPaletteDiffs(palettes.Count - 1); } //int similar = calcPaletteDiffs(palNum); // if (similar != -1) // { // paletteCounts[palNum] = 0; // paletteCounts[similar]++; // paletteNumbers[x, y] = similar; // } palNum++; Progress += add; bw.ReportProgress((int)Progress, "Generating Picture " + percent.ToString("000") + "%"); percent += add2; if (bw.CancellationPending) { bw.ReportProgress(0, "Canceled"); return; } } } percent = 0; add2 = 100d / (((double)countUsedPalettes() - (double)paletteMaxNum)); add = 74d / (((double)countUsedPalettes() - (double)paletteMaxNum)); //double iw = 0; while (countUsedPalettes() > paletteMaxNum) { //iw += 1; //Console.Out.WriteLine(countUsedPalettes()); int besta = -1; int bestb = -1; float bestDif = float.MaxValue; //Find the two most similar palettes for (int i = 0; i < palettes.Count; i++) { if (paletteCounts[i] == 0) { continue; } for (int j = 0; j < palettes.Count; j++) { if (i == j) { continue; } if (paletteCounts[j] == 0) { continue; } if (paletteDiffs[i, j] < bestDif) { bestDif = paletteDiffs[i, j]; besta = j; bestb = i; } } } //Merge the Palettes!!! palettes[besta] = palMerge(palettes[besta], palettes[bestb]); calcPaletteDiffs(besta); paletteCounts[besta] += paletteCounts[bestb]; paletteCounts[bestb] = 0; for (int x = 0; x < tx; x++) { for (int y = 0; y < ty; y++) { if (paletteNumbers[x, y] == bestb) { paletteNumbers[x, y] = besta; } } } Progress += add; percent += add2; bw.ReportProgress((int)Progress, "Generating Palette " + percent.ToString("000") + "%"); if (bw.CancellationPending) { bw.ReportProgress(0, "Canceled"); return; } } //CREATE THE FINAL PAL int currNum = 0; finalPalette = new Color[countUsedPalettes() * 4]; int[] newPalNums = new int[palettes.Count]; for (int i = 0; i < palettes.Count; i++) { if (paletteCounts[i] != 0) { transparentToTheEnd(palettes[i]);// newPalNums[i] = currNum; Array.Copy(palettes[i], 0, finalPalette, currNum * 4, 4); currNum++; } } ByteArrayOutputStream texDat = new ByteArrayOutputStream(); ByteArrayOutputStream f5Dat = new ByteArrayOutputStream(); for (int y = 0; y < ty; y++) { for (int x = 0; x < tx; x++) { //Find out if texel has transparent. bool hasTransparent = false; for (int yy = 0; yy < 4; yy++) { for (int xx = 0; xx < 4; xx++) { Color coll = iii.GetPixel(x * 4 + xx, y * 4 + yy); if (coll.A < 128) { hasTransparent = true; goto End; } } } End: //WRITE THE IMAGE DATA for (int yy = 0; yy < 4; yy++) { byte b = 0; byte pow = 1; for (int xx = 0; xx < 4; xx++) { Color coll = iii.GetPixel(x * 4 + xx, y * 4 + yy); byte col; if (coll.A < 128) { col = 3; } else { List <Color> colo = new List <Color>(); colo.AddRange(palettes[paletteNumbers[x, y]]); if (hasTransparent) { colo.RemoveAt(3); } col = (byte)ImageIndexer.closest(coll, colo.ToArray()); //if (col == 3) { col = 2; } } b |= (byte)(pow * col); pow *= 4; } texDat.writeByte(b); } //WRITE THE FORMAT-5 SPECIFIC DATA ushort dat = (ushort)(newPalNums[paletteNumbers[x, y]] * 2); if (!hasTransparent /* || !ContainsTransparent(img)*/) { dat |= 2 << 14; } f5Dat.writeUShort(dat); } } iii.UnlockBits(); f5data = f5Dat.getArray(); texdata = texDat.getArray(); }
static void Main(string[] args) { Console.WriteLine("Image to ENPG Batch Encoder - v1.0"); Console.WriteLine("By Mariomaster using NSMBe's Image Indexer and LZ77 compressor"); Console.WriteLine(); if (args.Length == 0) { Console.WriteLine("Drag 256x256 Image files onto this application to convert them to NSMB's ENPG format."); Console.WriteLine(); Console.Write("Press any key to exit..."); Console.ReadKey(); return; } bool compress = false; bool forCredits = false; checkCompress: Console.Write("Do you want to LZ77 compress the ENPGs? (y/n): "); char rc = Console.ReadKey().KeyChar; Console.WriteLine(); if (rc == 'y' || rc == 'Y') { compress = true; } else if (rc == 'n' || rc == 'N') { compress = false; } else { goto checkCompress; } checkForCredits: Console.Write("Are the Images intended as Credit Images (Reserve first 5 Palette slots)? (y/n): "); char rcr = Console.ReadKey().KeyChar; Console.WriteLine(); if (rcr == 'y' || rcr == 'Y') { forCredits = true; } else if (rcr == 'n' || rcr == 'N') { forCredits = false; } else { goto checkForCredits; } Console.WriteLine(); Console.WriteLine("Encoding " + args.Length + " images."); Console.WriteLine(); int successCount = 0; foreach (string path in args) { if (!File.Exists(path)) { Console.WriteLine("The file " + path + " does not exist!"); continue; } if (!System.Web.MimeMapping.GetMimeMapping(path).StartsWith("image/")) { Console.WriteLine("The file " + path + " is not an Image!"); continue; } Bitmap bmp = (Bitmap)Image.FromFile(path); if (bmp.Width != 256 || bmp.Height != 256) { Console.WriteLine("The Image " + path + " is not 256x256!"); continue; } string folder = Path.GetDirectoryName(path); string name = Path.GetFileNameWithoutExtension(path); Console.Write("Encoding " + path + "..."); bmp.RotateFlip(RotateFlipType.Rotate90FlipX); int cCount = 256; if (forCredits) { cCount = 251; } Color[] pal = ImageIndexer.createPaletteForImage(bmp, cCount); ByteArrayOutputStream b = new ByteArrayOutputStream(); for (int x = 0; x < bmp.Width; x++) { for (int y = 0; y < bmp.Height; y++) { Color c = bmp.GetPixel(x, y); int i = getClosestColor(pal, c); int writeColor = i; if (forCredits) { if (writeColor > 0) { writeColor += 5; } } b.writeByte((byte)writeColor); } } b.writeUShort(toRGB15(pal[0])); if (forCredits) { for (int i = 0; i < 5; i++) { b.writeUShort(0x0); } } for (int i = 1; i < pal.Length; i++) { b.writeUShort(toRGB15(pal[i])); } if (!Directory.Exists(folder + "\\convert")) { Directory.CreateDirectory(folder + "\\convert"); } var bw = new BinaryWriter(File.Open(folder + "\\convert\\" + name + ".enpg", FileMode.OpenOrCreate)); if (compress) { bw.Write(lz77.LZ77_Compress(b.getArray())); } else { bw.Write(b.getArray()); } bw.Flush(); bw.Close(); successCount++; Console.WriteLine("\rEncoding " + path + " done."); } Console.WriteLine(); Console.Write("Successfully encoded " + successCount + " of " + args.Length + " images. Press any key to exit..."); Console.ReadKey(); }
public ImageTexeler(Bitmap img, int paletteMaxNum) { this.img = img; int tx = img.Width / 4; int ty = img.Height / 4; palettes = new Color[tx * ty][]; paletteCounts = new int[tx * ty]; paletteNumbers = new int[tx, ty]; paletteDiffs = new float[tx * ty, tx *ty]; int palNum = 0; for (int x = 0; x < tx; x++) { for (int y = 0; y < ty; y++) { ImageIndexerFast iif = new ImageIndexerFast(img, x * 4, y * 4); palettes[palNum] = iif.palette; paletteNumbers[x, y] = palNum; paletteCounts[palNum] = 1; int similar = calcPaletteDiffs(palNum); /* if (similar != -1) * { * paletteCounts[palNum] = 0; * paletteCounts[similar]++; * paletteNumbers[x, y] = similar; * } */ palNum++; } } while (countUsedPalettes() > paletteMaxNum) { Console.Out.WriteLine(countUsedPalettes()); int besta = -1; int bestb = -1; float bestDif = float.MaxValue; //Find the two most similar palettes for (int i = 0; i < palettes.Length; i++) { if (paletteCounts[i] == 0) { continue; } for (int j = 0; j < palettes.Length; j++) { if (i == j) { continue; } if (paletteCounts[j] == 0) { continue; } if (paletteDiffs[i, j] < bestDif) { bestDif = paletteDiffs[i, j]; besta = j; bestb = i; } } } //Merge the Palettes!!! palettes[besta] = palMerge(palettes[besta], palettes[bestb]); calcPaletteDiffs(besta); paletteCounts[besta] += paletteCounts[bestb]; paletteCounts[bestb] = 0; for (int x = 0; x < tx; x++) { for (int y = 0; y < ty; y++) { if (paletteNumbers[x, y] == bestb) { paletteNumbers[x, y] = besta; } } } } //CREATE THE FINAL PAL int currNum = 0; finalPalette = new Color[paletteMaxNum * 4]; int[] newPalNums = new int[palettes.Length]; for (int i = 0; i < palettes.Length; i++) { if (paletteCounts[i] != 0) { //transparentToTheEnd(palettes[i]); newPalNums[i] = currNum; Array.Copy(palettes[i], 0, finalPalette, currNum * 4, 4); currNum++; } } ByteArrayOutputStream texDat = new ByteArrayOutputStream(); ByteArrayOutputStream f5Dat = new ByteArrayOutputStream(); for (int y = 0; y < ty; y++) { for (int x = 0; x < tx; x++) { //Find out if texel has transparent. bool hasTransparent = false; for (int yy = 0; yy < 4; yy++) { for (int xx = 0; xx < 4; xx++) { Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); if (coll.A < 128) { hasTransparent = true; } } } //WRITE THE IMAGE DATA for (int yy = 0; yy < 4; yy++) { byte b = 0; byte pow = 1; for (int xx = 0; xx < 4; xx++) { Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); byte col; if (coll.A < 128) { col = 3; } else { col = (byte)ImageIndexer.closest(coll, palettes[paletteNumbers[x, y]]); if (col == 3) { col = 2; } } b |= (byte)(pow * col); pow *= 4; } texDat.writeByte(b); } //WRITE THE FORMAT-5 SPECIFIC DATA ushort dat = (ushort)(newPalNums[paletteNumbers[x, y]] * 2); if (!hasTransparent) { dat |= 2 << 14; } f5Dat.writeUShort(dat); } } f5data = f5Dat.getArray(); texdata = texDat.getArray(); }
public ImageTexeler(Bitmap img, int paletteMaxNum) { this.img = img; int tx = img.Width / 4; int ty = img.Height / 4; palettes = new Color[tx*ty][]; paletteCounts = new int[tx*ty]; paletteNumbers = new int[tx, ty]; paletteDiffs = new float[tx*ty, tx*ty]; int palNum = 0; for(int x = 0; x < tx; x++) for (int y = 0; y < ty; y++) { ImageIndexerFast iif = new ImageIndexerFast(img, x * 4, y * 4); palettes[palNum] = iif.palette; paletteNumbers[x, y] = palNum; paletteCounts[palNum] = 1; int similar = calcPaletteDiffs(palNum); /* if (similar != -1) { paletteCounts[palNum] = 0; paletteCounts[similar]++; paletteNumbers[x, y] = similar; } */ palNum++; } while (countUsedPalettes() > paletteMaxNum) { Console.Out.WriteLine(countUsedPalettes()); int besta = -1; int bestb = -1; float bestDif = float.MaxValue; //Find the two most similar palettes for (int i = 0; i < palettes.Length; i++) { if (paletteCounts[i] == 0) continue; for (int j = 0; j < palettes.Length; j++) { if (i == j) continue; if (paletteCounts[j] == 0) continue; if (paletteDiffs[i, j] < bestDif) { bestDif = paletteDiffs[i, j]; besta = j; bestb = i; } } } //Merge the Palettes!!! palettes[besta] = palMerge(palettes[besta], palettes[bestb]); calcPaletteDiffs(besta); paletteCounts[besta] += paletteCounts[bestb]; paletteCounts[bestb] = 0; for (int x = 0; x < tx; x++) for (int y = 0; y < ty; y++) if (paletteNumbers[x, y] == bestb) paletteNumbers[x, y] = besta; } //CREATE THE FINAL PAL int currNum = 0; finalPalette = new Color[paletteMaxNum*4]; int[] newPalNums = new int[palettes.Length]; for(int i = 0; i < palettes.Length; i++) { if(paletteCounts[i] != 0) { //transparentToTheEnd(palettes[i]); newPalNums[i] = currNum; Array.Copy(palettes[i], 0, finalPalette, currNum*4, 4); currNum++; } } ByteArrayOutputStream texDat = new ByteArrayOutputStream(); ByteArrayOutputStream f5Dat = new ByteArrayOutputStream(); for (int y = 0; y < ty; y++) for (int x = 0; x < tx; x++) { //Find out if texel has transparent. bool hasTransparent = false; for (int yy = 0; yy < 4; yy++) for (int xx = 0; xx < 4; xx++) { Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); if (coll.A < 128) hasTransparent = true; } //WRITE THE IMAGE DATA for (int yy = 0; yy < 4; yy++) { byte b = 0; byte pow = 1; for (int xx = 0; xx < 4; xx++) { Color coll = img.GetPixel(x*4+xx, y*4+yy); byte col; if (coll.A < 128) { col = 3; } else { col = (byte)ImageIndexer.closest(coll, palettes[paletteNumbers[x, y]]); if (col == 3) col = 2; } b |= (byte)(pow * col); pow *= 4; } texDat.writeByte(b); } //WRITE THE FORMAT-5 SPECIFIC DATA ushort dat = (ushort)(newPalNums[paletteNumbers[x, y]] * 2); if(!hasTransparent) dat |= 2 << 14; f5Dat.writeUShort(dat); } f5data = f5Dat.getArray(); texdata = texDat.getArray(); }
/*public ImageTexeler(Bitmap img, int paletteMaxNum) { this.img = img; int tx = img.Width / 4; int ty = img.Height / 4; palettes = new Color[tx * ty][]; paletteCounts = new int[tx * ty]; paletteNumbers = new int[tx, ty]; paletteDiffs = new float[tx * ty, tx * ty]; int palNum = 0; for (int x = 0; x < tx; x++) for (int y = 0; y < ty; y++) { ImageIndexerFast iif = new ImageIndexerFast(img, x * 4, y * 4); palettes[palNum] = iif.palette; paletteNumbers[x, y] = palNum; paletteCounts[palNum] = 1; int similar = calcPaletteDiffs(palNum); /* if (similar != -1) { paletteCounts[palNum] = 0; paletteCounts[similar]++; paletteNumbers[x, y] = similar; } palNum++; } while (countUsedPalettes() > paletteMaxNum) { Console.Out.WriteLine(countUsedPalettes()); int besta = -1; int bestb = -1; float bestDif = float.MaxValue; //Find the two most similar palettes for (int i = 0; i < palettes.Length; i++) { if (paletteCounts[i] == 0) continue; for (int j = 0; j < palettes.Length; j++) { if (i == j) continue; if (paletteCounts[j] == 0) continue; if (paletteDiffs[i, j] < bestDif) { bestDif = paletteDiffs[i, j]; besta = j; bestb = i; } } } //Merge the Palettes!!! palettes[besta] = palMerge(palettes[besta], palettes[bestb]); calcPaletteDiffs(besta); paletteCounts[besta] += paletteCounts[bestb]; paletteCounts[bestb] = 0; for (int x = 0; x < tx; x++) for (int y = 0; y < ty; y++) if (paletteNumbers[x, y] == bestb) paletteNumbers[x, y] = besta; } //CREATE THE FINAL PAL int currNum = 0; finalPalette = new Color[paletteMaxNum * 4]; int[] newPalNums = new int[palettes.Length]; for (int i = 0; i < palettes.Length; i++) { if (paletteCounts[i] != 0) { transparentToTheEnd(palettes[i]);// newPalNums[i] = currNum; Array.Copy(palettes[i], 0, finalPalette, currNum * 4, 4); currNum++; } } ByteArrayOutputStream texDat = new ByteArrayOutputStream(); ByteArrayOutputStream f5Dat = new ByteArrayOutputStream(); for (int y = 0; y < ty; y++) for (int x = 0; x < tx; x++) { //Find out if texel has transparent. bool hasTransparent = false; for (int yy = 0; yy < 4; yy++) for (int xx = 0; xx < 4; xx++) { Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); if (coll.A < 128) hasTransparent = true; } //WRITE THE IMAGE DATA for (int yy = 0; yy < 4; yy++) { byte b = 0; byte pow = 1; for (int xx = 0; xx < 4; xx++) { Color coll = img.GetPixel(x * 4 + xx, y * 4 + yy); byte col; if (coll.A < 128) { col = 3; } else { col = (byte)ImageIndexer.closest(coll, palettes[paletteNumbers[x, y]]); if (col == 3) { col = 2; } } b |= (byte)(pow * col); pow *= 4; } texDat.writeByte(b); } //WRITE THE FORMAT-5 SPECIFIC DATA ushort dat = (ushort)(newPalNums[paletteNumbers[x, y]] * 2); if (!hasTransparent || !ContainsTransparent(img)) { dat |= 2 << 14; } f5Dat.writeUShort(dat); } f5data = f5Dat.getArray(); texdata = texDat.getArray(); }*/ public ImageTexeler(Bitmap img, int paletteMaxNum, ref System.ComponentModel.BackgroundWorker bw, bool color2 = false) { this.color2 = false; color2 = false; //this.color2 = color2; //bool trans = true;//ContainsTransparent(img); Bitmap im = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format64bppPArgb); using (Graphics gr = Graphics.FromImage(im)) { gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gr.DrawImage(img, 0, 0); } this.img = im; LockBitmap iii = new LockBitmap(img); iii.LockBits(); int tx = img.Width / 4; int ty = img.Height / 4; palettes = new List<Color[]>();//[tx * ty][]; paletteCounts = new List<int>();//new int[tx * ty]; paletteNumbers = new int[tx, ty]; paletteDiffs = new float[tx * ty, tx * ty]; double add = 18d / (double)(tx * ty); double Progress = 10; int palNum = 0; double percent = 0; double add2 = 100d / (double)(tx * ty); for (int x = 0; x < tx; x++) for (int y = 0; y < ty; y++) { Bitmap ni = new Bitmap(4, 4/*, System.Drawing.Imaging.PixelFormat.Format16bppRgb555*/); /*using (Graphics gr = Graphics.FromImage(ni)) { //gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; //gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;//.AntiAlias; gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gr.DrawImage(this.img, new Rectangle(0, 0, 4, 4), new Rectangle(x * 4, y * 4, 4, 4), GraphicsUnit.Pixel); }*/ LockBitmap nn = new LockBitmap(ni); nn.LockBits(); bool haveTransparent = false; for (int x1 = 0; x1 < 4; x1++) for (int y1 = 0; y1 < 4; y1++) { Color c = iii.GetPixel(x * 4 + x1, y * 4 + y1); nn.SetPixel(x1, y1, c); if (c.A < 128) { haveTransparent = true; //goto end; } } //end: nn.UnlockBits(); List<Color> pal1 = new List<Color>(); pal1.AddRange(ImageIndexer.createPaletteForImage(ni, 4, haveTransparent)); //if(haveTransparent){pal1.Add(Color.Transparent);} Color[] pal = pal1.ToArray(); //ImageIndexer.createPaletteForImage(ni, 4, false); transparentToTheEnd(pal); //if (haveTransparent) //{ // pal[0] = Color.Transparent; //} //ImageIndexerFast iif = new ImageIndexerFast(img, x * 4, y * 4); int con = contains(palettes.ToArray(), pal); if (con != -1) { paletteNumbers[x, y] = con; //paletteCounts.Add(1); } else { palettes.Add(pal);//[palNum] = pal;//iif.palette; paletteNumbers[x, y] = palettes.Count - 1; paletteCounts.Add(1);//[palNum] = 1; calcPaletteDiffs(palettes.Count - 1); } //int similar = calcPaletteDiffs(palNum); // if (similar != -1) // { // paletteCounts[palNum] = 0; // paletteCounts[similar]++; // paletteNumbers[x, y] = similar; // } palNum++; Progress += add; bw.ReportProgress((int)Progress, "Generating Picture " + percent.ToString("000") + "%"); percent += add2; if (bw.CancellationPending) { bw.ReportProgress(0, "Canceled"); return; } } percent = 0; add2 = 100d / (((double)countUsedPalettes() - (double)paletteMaxNum)); add = 74d / (((double)countUsedPalettes() - (double)paletteMaxNum)); //double iw = 0; while (countUsedPalettes() > paletteMaxNum) { //iw += 1; //Console.Out.WriteLine(countUsedPalettes()); int besta = -1; int bestb = -1; float bestDif = float.MaxValue; //Find the two most similar palettes for (int i = 0; i < palettes.Count; i++) { if (paletteCounts[i] == 0) continue; for (int j = 0; j < palettes.Count; j++) { if (i == j) continue; if (paletteCounts[j] == 0) continue; if (paletteDiffs[i, j] < bestDif) { bestDif = paletteDiffs[i, j]; besta = j; bestb = i; } } } //Merge the Palettes!!! palettes[besta] = palMerge(palettes[besta], palettes[bestb]); calcPaletteDiffs(besta); paletteCounts[besta] += paletteCounts[bestb]; paletteCounts[bestb] = 0; for (int x = 0; x < tx; x++) for (int y = 0; y < ty; y++) if (paletteNumbers[x, y] == bestb) paletteNumbers[x, y] = besta; Progress += add; percent += add2; bw.ReportProgress((int)Progress, "Generating Palette " + percent.ToString("000") + "%"); if (bw.CancellationPending) { bw.ReportProgress(0, "Canceled"); return; } } //CREATE THE FINAL PAL int currNum = 0; finalPalette = new Color[countUsedPalettes() * 4]; int[] newPalNums = new int[palettes.Count]; for (int i = 0; i < palettes.Count; i++) { if (paletteCounts[i] != 0) { transparentToTheEnd(palettes[i]);// newPalNums[i] = currNum; Array.Copy(palettes[i], 0, finalPalette, currNum * 4, 4); currNum++; } } ByteArrayOutputStream texDat = new ByteArrayOutputStream(); ByteArrayOutputStream f5Dat = new ByteArrayOutputStream(); for (int y = 0; y < ty; y++) for (int x = 0; x < tx; x++) { //Find out if texel has transparent. bool hasTransparent = false; for (int yy = 0; yy < 4; yy++) for (int xx = 0; xx < 4; xx++) { Color coll = iii.GetPixel(x * 4 + xx, y * 4 + yy); if (coll.A < 128) { hasTransparent = true; goto End; } } End: //WRITE THE IMAGE DATA for (int yy = 0; yy < 4; yy++) { byte b = 0; byte pow = 1; for (int xx = 0; xx < 4; xx++) { Color coll = iii.GetPixel(x * 4 + xx, y * 4 + yy); byte col; if (coll.A < 128) { col = 3; } else { List<Color> colo = new List<Color>(); colo.AddRange(palettes[paletteNumbers[x, y]]); if (hasTransparent) { colo.RemoveAt(3); } col = (byte)ImageIndexer.closest(coll, colo.ToArray()); //if (col == 3) { col = 2; } } b |= (byte)(pow * col); pow *= 4; } texDat.writeByte(b); } //WRITE THE FORMAT-5 SPECIFIC DATA ushort dat = (ushort)(newPalNums[paletteNumbers[x, y]] * 2); if (!hasTransparent/* || !ContainsTransparent(img)*/) { dat |= 2 << 14; } f5Dat.writeUShort(dat); } iii.UnlockBits(); f5data = f5Dat.getArray(); texdata = texDat.getArray(); }