public void XAreaEqualToYAreaAndXLongestDimensionLessThanY() { Sprite x = new Sprite("X", new Bitmap(15, 20), 0, false); Sprite y = new Sprite("Y", new Bitmap(10, 30), 0, false); SpriteSizeComparer comparer = new SpriteSizeComparer(); int expected = -1; int actual = comparer.Compare(x, y); Assert.AreEqual(expected, actual); }
public void XAreaLessThanYArea() { Sprite x = new Sprite("X", new Bitmap(10, 20), 0, false); Sprite y = new Sprite("Y", new Bitmap(20, 30), 0, false); SpriteSizeComparer comparer = new SpriteSizeComparer(); int expected = -1; int actual = comparer.Compare(x, y); Assert.AreEqual(expected, actual); }
/// <summary> /// Uses all images found in the specified source folder to build a compacted sprite sheet. /// Images used maintain their original orientation, but may be cropped to remove transparency /// if the <paramref name="cropTransparency"/> parameter is true. /// </summary> /// <param name="sourceFolder">Folder containing images to use in the sprite sheet. /// All images in the folder will be used.</param> /// <param name="outputName">Name to use for the sprite sheet output image file and XML definition file.</param> /// <param name="cropTransparency">True if transparent pixels should be removed when determining /// the source area of the image, or false if not.</param> public void BuildSheet(string sourceFolder, string outputName, bool cropTransparency, bool roundUpPower2Size) { if (!Directory.Exists(sourceFolder)) { throw new ArgumentException(string.Format("Source folder '{0}' does not exist", sourceFolder), "sourceFolder"); } if (string.IsNullOrWhiteSpace(outputName)) { throw new ArgumentNullException("outputName"); } DirectoryInfo dirInfo = new DirectoryInfo(sourceFolder); FileInfo[] files = dirInfo.GetFiles("*.png"); if ((files == null) || (files.Length == 0)) { // Not finding image files means nothing can be built, but this should not // be treated as an exception return; } // Replace spaces in the name with underscores to help with compatibility // with other tools or across platforms. outputName = outputName.Replace(' ', '_'); string sheetName = Path.Combine(sourceFolder, outputName + ".png"); string xmlName = Path.Combine(sourceFolder, outputName + ".xml"); if (File.Exists(sheetName)) { File.Delete(sheetName); } if (File.Exists(xmlName)) { File.Delete(xmlName); } // Calculate the total area of all images and find the widest. // Then create a list of images, sorted from smallest to largest. int totalArea = 0; int maxWidth = 0; List<Sprite> sprites = new List<Sprite>(); foreach (FileInfo file in files) { if (file.FullName != sheetName) { Bitmap image = new Bitmap(file.FullName); Sprite sprite = new Sprite(Path.GetFileNameWithoutExtension(file.FullName).Replace(' ', '_'), image, HorizontalPadding, VerticalPadding, cropTransparency); sprites.Add(sprite); totalArea += sprite.Width * sprite.Height; maxWidth = (sprite.Width > maxWidth) ? sprite.Width : maxWidth; } } sprites.Sort(new SpriteSizeComparer()); sprites.Reverse(); // Target width of the output sprite sheet is the larger of either the square root // of the total area of all images, rounded up, or the width of the widest image. int targetWidth = Math.Max((int)Math.Ceiling(Math.Sqrt(totalArea)), maxWidth); if (roundUpPower2Size) { targetWidth = MathHelper.LeastPower2GreaterThanX(targetWidth); } int remainingWidth = targetWidth; int nextX = 0; int nextY = 0; int maxHeightInRow = 0; for (int i = 0; i < sprites.Count; ++i) { // If the next image being added is wider than the remaining allowed // width of the current row of images, start a new row if (remainingWidth - sprites[i].Width <= 0) { remainingWidth = targetWidth; nextX = 0; nextY += maxHeightInRow; maxHeightInRow = 0; } sprites[i].SheetPosition = new Point(nextX, nextY); remainingWidth -= sprites[i].Width; nextX += sprites[i].Width; if (sprites[i].Height > maxHeightInRow) { maxHeightInRow = sprites[i].Height; } } int targetHeight = nextY + maxHeightInRow; if (roundUpPower2Size) { targetHeight = MathHelper.LeastPower2GreaterThanX(targetHeight); } Size size = new Size(targetWidth, targetHeight); WriteOutput(outputName, sheetName, xmlName, size, sprites); }