public BitmapPacker Insert(Bitmap texture) { //image = new Bitmap(filename); if (A != null && B != null) { BitmapPacker newNode = A.Insert(texture); if (newNode != null) return newNode; return B.Insert(texture); } else { if (image != null) return null; //if we're too small, return if (Rect.Width < texture.Width || Rect.Height < texture.Height) return null; //if we're just right, accept if (Rect.Width == texture.Width && Rect.Height == texture.Height) { image = texture; return this; } //otherwise, gotta split this node and create some kids A = new BitmapPacker(); B = new BitmapPacker(); //decide which way to split int dw = Rect.Width - texture.Width; int dh = Rect.Height - texture.Height; if (dw > dh) { A.Rect = new System.Drawing.Rectangle(Rect.Left, Rect.Top, texture.Width, Rect.Bottom - Rect.Top); B.Rect = new System.Drawing.Rectangle(Rect.Left + texture.Width, Rect.Top, Rect.Right - (Rect.Left + texture.Width), Rect.Bottom - Rect.Top); } else { A.Rect = new System.Drawing.Rectangle(Rect.Left, Rect.Top, Rect.Right - Rect.Left, texture.Height); B.Rect = new System.Drawing.Rectangle(Rect.Left, Rect.Top + texture.Height, Rect.Right - Rect.Left, Rect.Bottom - (Rect.Top + texture.Height)); } //insert into first child we created return A.Insert(texture); } }
public Bitmap GetBitmap() { var bitmaps = new List<Bitmap>(); foreach (var tex in _items) { if (File.Exists(tex.Filename)) { var bmp = new Bitmap(tex.Filename); bmp.Tag = tex; bitmaps.Add(bmp); if (string.IsNullOrWhiteSpace(tex.Name)) tex.Name = Path.GetFileNameWithoutExtension(tex.Filename); } } bitmaps = bitmaps.OrderByDescending(b => b.Width * b.Height).ToList(); Bitmap result = null; BitmapPacker packTest = null; if (bitmaps.Count > 0) { _width = 256; _height = 256; do { var packer = new BitmapPacker { Rect = new Rectangle(0, 0, _width, _height) }; foreach (var bmp in bitmaps) { packTest = packer.Insert(bmp); if (packTest == null) break; (bmp.Tag as TextureAtlasItem).Width = packTest.Rect.Width; (bmp.Tag as TextureAtlasItem).Height = packTest.Rect.Height; (bmp.Tag as TextureAtlasItem).X = packTest.Rect.X; (bmp.Tag as TextureAtlasItem).Y = packTest.Rect.Y; } if (packTest == null) { if (_width > _height) _height *= 2; else _width *= 2; } else { result = new Bitmap(_width, _height, PixelFormat.Format32bppArgb); packer.Render(result); } } while (packTest == null); } bitmaps.Clear(); return result; }
public void Build(System.Drawing.Font font, TextRenderingHint hint, string filename) { //new Glyph(97, font, hint); //Create Glyphs _glyphs.Clear(); for (int i = 33; i < 256; i++) { _glyphs.Add(new Glyph(i, font, hint)); } //Create Texture bool allFit; int startWidth = 128; int startHeight = 128; BitmapPacker root; do { allFit = true; root = new BitmapPacker(); root.Rect = new System.Drawing.Rectangle(0, 0, startWidth, startHeight); foreach (var glyph in _glyphs) { if (glyph.Bitmap != null) { var bp = root.Insert(glyph.Bitmap); if (bp == null) { if (startWidth > startHeight) { startHeight *= 2; } else { startWidth *= 2; } allFit = false; break; } else { glyph.Info.X1 = (byte)bp.Rect.X; glyph.Info.Y1 = (byte)bp.Rect.Y; glyph.Info.X2 = (byte)bp.Rect.Right; glyph.Info.Y2 = (byte)bp.Rect.Bottom; } } } } while (!allFit); Bitmap result = new Bitmap(root.Rect.Width, root.Rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); root.Render(result); result.Save(filename + ".png"); CalculateKernings(); using (var fs = new FileStream(filename + ".info", FileMode.Create)) { using (var bw = new BinaryWriter(fs)) { foreach (var g in _glyphs) { bw.Write(g.Info.X1); bw.Write(g.Info.Y1); bw.Write(g.Info.X2); bw.Write(g.Info.Y2); bw.Write(g.Info.YOffset); } bw.Write(_kerning); } } }