public static void ScaleTemplates(TemplateDoc tmpd, Size sizTile) { // Scale templates Template[] atmpl = tmpd.GetTemplates(); Template tmplBackground = tmpd.GetBackgroundTemplate(); tmpd.RemoveTemplates(atmpl); foreach (Template tmpl in atmpl) { ScaleTemplate(tmpl, tmpd.TileSize, sizTile); } tmpd.TileSize = sizTile; tmpd.AddTemplates(atmpl); tmpd.SetBackgroundTemplate(tmplBackground); }
public static TemplateDoc CloneTemplateDoc(TemplateDoc tmpdSrc) { // This should probably be on ICloneable::Clone() on TemplateDoc TemplateDoc tmpdDst = (TemplateDoc)DocManager.NewDocument(typeof(TemplateDoc), new Object[] { tmpdSrc.TileSize }); DocManager.SetActiveDocument(typeof(TemplateDoc), tmpdSrc); Template[] atmplSrc = tmpdSrc.GetTemplates(); Template tmplSrcBackground = tmpdSrc.GetBackgroundTemplate(); Template tmplDstBackground = null; ArrayList alsTmplDst = new ArrayList(); foreach (Template tmplSrc in atmplSrc) { Template tmplDst = new Template(tmpdDst, tmplSrc.Name); tmplDst.OccupancyMap = tmplSrc.OccupancyMap; tmplDst.TerrainMap = tmplSrc.TerrainMap; tmplDst.Bitmap = (Bitmap)tmplSrc.Bitmap.Clone(); alsTmplDst.Add(tmplDst); if (tmplSrc == tmplSrcBackground) { tmplDstBackground = tmplDst; } } if (tmplDstBackground != null) { tmpdDst.SetBackgroundTemplate(tmplDstBackground); } tmpdDst.AddTemplates((Template[])alsTmplDst.ToArray(typeof(Template))); Palette palSrc = tmpdSrc.GetPalette(); if (palSrc != null) { tmpdDst.SetPalette(palSrc, false); } return(tmpdDst); }
public static void ScaleTemplates(TemplateDoc tmpd, Size sizTile) { // Scale templates Template[] atmpl = tmpd.GetTemplates(); Template tmplBackground = tmpd.GetBackgroundTemplate(); tmpd.RemoveTemplates(atmpl); foreach (Template tmpl in atmpl) ScaleTemplate(tmpl, tmpd.TileSize, sizTile); tmpd.TileSize = sizTile; tmpd.AddTemplates(atmpl); tmpd.SetBackgroundTemplate(tmplBackground); }
public static void QuantizeTemplates(TemplateDoc tmpd, Palette palFixed, int cPalEntries, int cPalEntriesFixed, int cPalEntriesBackground) { // Load the fixed palette. The result will be 24 bit templates normalized to a palette of 256 colors, // the "fixed" palette plus a quantized palette. if (palFixed == null) { palFixed = Palette.OpenDialog(null); if (palFixed == null) { MessageBox.Show(DocManager.GetFrameParent(), "Must have the fixed color palette to continue!"); return; } switch (palFixed.Length) { case 16: cPalEntries = 16; cPalEntriesFixed = 16; cPalEntriesBackground = 0; break; case 256: cPalEntries = 256; cPalEntriesFixed = 128; cPalEntriesBackground = 32; break; } } // Quantize loop. Designed to make optimal use of the lower 128 fixed colors // Quantize background separately from foreground Template tmplBackground = tmpd.GetBackgroundTemplate(); if (tmplBackground != null && cPalEntriesBackground != 0) { // Create a despeckled hue map of the background. We'll use this to // subtract background from foreground so we can quantize foreground separately Bitmap bmHueBackground = MakeHueMap(tmplBackground.Bitmap); DespeckleGrayscaleBitmap(bmHueBackground, 9, 50); // Calc mean and standard deviation for filtering purposes double nMean = CalcGrayscaleMean(bmHueBackground); double nStdDev = CalcGrayscaleStandardDeviation(bmHueBackground, nMean); // Add extract & quantize the background pixels ArrayList alsColorsBackground = new ArrayList(); AddTemplateColors(alsColorsBackground, tmplBackground.Bitmap); palFixed = QuantizeColors(alsColorsBackground, palFixed, cPalEntriesFixed + cPalEntriesBackground, cPalEntriesFixed); cPalEntriesFixed += cPalEntriesBackground; // Now extract foreground pixels by first subtracting background pixels ArrayList alsColorsForeground = new ArrayList(); Template[] atmpl = tmpd.GetTemplates(); foreach (Template tmpl in atmpl) { if (tmpl == tmplBackground) continue; Bitmap bmT = MakeHueMap(tmpl.Bitmap); DespeckleGrayscaleBitmap(bmT, 9, 50); SubtractGrayscaleDistribution(bmT, nMean, nStdDev); for (int y = 0; y < bmT.Height; y++) { for (int x = 0; x < bmT.Width; x++) { Color clr = bmT.GetPixel(x, y); if (clr != Color.FromArgb(255, 0, 255)) bmT.SetPixel(x, y, tmpl.Bitmap.GetPixel(x, y)); } } AddTemplateColors(alsColorsForeground, bmT); } // Now quantize foreground pixels // Set the palette and color match Palette palNew = QuantizeColors(alsColorsForeground, palFixed, cPalEntries, cPalEntriesFixed); tmpd.SetPalette(palNew, true); } else { // No background template; just quantize everything together Template[] atmpl = tmpd.GetTemplates(); ArrayList alsColors = new ArrayList(); foreach (Template tmpl in atmpl) AddTemplateColors(alsColors, tmpl.Bitmap); // Now quantize foreground pixels // Set the palette and color match Palette palNew = QuantizeColors(alsColors, palFixed, cPalEntries, cPalEntriesFixed); tmpd.SetPalette(palNew, true); } }
public static TemplateDoc CloneTemplateDoc(TemplateDoc tmpdSrc) { // This should probably be on ICloneable::Clone() on TemplateDoc TemplateDoc tmpdDst = (TemplateDoc)DocManager.NewDocument(typeof(TemplateDoc), new Object[] { tmpdSrc.TileSize }); DocManager.SetActiveDocument(typeof(TemplateDoc), tmpdSrc); Template[] atmplSrc = tmpdSrc.GetTemplates(); Template tmplSrcBackground = tmpdSrc.GetBackgroundTemplate(); Template tmplDstBackground = null; ArrayList alsTmplDst = new ArrayList(); foreach (Template tmplSrc in atmplSrc) { Template tmplDst = new Template(tmpdDst, tmplSrc.Name); tmplDst.OccupancyMap = tmplSrc.OccupancyMap; tmplDst.TerrainMap = tmplSrc.TerrainMap; tmplDst.Bitmap = (Bitmap)tmplSrc.Bitmap.Clone(); alsTmplDst.Add(tmplDst); if (tmplSrc == tmplSrcBackground) tmplDstBackground = tmplDst; } if (tmplDstBackground != null) tmpdDst.SetBackgroundTemplate(tmplDstBackground); tmpdDst.AddTemplates((Template[])alsTmplDst.ToArray(typeof(Template))); Palette palSrc = tmpdSrc.GetPalette(); if (palSrc != null) tmpdDst.SetPalette(palSrc, false); return tmpdDst; }
public void DrawTileMap(Bitmap bm, ArrayList alsmiSelected, Size sizTile, TemplateDoc tmpd, LayerFlags lyrf) { // Draw background using (Graphics g = Graphics.FromImage(bm)) { Template tmplBackground = null; if (tmpd != null) tmplBackground = tmpd.GetBackgroundTemplate(); if (tmplBackground == null) { g.FillRectangle(new SolidBrush(Color.Black), 0, 0, bm.Width, bm.Height); for (int x = sizTile.Width; x < bm.Width; x += sizTile.Width) { for (int y = sizTile.Height; y < bm.Height; y += sizTile.Height) { bm.SetPixel(x, y, Color.BlanchedAlmond); } } } else { for (int x = 0; x < bm.Width; x += tmplBackground.Bitmap.Width) { for (int y = 0; y < bm.Height; y += tmplBackground.Bitmap.Height) g.DrawImage(tmplBackground.Bitmap, x, y); } } // Draw templates if ((lyrf & LayerFlags.Templates) != 0) { foreach (IMapItem mi in m_alsmi) { int x = (int)mi.tx * sizTile.Width; int y = (int)mi.ty * sizTile.Height; mi.Draw(g, x, y, sizTile, tmpd, LayerType.TileMap, alsmiSelected != null ? alsmiSelected.Contains(mi) : false); } } } }
public static void QuantizeTemplates(TemplateDoc tmpd, Palette palFixed, int cPalEntries, int cPalEntriesFixed, int cPalEntriesBackground) { // Load the fixed palette. The result will be 24 bit templates normalized to a palette of 256 colors, // the "fixed" palette plus a quantized palette. if (palFixed == null) { palFixed = Palette.OpenDialog(null); if (palFixed == null) { MessageBox.Show(DocManager.GetFrameParent(), "Must have the fixed color palette to continue!"); return; } switch (palFixed.Length) { case 16: cPalEntries = 16; cPalEntriesFixed = 16; cPalEntriesBackground = 0; break; case 256: cPalEntries = 256; cPalEntriesFixed = 128; cPalEntriesBackground = 32; break; } } // Quantize loop. Designed to make optimal use of the lower 128 fixed colors // Quantize background separately from foreground Template tmplBackground = tmpd.GetBackgroundTemplate(); if (tmplBackground != null && cPalEntriesBackground != 0) { // Create a despeckled hue map of the background. We'll use this to // subtract background from foreground so we can quantize foreground separately Bitmap bmHueBackground = MakeHueMap(tmplBackground.Bitmap); DespeckleGrayscaleBitmap(bmHueBackground, 9, 50); // Calc mean and standard deviation for filtering purposes double nMean = CalcGrayscaleMean(bmHueBackground); double nStdDev = CalcGrayscaleStandardDeviation(bmHueBackground, nMean); // Add extract & quantize the background pixels ArrayList alsColorsBackground = new ArrayList(); AddTemplateColors(alsColorsBackground, tmplBackground.Bitmap); palFixed = QuantizeColors(alsColorsBackground, palFixed, cPalEntriesFixed + cPalEntriesBackground, cPalEntriesFixed); cPalEntriesFixed += cPalEntriesBackground; // Now extract foreground pixels by first subtracting background pixels ArrayList alsColorsForeground = new ArrayList(); Template[] atmpl = tmpd.GetTemplates(); foreach (Template tmpl in atmpl) { if (tmpl == tmplBackground) { continue; } Bitmap bmT = MakeHueMap(tmpl.Bitmap); DespeckleGrayscaleBitmap(bmT, 9, 50); SubtractGrayscaleDistribution(bmT, nMean, nStdDev); for (int y = 0; y < bmT.Height; y++) { for (int x = 0; x < bmT.Width; x++) { Color clr = bmT.GetPixel(x, y); if (clr != Color.FromArgb(255, 0, 255)) { bmT.SetPixel(x, y, tmpl.Bitmap.GetPixel(x, y)); } } } AddTemplateColors(alsColorsForeground, bmT); } // Now quantize foreground pixels // Set the palette and color match Palette palNew = QuantizeColors(alsColorsForeground, palFixed, cPalEntries, cPalEntriesFixed); tmpd.SetPalette(palNew, true); } else { // No background template; just quantize everything together Template[] atmpl = tmpd.GetTemplates(); ArrayList alsColors = new ArrayList(); foreach (Template tmpl in atmpl) { AddTemplateColors(alsColors, tmpl.Bitmap); } // Now quantize foreground pixels // Set the palette and color match Palette palNew = QuantizeColors(alsColors, palFixed, cPalEntries, cPalEntriesFixed); tmpd.SetPalette(palNew, true); } }
static void ImportTileMap(TileMap tmap, TileSet tset, TemplateDoc tmpd, LevelDoc lvld) { // The TileMap is a list of indexes into a tile set. A Tileset is a list of tiles compiled // from Templates. Reverse the tilemap into Templates, and set into lvld. bool[,] afCellTaken = new bool[64, 64]; ArrayList alsTemplPos = new ArrayList(); Template[] atmpl = tmpd.GetTemplates(); for (int ty = 0; ty < tmap.Height; ty++) { for (int tx = 0; tx < tmap.Width; tx++) { // Cell mapped already? if (afCellTaken[ty, tx]) { continue; } // Cell not mapped. Create TemplatePos. int iTile = tmap.GetTileIndex(tx, ty); TileData tdata = tset.GetTileData(iTile); Template tmpl = atmpl[tdata.iTemplate]; // Don't bother with background tiles if (tmpl == tmpd.GetBackgroundTemplate()) { continue; } int txOrigin = tx - tdata.txTemplate; int tyOrigin = ty - tdata.tyTemplate; bool[,] afMapped = new bool[tmpl.Cty, tmpl.Ctx]; for (int tyTmpl = 0; tyTmpl < tmpl.Cty; tyTmpl++) { for (int txTmpl = 0; txTmpl < tmpl.Ctx; txTmpl++) { int txT = txOrigin + txTmpl; int tyT = tyOrigin + tyTmpl; if (txT < 0 || txT >= 64 || tyT < 0 || tyT >= 64) { continue; } if (afCellTaken[tyT, txT]) { continue; } int iTileT = tmap.GetTileIndex(txT, tyT); if (iTileT != -1) { TileData tdataT = tset.GetTileData(iTileT); if (tdataT.iTemplate != tdata.iTemplate) { continue; } if (tdataT.txTemplate != txTmpl || tdataT.tyTemplate != tyTmpl) { continue; } } afMapped[tyTmpl, txTmpl] = true; afCellTaken[tyT, txT] = true; } } alsTemplPos.Add(new TemplatePos(tmpl, txOrigin, tyOrigin, afMapped)); } } // Figure out the bounds. Rectangle rcBounds = new Rectangle((64 - tmap.Width) / 2, (64 - tmap.Height) / 2, tmap.Width, tmap.Height); lvld.Bounds = rcBounds; // The list of TemplatePos's has been created. Add to LevelDoc. ArrayList alsTiles = new ArrayList(); foreach (TemplatePos tpos in alsTemplPos) { Tile tile = new Tile(tpos.tmpl.Name, tpos.txOrigin + rcBounds.Left, tpos.tyOrigin + rcBounds.Top, tpos.afMapped, tpos.tmpl.OccupancyMap); alsTiles.Add(tile); } lvld.AddMapItems((IMapItem[])alsTiles.ToArray(typeof(IMapItem))); }
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)); } }
static void ImportTileMap(TileMap tmap, TileSet tset, TemplateDoc tmpd, LevelDoc lvld) { // The TileMap is a list of indexes into a tile set. A Tileset is a list of tiles compiled // from Templates. Reverse the tilemap into Templates, and set into lvld. bool[,] afCellTaken = new bool[64, 64]; ArrayList alsTemplPos = new ArrayList(); Template[] atmpl = tmpd.GetTemplates(); for (int ty = 0; ty < tmap.Height; ty++) { for (int tx = 0; tx < tmap.Width; tx++) { // Cell mapped already? if (afCellTaken[ty, tx]) { continue; } // Cell not mapped. Create TemplatePos. int iTile = tmap.GetTileIndex(tx, ty); TileData tdata = tset.GetTileData(iTile); Template tmpl = atmpl[tdata.iTemplate]; // Don't bother with background tiles if (tmpl == tmpd.GetBackgroundTemplate()) { continue; } int txOrigin = tx - tdata.txTemplate; int tyOrigin = ty - tdata.tyTemplate; bool[,] afMapped = new bool[tmpl.Cty, tmpl.Ctx]; for (int tyTmpl = 0; tyTmpl < tmpl.Cty; tyTmpl++) { for (int txTmpl = 0; txTmpl < tmpl.Ctx; txTmpl++) { int txT = txOrigin + txTmpl; int tyT = tyOrigin + tyTmpl; if (txT < 0 || txT >= 64 || tyT < 0 || tyT >= 64) { continue; } if (afCellTaken[tyT, txT]) { continue; } int iTileT = tmap.GetTileIndex(txT, tyT); if (iTileT != -1) { TileData tdataT = tset.GetTileData(iTileT); if (tdataT.iTemplate != tdata.iTemplate) { continue; } if (tdataT.txTemplate != txTmpl || tdataT.tyTemplate != tyTmpl) { continue; } } afMapped[tyTmpl, txTmpl] = true; afCellTaken[tyT, txT] = true; } } alsTemplPos.Add(new TemplatePos(tmpl, txOrigin, tyOrigin, afMapped)); } } // Figure out the bounds. Rectangle rcBounds = new Rectangle((64 - tmap.Width) / 2, (64 - tmap.Height) / 2, tmap.Width, tmap.Height); lvld.Bounds = rcBounds; // The list of TemplatePos's has been created. Add to LevelDoc. ArrayList alsTiles = new ArrayList(); foreach (TemplatePos tpos in alsTemplPos) { Tile tile = new Tile(tpos.tmpl.Name, tpos.txOrigin + rcBounds.Left, tpos.tyOrigin + rcBounds.Top, tpos.afMapped, tpos.tmpl.OccupancyMap); alsTiles.Add(tile); } lvld.AddMapItems((IMapItem[])alsTiles.ToArray(typeof(IMapItem))); }
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)); }