/// <summary> /// /// </summary> /// <param name="clrMismatch"></param> /// <returns></returns> public unsafe bool CheckColorsMatch(out Color clrMismatch) { // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, m_bm.Width, m_bm.Height); BitmapData bmd = m_bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte * pbBase = (byte *)bmd.Scan0.ToPointer(); // Make sure each pixel is an exact match clrMismatch = Color.FromArgb(0, 0, 0); for (int y = 0; y < m_bm.Height; y++) { for (int x = 0; x < m_bm.Width; x++) { byte *pb = pbBase + y * bmd.Stride + x * 3; Color clr = Color.FromArgb(pb[2], pb[1], pb[0]); if (m_pal[m_pal.FindClosestEntry(clr)] != clr) { m_bm.UnlockBits(bmd); clrMismatch = clr; return(false); } } } m_bm.UnlockBits(bmd); return(true); }
public static Bitmap ScaleBitmap(Bitmap bm, double nScale, Palette palFixed) { Color[] aclrSpecial = new Color[] { // side colors Color.FromArgb(0, 116, 232), Color.FromArgb(0, 96, 196), Color.FromArgb(0, 64, 120), Color.FromArgb(0, 48, 92), Color.FromArgb(0, 32, 64), // transparent Color.FromArgb(255, 0, 255), // shadow Color.FromArgb(156, 212, 248), }; Bitmap bmNew = new Bitmap((int)Math.Floor(bm.Width * nScale + 0.5), (int)Math.Floor(bm.Height * nScale + 0.5)); for (int y = 0; y < bmNew.Height; y++) { for (int x = 0; x < bmNew.Width; x++) { double nWidthRatio = (double)bm.Width / (double)bmNew.Width; double xLeft = (double)x * nWidthRatio; double nHeightRatio = (double)bm.Height / (double)bmNew.Height; double yTop = (double)y * nHeightRatio; double xRight = xLeft + 1.0 * nWidthRatio; if (xRight > bm.Width) { xRight = bm.Width; } double yBottom = yTop + 1.0 * nHeightRatio; if (yBottom > bm.Height) { yBottom = bm.Height; } DoubleRect drc = new DoubleRect(xLeft, yTop, xRight, yBottom); Color clrSample = SampleGobBitmap(bm, drc, aclrSpecial, 4); if (palFixed != null) { bool fSpecial = false; foreach (Color clrSpecial in aclrSpecial) { if (clrSample == clrSpecial) { fSpecial = true; break; } } if (!fSpecial) { clrSample = palFixed[palFixed.FindClosestEntry(clrSample)]; } } bmNew.SetPixel(x, y, clrSample); } } return(bmNew); }
public static unsafe void Save(string strFile, Palette pal, string strFileOut) { Bitmap bm = new Bitmap(strFile); // Find the palette index for black int iclrBlack = pal.FindClosestEntry(Color.FromArgb(0, 0, 0)); // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, bm.Width, bm.Height); BitmapData bmd = bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte * pbBase = (byte *)bmd.Scan0.ToPointer(); // Map all the pixels in the bitmap to 'nearest' color palette indices byte[] ab = new byte[((bm.Width + 1) & ~1) * bm.Height]; int i = 0; for (int y = 0; y < bm.Height; y++) { for (int x = 0; x < bm.Width; x++) { byte *pb = pbBase + y * bmd.Stride + x * 3; Color clr = Color.FromArgb(pb[2], pb[1], pb[0]); if (clr == Color.FromArgb(156, 212, 248)) { clr = Color.FromArgb(0, 0, 0); } ab[i++] = (byte)pal.FindClosestEntry(clr); } if ((bm.Width & 1) == 1) { ab[i++] = (byte)iclrBlack; } } bm.UnlockBits(bmd); // Write bitmap header, bits BinaryWriter bwtr = new BinaryWriter(new FileStream(strFileOut, FileMode.Create, FileAccess.Write)); bwtr.Write(Misc.SwapUShort((ushort)((bm.Width + 1) & ~1))); bwtr.Write(Misc.SwapUShort((ushort)bm.Height)); bwtr.Write(ab); bwtr.Close(); // Done bm.Dispose(); }
public static unsafe void Save(string strFile, Palette pal, string strFileOut) { Bitmap bm = new Bitmap(strFile); // Find the palette index for black int iclrBlack = pal.FindClosestEntry(Color.FromArgb(0, 0, 0)); // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, bm.Width, bm.Height); BitmapData bmd = bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte *pbBase = (byte *)bmd.Scan0.ToPointer(); // Map all the pixels in the bitmap to 'nearest' color palette indices byte[] ab = new byte[((bm.Width + 1) & ~1) * bm.Height]; int i = 0; for (int y = 0; y < bm.Height; y++) { for (int x = 0; x < bm.Width; x++) { byte *pb = pbBase + y * bmd.Stride + x * 3; Color clr = Color.FromArgb(pb[2], pb[1], pb[0]); if (clr == Color.FromArgb(156, 212, 248)) clr = Color.FromArgb(0, 0, 0); ab[i++] = (byte)pal.FindClosestEntry(clr); } if ((bm.Width & 1) == 1) ab[i++] = (byte)iclrBlack; } bm.UnlockBits(bmd); // Write bitmap header, bits BinaryWriter bwtr = new BinaryWriter(new FileStream(strFileOut, FileMode.Create, FileAccess.Write)); bwtr.Write(Misc.SwapUShort((ushort)((bm.Width + 1) & ~1))); bwtr.Write(Misc.SwapUShort((ushort)bm.Height)); bwtr.Write(ab); bwtr.Close(); // Done bm.Dispose(); }
public static Bitmap ScaleBitmap(Bitmap bm, double nScale, Palette palFixed) { Color[] aclrSpecial = new Color[] { // side colors Color.FromArgb(0, 116, 232), Color.FromArgb(0, 96, 196), Color.FromArgb(0, 64, 120), Color.FromArgb(0, 48, 92), Color.FromArgb(0, 32, 64), // transparent Color.FromArgb(255, 0, 255), // shadow Color.FromArgb(156, 212, 248), }; Bitmap bmNew = new Bitmap((int)Math.Floor(bm.Width * nScale + 0.5), (int)Math.Floor(bm.Height * nScale + 0.5)); for (int y = 0; y < bmNew.Height; y++) { for (int x = 0; x < bmNew.Width; x++) { double nWidthRatio = (double)bm.Width / (double)bmNew.Width; double xLeft = (double)x * nWidthRatio; double nHeightRatio = (double)bm.Height / (double)bmNew.Height; double yTop = (double)y * nHeightRatio; double xRight = xLeft + 1.0 * nWidthRatio; if (xRight > bm.Width) xRight = bm.Width; double yBottom = yTop + 1.0 * nHeightRatio; if (yBottom > bm.Height) yBottom = bm.Height; DoubleRect drc = new DoubleRect(xLeft, yTop, xRight, yBottom); Color clrSample = SampleGobBitmap(bm, drc, aclrSpecial, 4); if (palFixed != null) { bool fSpecial = false; foreach (Color clrSpecial in aclrSpecial) { if (clrSample == clrSpecial) { fSpecial = true; break; } } if (!fSpecial) clrSample = palFixed[palFixed.FindClosestEntry(clrSample)]; } bmNew.SetPixel(x, y, clrSample); } } return bmNew; }
static unsafe void Main(string[] args) { // Get parameters Palette palIn = new Palette(args[0]); string strFileOut = args[1]; double dAlpha = Double.Parse(args[2]); // Create mapping byte[] ab = new byte[palIn.Length]; Palette palInHSB = new Palette(palIn.Length); for (int iclr = 0; iclr < palIn.Length; iclr++) { Color clr = palIn[iclr]; double h = clr.GetHue(); double s = clr.GetSaturation(); double l = clr.GetBrightness(); double r; double g; double b; MyHSLtoRGB(h, s, l * dAlpha, &r, &g, &b); Color clrShadow = Color.FromArgb((int)(r * 255.0), (int)(g * 255.0), (int)(b * 255.0)); ab[iclr] = (byte)palIn.FindClosestEntry(clrShadow); } // Write palette mapping Stream stm = new FileStream(strFileOut, FileMode.Create, FileAccess.Write, FileShare.None); BinaryWriter bwtr = new BinaryWriter(stm); bwtr.Write(ab); bwtr.Close(); #if false // Check it Palette palCheck = new Palette(palIn.Length); for (int iclr = 0; iclr < palIn.Length; iclr++) palCheck[iclr] = palIn[ab[iclr]]; palCheck.SaveJasc("shadow.pal"); #endif }
public void SetPalette(Palette pal, bool fColorMatch) { m_pal = pal; SetModified(true); if (!fColorMatch) return; ArrayList alsColors = new ArrayList(); foreach (Template tmpl in m_alsTemplates) { Bitmap bm = tmpl.Bitmap; bool[,] afOccupancy = tmpl.OccupancyMap; int ctx = afOccupancy.GetLength(1); int cty = afOccupancy.GetLength(0); for (int ty = 0; ty < cty; ty++) { for (int tx = 0; tx < ctx; tx++) { if (!afOccupancy[ty, tx]) continue; int xOrigin = tx * m_sizTile.Width; int yOrigin = ty * m_sizTile.Height; for (int y = yOrigin; y < yOrigin + m_sizTile.Height; y++) { for (int x = xOrigin; x < xOrigin + m_sizTile.Width; x++) { Color clrOld = bm.GetPixel(x, y); Color clrNew = pal[pal.FindClosestEntry(clrOld)]; bm.SetPixel(x, y, clrNew); } } } } TemplateDocTemplate doct = (TemplateDocTemplate)m_doct; doct.OnTemplateChanged(this, "Bitmap", tmpl.Name, null); } }
void WriteMiniTiles(BinaryWriter bwtr, Palette pal, TemplateDoc tmpd, int cx, bool fNext, double nAreaBackgroundThreshold, double nLuminanceMultBackground, double nSaturationMultBackground, double nLuminanceMultForeground, double nSaturationMultForeground) { // struct MiniTileSetHeader { // mtshdr // ushort offNext; // ushort cTiles; // ushort cxTile; // ushort cyTile; // }; ushort offNext = 0; if (fNext) offNext = (ushort)(8 + m_alsTileData.Count * cx * cx); bwtr.Write(Misc.SwapUShort(offNext)); bwtr.Write(Misc.SwapUShort((ushort)m_alsTileData.Count)); bwtr.Write(Misc.SwapUShort((ushort)cx)); bwtr.Write(Misc.SwapUShort((ushort)cx)); // If a background template exists, use it to distinguish foreground from background objects for better minimaps Size sizTile = tmpd.TileSize; ArrayList alsColors = new ArrayList(); Template tmplBackground = tmpd.GetBackgroundTemplate(); if (tmplBackground != null && nAreaBackgroundThreshold >= 0.0) { // Get despeckled hue map of background, calc mean and // std dev for filtering purposes Bitmap bmHueBackground = TemplateTools.MakeHueMap(tmplBackground.Bitmap); TemplateTools.DespeckleGrayscaleBitmap(bmHueBackground, 9, 50); double nMean = TemplateTools.CalcGrayscaleMean(bmHueBackground); double nStdDev = TemplateTools.CalcGrayscaleStandardDeviation(bmHueBackground, nMean); // Go through each tile, first make a mask that'll delineate foreground from background Bitmap bmTile = new Bitmap(sizTile.Width, sizTile.Height); foreach (TileData td in m_alsTileData) { // Need to turn data back into a bitmap - doh! for (int y = 0; y < sizTile.Height; y++) { for (int x = 0; x < sizTile.Width; x++) { Color clr = (Color)td.aclr[y * sizTile.Width + x]; bmTile.SetPixel(x, y, clr); } } // Create mask which'll replace background with transparent color (255, 0, 255) Bitmap bmMask = TemplateTools.MakeHueMap(bmTile); TemplateTools.DespeckleGrayscaleBitmap(bmMask, 9, 50); TemplateTools.SubtractGrayscaleDistribution(bmMask, nMean, nStdDev); // Now scale tile down to desired size, using mask as input Bitmap bmScaled = TemplateTools.ScaleTemplateBitmap(bmTile, bmMask, cx, cx, nAreaBackgroundThreshold, nLuminanceMultBackground, nSaturationMultBackground, nLuminanceMultForeground, nSaturationMultForeground); // Grab the data for (int y = 0; y < cx; y++) { for (int x = 0; x < cx; x++) { alsColors.Add(bmScaled.GetPixel(x, y)); } } bmScaled.Dispose(); bmMask.Dispose(); } } else { // No background template; just scale Bitmap bmTile = new Bitmap(sizTile.Width, sizTile.Height); foreach (TileData td in m_alsTileData) { // Need to turn data back into a bitmap - doh! for (int y = 0; y < sizTile.Height; y++) { for (int x = 0; x < sizTile.Width; x++) { Color clr = (Color)td.aclr[y * sizTile.Width + x]; bmTile.SetPixel(x, y, clr); } } // Now scale tile down to desired size, using mask as input Bitmap bmScaled = TemplateTools.ScaleTemplateBitmap(bmTile, null, cx, cx, 1.0, 1.0, 1.0, 1.0, 1.0); // Grab the data for (int y = 0; y < cx; y++) { for (int x = 0; x < cx; x++) { alsColors.Add(bmScaled.GetPixel(x, y)); } } bmScaled.Dispose(); } } // Palette match and write results foreach (Color clr in alsColors) bwtr.Write((byte)pal.FindClosestEntry(clr)); }
unsafe int[][] GetScans(Bitmap bm) { // Special colors int[][] aaiclrScans = new int[m_cy][]; // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, m_cx, m_cy); BitmapData bmd = bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte * pbBase = (byte *)bmd.Scan0.ToPointer(); for (int y = 0; y < m_cy; y++) { int[] aiclrScan = new int[m_cx]; for (int x = 0; x < m_cx; x++) { // Get color byte *pb = pbBase + y * bmd.Stride + x * 3; Color clr = Color.FromArgb(pb[2], pb[1], pb[0]); if (clr == s_clrTransparent) { aiclrScan[x] = s_iclrTransparent; continue; } if (clr == s_clrShadow) { aiclrScan[x] = s_iclrShadow; continue; } if (clr == s_clrSideIndex0) { aiclrScan[x] = s_iclrSideFirst + 0; continue; } if (clr == s_clrSideIndex1) { aiclrScan[x] = s_iclrSideFirst + 1; continue; } if (clr == s_clrSideIndex2) { aiclrScan[x] = s_iclrSideFirst + 2; continue; } if (clr == s_clrSideIndex3) { aiclrScan[x] = s_iclrSideFirst + 3; continue; } if (clr == s_clrSideIndex4) { aiclrScan[x] = s_iclrSideFirst + 4; continue; } aiclrScan[x] = m_pal.FindClosestEntry(clr); } aaiclrScans[y] = aiclrScan; } bm.UnlockBits(bmd); return(aaiclrScans); }
static unsafe int Main(string[] astrArgs) { // Command-line argument processing if (astrArgs.Length == 0) { PrintHelp(); return 0; } for (int i = 0; i < astrArgs.Length; i++) { switch (astrArgs[i]) { case "-?": PrintHelp(); return 0; case "-p": gstrPalette = astrArgs[++i]; gpal = new Palette(gstrPalette); break; case "-6": gf6bitRGB = true; break; default: if (astrArgs[i][0] == '-') { Console.WriteLine("Error: invalid flag '{0}'", astrArgs[i]); return -1; } // Assume all 'unassociated' arguments are input filenames (potentially wildcarded) string strDir = Path.GetDirectoryName(astrArgs[i]); if (strDir == "") strDir = "."; string[] astrFileNames = Directory.GetFiles(strDir, Path.GetFileName(astrArgs[i])); if (astrFileNames.Length == 0) { gstrcFileNames.Add(astrArgs[i]); } else { foreach (string strFileName in astrFileNames) { if (strFileName.ToLower().EndsWith(".ani")) { string strT = Path.GetDirectoryName(strFileName) + @"\" + Path.GetFileNameWithoutExtension(strFileName) + @"\*.png"; string[] astrT = Directory.GetFiles(Path.GetDirectoryName(strT), Path.GetFileName(strT)); gstrcFileNames.AddRange(astrT); } else { gstrcFileNames.Add(strFileName); } } } break; } } if (gpal == null) { Console.WriteLine("A valid palette must be specified via the '-p' switch"); return -1; } if (gstrcFileNames.Count == 0) { Console.WriteLine("Error: no files specified"); return -1; } int nReturnValue = 0; Color clrShadow = Color.FromArgb(156, 212, 248); Console.Write("Verifying bitmap colors..."); foreach (string strFileName in gstrcFileNames) { Hashtable htInvalidColors = new Hashtable(); Bitmap bm = null; try { bm = new Bitmap(strFileName); } catch { Console.WriteLine("Error: {0} is not a recognized bitmap or palette file", strFileName); continue; } Color clrTransparent = bm.GetPixel(0, 0); if (gf6bitRGB) clrTransparent = Color.FromArgb(clrTransparent.R & 0xfc, clrTransparent.G & 0xfc, clrTransparent.B & 0xfc); // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, bm.Width, bm.Height); BitmapData bmd = bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte *pbBase = (byte *)bmd.Scan0.ToPointer(); for (int y = 0; y < bm.Height; y++) { for (int x = 0; x < bm.Width; x++) { byte *pb = pbBase + y * bmd.Stride + x * 3; Color clr; if (gf6bitRGB) clr = Color.FromArgb(pb[2] & 0xfc, pb[1] & 0xfc, pb[0] & 0xfc); else clr = Color.FromArgb(pb[2], pb[1], pb[0]); int i = gpal.FindClosestEntry(clr); if (gpal[i] != clr && clr != clrShadow && clr != clrTransparent && !htInvalidColors.ContainsKey(clr)) htInvalidColors.Add(clr, clr); } } bm.UnlockBits(bmd); // Report any invalid colors if (htInvalidColors.Count != 0) { if (nReturnValue == 0) Console.WriteLine(); nReturnValue = -1; int cclr = htInvalidColors.Count; Color[] aclr = new Color[cclr]; htInvalidColors.Values.CopyTo(aclr, 0); Console.Write("{0} contains {1} invalid color{2} (", Path.GetFileName(strFileName), cclr, cclr == 1 ? "" : "s"); for (int i = 0; i < aclr.Length; i++) { Color clr = aclr[i]; Console.Write("{0},{1},{2}", clr.R, clr.G, clr.B); if (i != aclr.Length - 1) Console.Write(", "); } Console.WriteLine(")"); } } if (nReturnValue == 0) Console.WriteLine("done"); return nReturnValue; }