public void TestBarelyFittingRectangle() { ArevaloRectanglePacker packer = new ArevaloRectanglePacker(128, 128); Point placement = packer.Pack(128, 128); Assert.AreEqual(new Point(0, 0), placement); }
public void TestTooLargeRectangle() { ArevaloRectanglePacker packer = new ArevaloRectanglePacker(128, 128); Point placement; bool result = packer.TryPack(129, 10, out placement); Assert.IsFalse(result); result = packer.TryPack(10, 129, out placement); Assert.IsFalse(result); }
private bool TestPackingImages(int testWidth, int testHeight, Dictionary<string, Microsoft.Xna.Framework.Rectangle> testImagePlacement) { // create the rectangle packer ArevaloRectanglePacker rectanglePacker = new ArevaloRectanglePacker(testWidth, testHeight); foreach (var image in files) { // get the bitmap for this file Size size = imageSizes[System.IO.Path.GetFileNameWithoutExtension(image)]; // pack the image Point origin; if (!rectanglePacker.TryPack(size.Width + padding, size.Height + padding, out origin)) { return false; } // add the destination rectangle to our dictionary testImagePlacement.Add(System.IO.Path.GetFileNameWithoutExtension(image), new Microsoft.Xna.Framework.Rectangle(origin.X, origin.Y, size.Width + padding, size.Height + padding)); } return true; }
/// <summary> /// Collect information about the images and bin pack them using the chosen algorithm /// </summary> /// <param name="imagesInfo"></param> /// <param name="spriteSize"></param> public void GetImagesInfo(out List<SpriteImageItem> imagesInfo, out Size spriteSize, int padding) { imagesInfo = new List<SpriteImageItem>(); // calculate initial sprite size to optimize process speed // -> make sure that the widest and the tallest images fit // -> make sure the resulting area is the same as the sum of all images area int maxW = 0; int maxH = 0; //int totalArea = 0; foreach (var file in GetFiles()) { var image = Image.FromFile(file.FullName); imagesInfo.Add(new SpriteImageItem() { Image = image, Name = file.Name }); if (image.Width > maxW) maxW = image.Width; if (image.Height > maxH) maxH = image.Height; //totalArea = image.Width * image.Height; } int finalW = 0; int finalH = 0; //int totalW = (int)Math.Ceiling((decimal)totalArea / 2); //int totalH = totalW; finalW = maxW;// maxW > totalW ? maxW : totalW; finalH = maxH; // maxH > totalH ? maxH : totalH; List<SpriteImageItem> unfitImagesInfo = new List<SpriteImageItem>(); bool finished = false; while (!finished) { // start packing process RectanglePacker packer = null; switch (this.Options.BinPackingLevel) { case 1: // faster and less compless algorithm packer = new SimpleRectanglePacker(finalW, finalH); break; case 2: // still fast and much better packing algorithm packer = new CygonRectanglePacker(finalW, finalH); break; case 3: // the best packing algorithm. Addicional processing time might not be noticeable packer = new ArevaloRectanglePacker(finalW, finalH); break; default: // default packer = new CygonRectanglePacker(finalW, finalH); break; } //var usedArea = 0; foreach (var iInfo in imagesInfo) { // Find a place for a rectangle of size 30x20 in the packing area Point placement; if (packer.TryPack(iInfo.Image.Width + padding, iInfo.Image.Height + padding, out placement)) { iInfo.Position = placement; //usedArea += iInfo.Image.Width * iInfo.Image.Height; } else { unfitImagesInfo.Add(iInfo); } } if (unfitImagesInfo.Count == 0) { finished = true; } else { // add the diff between the used area and the remaining images area //var extraW = 0; //var extraH = 0; //foreach (var unfit in unfitImagesInfo) //{ // extraW += unfit.Image.Width; // extraH += unfit.Image.Height; //} // after some tests the speed and result are quite the same as adding a few more pixels to the // sprite final size and run the whole process again finalW += 10; finalH += 10; unfitImagesInfo.Clear(); } } spriteSize = new Size(finalW, finalH); }
private bool TestPackingImages(int testWidth, int testHeight, Lexicon<string, Rectangle> testImagePlacement) { // create the rectangle packer ArevaloRectanglePacker rectanglePacker = new ArevaloRectanglePacker(testWidth, testHeight); foreach (var image in files) { // get the bitmap for this file Size size = imageSizes[image.Key][0]; // pack the image Point origin; if (!rectanglePacker.TryPack(size.Width + padding, size.Height + padding, out origin)) { return false; } // add the destination rectangle to our dictionary testImagePlacement.Add(image.Key, new Rectangle(origin.X, origin.Y, size.Width + padding, size.Height + padding)); } return true; }
//贴图装箱算法 public static IList<TexturePacket> PacketTexture(GraphicsDevice gdevice,IDictionary<string,Texture2D> sources) { List<TexturePacket> list = new List<TexturePacket>(); int packetsize = 512; RectanglePacker packer = new ArevaloRectanglePacker(packetsize, packetsize); Texture2D tex = new Texture2D(gdevice, packer.PackingAreaWidth, packer.PackingAreaHeight, false, SurfaceFormat.Color); Dictionary<string, RectangleF> rects = new Dictionary<string, RectangleF>(); foreach (var i in sources) { UInt32[] data=new UInt32[i.Value.Width*i.Value.Height]; i.Value.GetData<UInt32>(data); int twidth = i.Value.Width; int theight = i.Value.Height; bool bfixx=false; bool bfixy = false; if((twidth== packetsize/2||twidth==packetsize/4)) { } else { bfixx=true; twidth+=2; } if (theight==packetsize/2||theight==packetsize/4) { } else { theight += 2; bfixy = true; } Point pos; if (packer.TryPack(twidth, theight, out pos)) { //right } else { TexturePacket p = new TexturePacket(tex, rects); list.Add(p); packer = new ArevaloRectanglePacker(packetsize, packetsize); tex = new Texture2D(gdevice, packer.PackingAreaWidth, packer.PackingAreaHeight, false, SurfaceFormat.Color); rects = new Dictionary<string, RectangleF>(); packer.TryPack(i.Value.Width, i.Value.Height, out pos); } if (bfixx) pos.X += 1; if(bfixy) pos.Y+=1; tex.SetData<UInt32>(0, new Rectangle(pos.X, pos.Y, i.Value.Width, i.Value.Height), data, 0, data.Length); rects.Add(i.Key, new RectangleF( (float)(pos.X) / (float)packer.PackingAreaWidth, (float)(pos.Y) / (float)packer.PackingAreaHeight, (float)i.Value.Width / (float)packer.PackingAreaWidth, (float)i.Value.Height / (float)packer.PackingAreaHeight )); } { TexturePacket p = new TexturePacket(tex, rects); list.Add(p); } return list; }
public void TestThrowOnTooLargeRectangle() { ArevaloRectanglePacker packer = new ArevaloRectanglePacker(128, 128); Assert.Throws<OutOfSpaceException>( delegate() { packer.Pack(129, 129); } ); }