Ejemplo n.º 1
0
        public static void TreePack(Size textureSize, string[] filenames, string outputFilename)
        {
            System.Drawing.Image[] images = new Image[filenames.Length];
//			for (int i=0; i<filenames.Length; i++)
//			{
//				files[i] = new System.IO.FileInfo(filenames[i]);
//				images[i] = System.Drawing.Bitmap.FromFile(filenames[i]);
//			}
//			ERectangle[] rects;
//			EPoint[] offsets;
//			Bitmap bmp = TreePack(images, out rects, out offsets);
//			bmp.Save(outputFilename);

            EPoint[]             offsets       = new EPoint[filenames.Length];
            System.IO.FileInfo[] files         = new System.IO.FileInfo[filenames.Length];
            PropList             originalOrder = new PropList();

            for (int i = 0; i < filenames.Length; i++)
            {
                files[i]  = new System.IO.FileInfo(filenames[i]);
                images[i] = System.Drawing.Bitmap.FromFile(filenames[i]);

                EPoint pntMid = new EPoint(images[i].Width, images[i].Height) / 2;
                EPoint pnt    = new EPoint();
                images[i]  = Endogine.BitmapHelpers.BitmapHelper.TrimWhitespace((Bitmap)images[i], out pnt);
                offsets[i] = pntMid - pnt + new EPoint(1, 1);

                originalOrder.Add(filenames[i], images[i]);
            }

            Image[] unpacked = null;

            int  numPixelsMinimum;
            Size maxWnH, minWnH;

            GetImagesStatistics(images, out numPixelsMinimum, out maxWnH, out minWnH);

            if (textureSize.Width == 0 || textureSize.Height == 0)
            {
                int side  = (int)Math.Sqrt(numPixelsMinimum);
                int asdas = (int)Math.Ceiling(Math.Log(side, 2));
                textureSize = new Size(side, side);
            }

            if (numPixelsMinimum >= textureSize.Width * textureSize.Height)
            {
                throw new Exception("Not enough space to pack in");
            }

            images = Endogine.BitmapHelpers.TexturePacking.SortImagesBySize(images);


            Random rnd = new Random();

            int nNumTries = 1;

            for (int i = 0; i < nNumTries; i++)
            {
                //Irritating, but since we can't find index of an item in a standard array...:
                ArrayList aImagesNewOrder = new ArrayList();
                foreach (Image image in images)
                {
                    aImagesNewOrder.Add(image);
                }

                EPoint[] locsInTexture = null;
                Bitmap   bmp           = Endogine.BitmapHelpers.TexturePacking.TreePack(textureSize, images, out unpacked, out locsInTexture);
                int      areaExcluded  = Endogine.BitmapHelpers.TexturePacking.GetTotalArea(unpacked);

                if (unpacked.Length > 0)
                {
                    throw new Exception("Couldn't fit all images. Total pixels excluded = " + areaExcluded.ToString() + " (side = " + ((int)Math.Sqrt(areaExcluded)).ToString() + ")");
                }

                ArrayList aUnpacked = new ArrayList();
                foreach (Image image in unpacked)
                {
                    aUnpacked.Add(image);
                }
                int areaUnused = 0;
                foreach (Image image in images)
                {
                    if (!aUnpacked.Contains(image))
                    {
                        areaUnused += image.Size.Width * image.Size.Height;
                    }
                }

                if (areaUnused > textureSize.Width * textureSize.Height / 2)
                {
                    //TODO: we could maybe make the texture at least half as big
                }

                Node infoNode = new Node();
                infoNode = infoNode.CreateChild("Files");

                //TODO: go by the list of images that was actually used!
                for (int orgIndex = 0; orgIndex < originalOrder.Count; orgIndex++)
                {
                    Image image = (Image)originalOrder.GetByIndex(orgIndex);
                    if (aUnpacked.Contains(image))
                    {
                        continue;
                    }

                    int newIndex = aImagesNewOrder.IndexOf(image);

                    //create the file entry (File, Rect, Offset)
                    ERectangle rctInTexture = new ERectangle(
                        locsInTexture[newIndex].X, locsInTexture[newIndex].Y, image.Width, image.Height);
                    Node frameNode = infoNode.CreateChild("File");
                    //remove extension from filename:
                    frameNode.Value = files[orgIndex].Name.Substring(0, files[orgIndex].Name.LastIndexOf(files[orgIndex].Extension));
                    //frameNode.Value = files[orgIndex].Name;
                    Node subNode = frameNode.CreateChild("Rect");
                    subNode.Value = rctInTexture.ToString();
                    subNode       = frameNode.CreateChild("Offset");
                    subNode.Value = offsets[orgIndex].ToString();
                }

                System.Xml.XmlDocument doc = infoNode.RootNode.CreateXmlDocument();

                string sOut = null;
                if (nNumTries > 1)
                {
                    sOut = outputFilename + areaExcluded.ToString() + "-" + i.ToString();
                }
                else
                {
                    sOut = outputFilename;
                }

                doc.Save(sOut + ".xml");
                bmp.Save(sOut + ".png");

                //randomize order to see if we get better results:
                ArrayList aImages = new ArrayList();
                for (int j = 0; j < images.Length; j++)
                {
                    aImages.Add(images[j]);
                }

                Image[] randomOrder = new Image[images.Length];
                for (int j = images.Length - 1; j >= 0; j--)
                {
                    int pos = 0;
                    if (j > 0)
                    {
                        pos = Math.Min(rnd.Next(j), j - 1);
                    }
                    randomOrder[j] = (Image)aImages[pos];
                    aImages.RemoveAt(pos);
                }
                images = randomOrder;
            }
        }
