static unsafe int Main(string[] astrArgs) { #if false while (true) { float h, s, l; float r, g, b; string str = Console.ReadLine(); r = float.Parse(str); str = Console.ReadLine(); g = float.Parse(str); str = Console.ReadLine(); b = float.Parse(str); // r = .5f; g = .5f; b = 1.0f; Misc.RgbToHsl(r, g, b, &h, &s, &l); Console.WriteLine("r: {3}, g: {4}, b: {5} -> h: {0}, s: {1}, l: {2}", h, s, l, r, g, b); Misc.HslToRgb(h, s, l, &r, &g, &b); Console.WriteLine("r: {3}, g: {4}, b: {5} <- h: {0}, s: {1}, l: {2}", h, s, l, r, g, b); } return 0; #endif // 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 "-n": gstrTemplateNames = astrArgs[++i]; break; case "-tc": gstrTileCollection = astrArgs[++i]; break; case "-art": gstrTemplateBitmap = astrArgs[++i]; break; case "-ter": gstrTerrainBitmap = astrArgs[++i]; break; case "-colors": gstrColorsBitmap = astrArgs[++i]; break; case "-ts": gcxTile = int.Parse(astrArgs[++i]); gcyTile = gcxTile; break; default: Console.WriteLine("Error: invalid argument '{0}'", astrArgs[i]); return 1; } } Color clrBlocked = Color.FromArgb(255, 0, 0); Bitmap bmTerrain = null; if (gstrTerrainBitmap != null) bmTerrain = new Bitmap(gstrTerrainBitmap); Bitmap bmColors = null; if (gstrColorsBitmap != null) bmColors = new Bitmap(gstrColorsBitmap); if (gstrTemplateBitmap == null) { Console.WriteLine("Error: A valid source bitmap must be specified"); return -1; } if (gstrOutputPrefix == null) gstrOutputPrefix = Path.GetFileNameWithoutExtension(gstrTemplateBitmap); Console.WriteLine("Reading {0}", gstrTemplateBitmap); Bitmap bmFile = null; try { bmFile = new Bitmap(gstrTemplateBitmap); } catch { Console.WriteLine("Error: {0} is not a recognized bitmap file", gstrTemplateBitmap); return -1; } // Using DrawImage to copy subrectangles of a loaded bitmap doesn't work reliably // due to GDI+'s desire to scale based on Bitmap.Horizontal/VerticalResolution so // we must create a neutral resolution bitmap before doing any DrawImage'ing from it. Console.WriteLine("Creating neutral resolution source bitmap", gstrTemplateBitmap); Bitmap bm = SpiffLib.Misc.NormalizeBitmap(bmFile); bmFile.Dispose(); // The upper-left-most pixel defines the transparent color gclrTransparent = bm.GetPixel(0, 0); // int ctx = bm.Width / gcxTile; int cty = bm.Height / gcyTile; gaCells = new int[ctx, cty]; for (int j = 0; j < cty; j++) { for (int i = 0; i < ctx; i++) { gaCells[i, j] = -1; // -1 = empty } } ArrayList alTemplates = new ArrayList(); Console.WriteLine("Scanning for templates", alTemplates.Count); // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, bm.Width, bm.Height); gbmd = bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte *pbBase = (byte *)gbmd.Scan0.ToPointer(); for (int y = gcyTile, ty = 1; y < bm.Height - gcyTile; y += gcyTile, ty++) { for (int x = gcxTile, tx = 1; x < bm.Width - gcxTile; x += gcxTile, tx++) { byte *pb = pbBase + y * gbmd.Stride + x * 3; Color clr = Color.FromArgb(pb[2], pb[1], pb[0]); if (clr != gclrTransparent && gaCells[tx, ty] == -1) { ArrayList alTiles = new ArrayList(); FloodFill(pbBase, alTiles, tx, ty); alTemplates.Add(alTiles); } } } bm.UnlockBits(gbmd); StreamReader stmrTemplateNames = null; if (gstrTemplateNames != null) stmrTemplateNames = new StreamReader(gstrTemplateNames); Console.WriteLine("Extracting {0} templates", alTemplates.Count); m.DocManager.AddTemplate(new m.TemplateDocTemplate()); m.TemplateDoc tmpd = (m.TemplateDoc)m.DocManager.NewDocument(typeof(m.TemplateDoc), new Object[] { new Size(gcxTile, gcyTile) }); m.Template[] atmpl = new m.Template[alTemplates.Count]; // Create a new bitmap for each template. Empty cells of the template are // filled with the transparent color. int cTiles = 0; int nTemplate = 0; foreach (ArrayList alTiles in alTemplates) { cTiles += alTiles.Count; // Found boundary of template int txMax = -1, tyMax = -1; int txMin = 99999, tyMin = 99999; foreach (Point pt in alTiles) { if (pt.X < txMin) txMin = pt.X; if (pt.X > txMax) txMax = pt.X; if (pt.Y < tyMin) tyMin = pt.Y; if (pt.Y > tyMax) tyMax = pt.Y; } // ctx = txMax + 1 - txMin; cty = tyMax + 1 - tyMin; int cx = ctx * gcxTile; int cy = cty * gcyTile; Bitmap bmTemplate = new Bitmap(cx, cy, PixelFormat.Format24bppRgb); Graphics gTemplate = Graphics.FromImage(bmTemplate); Rectangle rcSrc = new Rectangle(txMin * gcxTile, tyMin * gcyTile, cx, cy); gTemplate.DrawImage(bm, 0, 0, rcSrc, GraphicsUnit.Pixel); string strT; if (gstrTemplateNames != null) { strT = stmrTemplateNames.ReadLine(); if (strT == null) // end of template names reached strT = String.Format("template{0:0#}", nTemplate); } else { strT = String.Format("{0}{1:0#}", gstrOutputPrefix, nTemplate); } if (gstrTileCollection == null) { bmTemplate.Save(strT + ".png", ImageFormat.Png); bmTemplate.Dispose(); } else { m.Template tmpl = new m.Template(tmpd, bmTemplate, strT); if (bmTerrain != null) { tmpl.TerrainMap = new m.TerrainTypes[cty, ctx]; for (int j = 0; j < cty; j++) { for (int i = 0; i < ctx; i++) { if (bmTerrain.GetPixel((txMin + i) * gcxTile, (tyMin + j) * gcyTile) == clrBlocked) tmpl.TerrainMap[j, i] = m.TerrainTypes.Blocked; else tmpl.TerrainMap[j, i] = m.TerrainTypes.Open; } } } if (bmColors != null) { Color[] aclr = new Color[4] { Color.FromArgb(114, 167, 48), // grass Color.FromArgb(81, 142, 118), // cliff Color.FromArgb(1, 172, 254), // water Color.FromArgb(174, 168, 99), // road }; tmpl.TerrainColors = new m.TerrainColors[cty * 2, ctx * 2]; for (int yT = 0; yT < cty * 2; yT++) { for (int xT = 0; xT < ctx * 2; xT++) { Color clr = bmColors.GetPixel(txMin * gcxTile + xT * gcxTile / 2, tyMin * gcyTile + yT * gcyTile / 2); m.TerrainColors tclr = m.TerrainColors.Grass; for (int i = 0; i < aclr.Length; i++) { if (clr == aclr[i]) { tclr = (m.TerrainColors)i; break; } } tmpl.TerrainColors[yT, xT] = tclr; } } } if (strT.ToLower() == "background") tmpd.SetBackgroundTemplate(tmpl); atmpl[nTemplate] = tmpl; } gTemplate.Dispose(); nTemplate++; } if (stmrTemplateNames != null) stmrTemplateNames.Close(); if (gstrTileCollection != null) { Console.WriteLine("Writing templates to {0}", gstrTileCollection); tmpd.AddTemplates(atmpl); tmpd.SaveAs(gstrTileCollection); } Console.WriteLine("{0} tiles total in {1} templates ({2:###,###,###} bytes)", cTiles, alTemplates.Count, cTiles * gcxTile * gcyTile); return 0; }
static unsafe int Main(string[] astrArgs) { #if false while (true) { float h, s, l; float r, g, b; string str = Console.ReadLine(); r = float.Parse(str); str = Console.ReadLine(); g = float.Parse(str); str = Console.ReadLine(); b = float.Parse(str); // r = .5f; g = .5f; b = 1.0f; Misc.RgbToHsl(r, g, b, &h, &s, &l); Console.WriteLine("r: {3}, g: {4}, b: {5} -> h: {0}, s: {1}, l: {2}", h, s, l, r, g, b); Misc.HslToRgb(h, s, l, &r, &g, &b); Console.WriteLine("r: {3}, g: {4}, b: {5} <- h: {0}, s: {1}, l: {2}", h, s, l, r, g, b); } return(0); #endif // 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 "-n": gstrTemplateNames = astrArgs[++i]; break; case "-tc": gstrTileCollection = astrArgs[++i]; break; case "-art": gstrTemplateBitmap = astrArgs[++i]; break; case "-ter": gstrTerrainBitmap = astrArgs[++i]; break; case "-colors": gstrColorsBitmap = astrArgs[++i]; break; case "-ts": gcxTile = int.Parse(astrArgs[++i]); gcyTile = gcxTile; break; default: Console.WriteLine("Error: invalid argument '{0}'", astrArgs[i]); return(1); } } Color clrBlocked = Color.FromArgb(255, 0, 0); Bitmap bmTerrain = null; if (gstrTerrainBitmap != null) { bmTerrain = new Bitmap(gstrTerrainBitmap); } Bitmap bmColors = null; if (gstrColorsBitmap != null) { bmColors = new Bitmap(gstrColorsBitmap); } if (gstrTemplateBitmap == null) { Console.WriteLine("Error: A valid source bitmap must be specified"); return(-1); } if (gstrOutputPrefix == null) { gstrOutputPrefix = Path.GetFileNameWithoutExtension(gstrTemplateBitmap); } Console.WriteLine("Reading {0}", gstrTemplateBitmap); Bitmap bmFile = null; try { bmFile = new Bitmap(gstrTemplateBitmap); } catch { Console.WriteLine("Error: {0} is not a recognized bitmap file", gstrTemplateBitmap); return(-1); } // Using DrawImage to copy subrectangles of a loaded bitmap doesn't work reliably // due to GDI+'s desire to scale based on Bitmap.Horizontal/VerticalResolution so // we must create a neutral resolution bitmap before doing any DrawImage'ing from it. Console.WriteLine("Creating neutral resolution source bitmap", gstrTemplateBitmap); Bitmap bm = SpiffLib.Misc.NormalizeBitmap(bmFile); bmFile.Dispose(); // The upper-left-most pixel defines the transparent color gclrTransparent = bm.GetPixel(0, 0); // int ctx = bm.Width / gcxTile; int cty = bm.Height / gcyTile; gaCells = new int[ctx, cty]; for (int j = 0; j < cty; j++) { for (int i = 0; i < ctx; i++) { gaCells[i, j] = -1; // -1 = empty } } ArrayList alTemplates = new ArrayList(); Console.WriteLine("Scanning for templates", alTemplates.Count); // Lock down bits for speed Rectangle rc = new Rectangle(0, 0, bm.Width, bm.Height); gbmd = bm.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte *pbBase = (byte *)gbmd.Scan0.ToPointer(); for (int y = gcyTile, ty = 1; y < bm.Height - gcyTile; y += gcyTile, ty++) { for (int x = gcxTile, tx = 1; x < bm.Width - gcxTile; x += gcxTile, tx++) { byte *pb = pbBase + y * gbmd.Stride + x * 3; Color clr = Color.FromArgb(pb[2], pb[1], pb[0]); if (clr != gclrTransparent && gaCells[tx, ty] == -1) { ArrayList alTiles = new ArrayList(); FloodFill(pbBase, alTiles, tx, ty); alTemplates.Add(alTiles); } } } bm.UnlockBits(gbmd); StreamReader stmrTemplateNames = null; if (gstrTemplateNames != null) { stmrTemplateNames = new StreamReader(gstrTemplateNames); } Console.WriteLine("Extracting {0} templates", alTemplates.Count); m.DocManager.AddTemplate(new m.TemplateDocTemplate()); m.TemplateDoc tmpd = (m.TemplateDoc)m.DocManager.NewDocument(typeof(m.TemplateDoc), new Object[] { new Size(gcxTile, gcyTile) }); m.Template[] atmpl = new m.Template[alTemplates.Count]; // Create a new bitmap for each template. Empty cells of the template are // filled with the transparent color. int cTiles = 0; int nTemplate = 0; foreach (ArrayList alTiles in alTemplates) { cTiles += alTiles.Count; // Found boundary of template int txMax = -1, tyMax = -1; int txMin = 99999, tyMin = 99999; foreach (Point pt in alTiles) { if (pt.X < txMin) { txMin = pt.X; } if (pt.X > txMax) { txMax = pt.X; } if (pt.Y < tyMin) { tyMin = pt.Y; } if (pt.Y > tyMax) { tyMax = pt.Y; } } // ctx = txMax + 1 - txMin; cty = tyMax + 1 - tyMin; int cx = ctx * gcxTile; int cy = cty * gcyTile; Bitmap bmTemplate = new Bitmap(cx, cy, PixelFormat.Format24bppRgb); Graphics gTemplate = Graphics.FromImage(bmTemplate); Rectangle rcSrc = new Rectangle(txMin * gcxTile, tyMin * gcyTile, cx, cy); gTemplate.DrawImage(bm, 0, 0, rcSrc, GraphicsUnit.Pixel); string strT; if (gstrTemplateNames != null) { strT = stmrTemplateNames.ReadLine(); if (strT == null) // end of template names reached { strT = String.Format("template{0:0#}", nTemplate); } } else { strT = String.Format("{0}{1:0#}", gstrOutputPrefix, nTemplate); } if (gstrTileCollection == null) { bmTemplate.Save(strT + ".png", ImageFormat.Png); bmTemplate.Dispose(); } else { m.Template tmpl = new m.Template(tmpd, bmTemplate, strT); if (bmTerrain != null) { tmpl.TerrainMap = new m.TerrainTypes[cty, ctx]; for (int j = 0; j < cty; j++) { for (int i = 0; i < ctx; i++) { if (bmTerrain.GetPixel((txMin + i) * gcxTile, (tyMin + j) * gcyTile) == clrBlocked) { tmpl.TerrainMap[j, i] = m.TerrainTypes.Blocked; } else { tmpl.TerrainMap[j, i] = m.TerrainTypes.Open; } } } } if (bmColors != null) { Color[] aclr = new Color[4] { Color.FromArgb(114, 167, 48), // grass Color.FromArgb(81, 142, 118), // cliff Color.FromArgb(1, 172, 254), // water Color.FromArgb(174, 168, 99), // road }; tmpl.TerrainColors = new m.TerrainColors[cty * 2, ctx * 2]; for (int yT = 0; yT < cty * 2; yT++) { for (int xT = 0; xT < ctx * 2; xT++) { Color clr = bmColors.GetPixel(txMin * gcxTile + xT * gcxTile / 2, tyMin * gcyTile + yT * gcyTile / 2); m.TerrainColors tclr = m.TerrainColors.Grass; for (int i = 0; i < aclr.Length; i++) { if (clr == aclr[i]) { tclr = (m.TerrainColors)i; break; } } tmpl.TerrainColors[yT, xT] = tclr; } } } if (strT.ToLower() == "background") { tmpd.SetBackgroundTemplate(tmpl); } atmpl[nTemplate] = tmpl; } gTemplate.Dispose(); nTemplate++; } if (stmrTemplateNames != null) { stmrTemplateNames.Close(); } if (gstrTileCollection != null) { Console.WriteLine("Writing templates to {0}", gstrTileCollection); tmpd.AddTemplates(atmpl); tmpd.SaveAs(gstrTileCollection); } Console.WriteLine("{0} tiles total in {1} templates ({2:###,###,###} bytes)", cTiles, alTemplates.Count, cTiles * gcxTile * gcyTile); return(0); }