private bool TestPackingImages(int testWidth, int testHeight, RectangleF[] testImagePlacement, out int packedWidth, out int packedHeight) { packedWidth = packedHeight = 0; // create the rectangle packer var rectanglePacker = new ArevaloRectanglePacker(testWidth, testHeight); foreach (var image in ItemArray) { // get the bitmap for this file var size = ImageSizes[image.Key]; // pack the image if (!rectanglePacker.TryPack((int)Math.Ceiling(size.Width + padding), (int)Math.Ceiling(size.Height + padding), out Point origin)) { return(false); } // add the destination rectangle to our dictionary testImagePlacement[image.Key] = new RectangleF(origin.X, origin.Y, size.Width, size.Height); } packedWidth = rectanglePacker.ActualPackingAreaWidth; packedHeight = rectanglePacker.ActualPackingAreaHeight; return(true); }
private bool TestPackingRectangles(int testWidth, int testHeight, IDictionary <string, Rectangle> placementStorage) { RectanglePacker rectanglePacker; bool result; result = true; rectanglePacker = new ArevaloRectanglePacker(testWidth, testHeight); // reset the results placementStorage.Clear(); foreach (string image in _files) { Size size; Point origin; // get the bitmap for this file size = _imageSizes[image]; // pack the image result = rectanglePacker.TryPack(size.Width, size.Height, out origin); if (result) { placementStorage.Add(image, new Rectangle(origin.X, origin.Y, size.Width, size.Height)); } else { break; } } return(result); }
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); }
/// <summary> /// Determines whether the atlas' images can fit on a texture of the specified size. /// </summary> private static Boolean TestPackingImages(TextureAtlasDescription atlasDesc, IEnumerable <TextureAtlasImage> atlasImages, Int32 testWidth, Int32 testHeight, Dictionary <String, Rectangle> testImagePlacement) { var rectanglePacker = new ArevaloRectanglePacker(testWidth, testHeight); foreach (var image in atlasImages) { var size = image.Size; var origin = Vector2.Zero; var padding = atlasDesc.Metadata.Padding; if (!rectanglePacker.TryPack(size.Width + padding, size.Height + padding, out origin)) { return(false); } testImagePlacement.Add(image.Name, new Rectangle((int)origin.X, (int)origin.Y, size.Width + padding, size.Height + padding)); } return(true); }
private bool TestPackingImages(int testWidth, int testHeight, Dictionary <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.Name]; // pack the image if (!rectanglePacker.TryPack(size.Width + padding, size.Height + padding, out var origin)) { return(false); } // add the destination rectangle to our dictionary testImagePlacement.Add(image.Name, new Rectangle(origin.X, origin.Y, size.Width + padding, size.Height + padding)); } return(true); }
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 void writeToLua(DirectoryInfo directoryDest, string suffix, float XRatio, float YRatio) { try { if (this.SpriteSheet != null) { ArevaloRectanglePacker packer = null; Bitmap bitmapTemp = null; bool ok = false; try { bitmapTemp = new Bitmap(4096, 4096); packer = new ArevaloRectanglePacker(4096, 4096); ok = true; } catch (Exception e1) { ok = false; } if (ok == false) { try { bitmapTemp = new Bitmap(2048, 2048); packer = new ArevaloRectanglePacker(2048, 2048); ok = true; } catch (Exception e2) { ok = false; } } if (ok == false) { try { bitmapTemp = new Bitmap(1024, 1024); packer = new ArevaloRectanglePacker(1024, 1024); ok = true; } catch (Exception e3) { ok = false; } } if (ok == false) { System.Windows.MessageBox.Show("Error during the \"" + this.SpriteSheet.Name + "\" sprite sheet creation!\n The system does not allow to create image bigger than 1024x1024! Please check your memory available!", "Warning", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); return; } int maxWidth = 0; int maxHeight = 0; String FinalString = HEADER_LUA; String framesLua = ""; float frameFactor = this.SpriteSheet.FramesFactor; //Parcourir la liste des frames de la sprite sheet using (Graphics g = Graphics.FromImage(bitmapTemp)) { for (int i = 0; i < this.SpriteSheet.Frames.Count; i++) { SpriteFrame frame = this.SpriteSheet.Frames[i]; double width = Math.Ceiling(((float)frame.ImageSize.Width / frameFactor * XRatio)); double height = Math.Ceiling(((float)frame.ImageSize.Height / frameFactor * YRatio)); Point pDest = Point.Empty; bool res = packer.TryPack((int)width, (int)height, out pDest); if (res == true) { Image finalImg = null; string sheetPath = Path.Combine(this.currentProject.ProjectPath + "\\Resources\\SpriteSheets", this.SpriteSheet.Name); string framePath = sheetPath + "\\" + this.SpriteSheet.Name + "_frame" + i + ".png"; if (System.IO.File.Exists(framePath)) { finalImg = Image.FromFile(framePath); } if (finalImg != null) { if (pDest.X + width > maxWidth) { maxWidth = pDest.X + (int)width; } if (pDest.Y + height > maxHeight) { maxHeight = pDest.Y + (int)height; } g.DrawImage(finalImg, new Rectangle(pDest, new Size((int)width, (int)height))); finalImg.Dispose(); finalImg = null; framesLua += "{ \n"; framesLua += " name = \"" + frame.NomFrame + "\", \n"; framesLua += " spriteColorRect = { x = 0,y = 0, width = " + width + ", height = " + height + "},\n"; framesLua += " textureRect = { x = " + pDest.X + ", y = " + pDest.Y + ", width = " + width + ", height = " + height + "},\n"; framesLua += " spriteSourceSize = { width = " + width + ", height = " + height + "},\n"; framesLua += " spriteTrimmed = true, \n"; framesLua += " spriteRotated = false \n"; framesLua += "}, \n"; } else { System.Windows.MessageBox.Show("Cannot find frame " + i + " image in \"" + this.SpriteSheet.Name + "\" resources folder!", "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } } else { System.Windows.MessageBox.Show("Cannot packing frame " + i + " in \"" + this.SpriteSheet.Name + "\" sprite sheet because the image size needed is bigger than the size authorized by your system or by Corona: 4096x4096!\n Please try to reduce the size of your animation!", "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); break; } } g.Dispose(); } Bitmap finalSheet = bitmapTemp.Clone(new Rectangle(0, 0, maxWidth, maxHeight), System.Drawing.Imaging.PixelFormat.Format32bppArgb); bitmapTemp.Dispose(); bitmapTemp = null; finalSheet.Save(directoryDest.FullName + "\\" + this.SpriteSheet.Name.Replace(" ", "_").ToLower() + suffix + ".png", System.Drawing.Imaging.ImageFormat.Png); finalSheet.Dispose(); finalSheet = null; //Ajouter les frames a l'entete FinalString = FinalString + framesLua; //Ajouter le pied de page FinalString = FinalString + FOOTER_LUA; //Ecrire dans le fichier File.WriteAllText(directoryDest.FullName + "\\sprite" + this.SpriteSheet.Name.Replace(" ", "").ToLower() + "anim" + suffix + ".lua", FinalString); packer = null; } } catch (Exception ex) { System.Windows.MessageBox.Show("Error during the \"" + this.SpriteSheet.Name + "\" sprite sheet creation!\n" + ex.Message, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } }
//贴图装箱算法 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 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); } ); }