Ejemplo n.º 2
0
        public static void TreePack(Size textureSize, string[] filenames, string outputFilename)
        {
            System.Drawing.Image[] images = new Image[filenames.Length];
            //			for (int i=0; i<filenames.Length; i++)
            //			{
            //				files[i] = new System.IO.FileInfo(filenames[i]);
            //				images[i] = System.Drawing.Bitmap.FromFile(filenames[i]);
            //			}
            //			ERectangle[] rects;
            //			EPoint[] offsets;
            //			Bitmap bmp = TreePack(images, out rects, out offsets);
            //			bmp.Save(outputFilename);

            EPoint[] offsets = new EPoint[filenames.Length];
            System.IO.FileInfo[] files = new System.IO.FileInfo[filenames.Length];
            PropList originalOrder = new PropList();
            for (int i=0; i<filenames.Length; i++)
            {
                files[i] = new System.IO.FileInfo(filenames[i]);
                images[i] = System.Drawing.Bitmap.FromFile(filenames[i]);

                EPoint pntMid = new EPoint(images[i].Width, images[i].Height)/2;
                EPoint pnt = new EPoint();
                images[i] = Endogine.BitmapHelpers.BitmapHelper.TrimWhitespace((Bitmap)images[i], out pnt);
                offsets[i] = pntMid - pnt + new EPoint(1,1);

                originalOrder.Add(filenames[i], images[i]);
            }

            Image[] unpacked = null;

            int numPixelsMinimum;
            Size maxWnH, minWnH;
            GetImagesStatistics(images, out numPixelsMinimum, out maxWnH, out minWnH);

            if (textureSize.Width == 0 || textureSize.Height == 0)
            {
                int side = (int)Math.Sqrt(numPixelsMinimum);
                int asdas = (int)Math.Ceiling(Math.Log(side, 2));
                textureSize = new Size(side,side);
            }

            if (numPixelsMinimum >= textureSize.Width*textureSize.Height)
                throw new Exception("Not enough space to pack in");

            images = Endogine.BitmapHelpers.TexturePacking.SortImagesBySize(images);

            Random rnd = new Random();

            int nNumTries = 1;
            for (int i=0; i<nNumTries; i++)
            {
                //Irritating, but since we can't find index of an item in a standard array...:
                ArrayList aImagesNewOrder = new ArrayList();
                foreach (Image image in images)
                    aImagesNewOrder.Add(image);

                EPoint[] locsInTexture = null;
                Bitmap bmp = Endogine.BitmapHelpers.TexturePacking.TreePack(textureSize, images, out unpacked, out locsInTexture);
                int areaExcluded = Endogine.BitmapHelpers.TexturePacking.GetTotalArea(unpacked);

                if (unpacked.Length > 0)
                    throw new Exception("Couldn't fit all images. Total pixels excluded = "+areaExcluded.ToString() + " (side = "+((int)Math.Sqrt(areaExcluded)).ToString()+")");

                ArrayList aUnpacked = new ArrayList();
                foreach (Image image in unpacked)
                    aUnpacked.Add(image);
                int areaUnused = 0;
                foreach (Image image in images)
                {
                    if (!aUnpacked.Contains(image))
                        areaUnused+=image.Size.Width*image.Size.Height;
                }

                if (areaUnused > textureSize.Width*textureSize.Height/2)
                {
                    //TODO: we could maybe make the texture at least half as big
                }

                Node infoNode = new Node();
                infoNode = infoNode.CreateChild("Files");

                //TODO: go by the list of images that was actually used!
                for (int orgIndex = 0; orgIndex<originalOrder.Count; orgIndex++)
                {
                    Image image = (Image)originalOrder.GetByIndex(orgIndex);
                    if (aUnpacked.Contains(image))
                        continue;

                    int newIndex = aImagesNewOrder.IndexOf(image);

                    //create the file entry (File, Rect, Offset)
                    ERectangle rctInTexture = new ERectangle(
                        locsInTexture[newIndex].X, locsInTexture[newIndex].Y, image.Width, image.Height);
                    Node frameNode = infoNode.CreateChild("File");
                    //remove extension from filename:
                    frameNode.Value = files[orgIndex].Name.Substring(0,files[orgIndex].Name.LastIndexOf(files[orgIndex].Extension));
                    //frameNode.Value = files[orgIndex].Name;
                    Node subNode = frameNode.CreateChild("Rect");
                    subNode.Value = rctInTexture.ToString();
                    subNode = frameNode.CreateChild("Offset");
                    subNode.Value = offsets[orgIndex].ToString();
                }

                System.Xml.XmlDocument doc = infoNode.RootNode.CreateXmlDocument();

                string sOut = null;
                if (nNumTries > 1)
                    sOut = outputFilename+areaExcluded.ToString()+"-"+i.ToString();
                else
                    sOut = outputFilename;

                doc.Save(sOut+".xml");
                bmp.Save(sOut+".png");

                //randomize order to see if we get better results:
                ArrayList aImages = new ArrayList();
                for (int j=0; j<images.Length;j++)
                    aImages.Add(images[j]);

                Image[] randomOrder = new Image[images.Length];
                for (int j=images.Length-1;j>=0;j--)
                {
                    int pos = 0;
                    if (j > 0)
                        pos = Math.Min(rnd.Next(j), j-1);
                    randomOrder[j] = (Image)aImages[pos];
                    aImages.RemoveAt(pos);
                }
                images = randomOrder;
            }
        }