public void TestRotationElement1()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElementFromFile("imageRotated0", 0, TextureAddressMode.Clamp, TextureAddressMode.Clamp)
            };

            textureElements[0].SourceRegion.IsRotated = true;

            var texturePacker = new TexturePacker
            {
                AllowMultipack = true,
                AllowRotation  = true,
                MaxWidth       = 128,
                MaxHeight      = 256,
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);
            Assert.Single(texturePacker.AtlasTextureLayouts);

            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(texturePacker.AtlasTextureLayouts[0], false);

            SaveAndCompareTexture(atlasTexture, "TestRotationElement1");
        }
        public void TestCreateTextureAtlasToOutput()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElement("MediumPurple", 130, 158, 10, TextureAddressMode.Border, Color.MediumPurple, Color.SteelBlue),
                CreateElement("Red", 127, 248, 10, TextureAddressMode.Border, Color.Red, Color.SteelBlue),
                CreateElement("Blue", 212, 153, 10, TextureAddressMode.Border, Color.Blue, Color.SteelBlue),
                CreateElement("Gold", 78, 100, 10, TextureAddressMode.Border, Color.Gold, Color.SteelBlue),
                CreateElement("RosyBrown", 78, 100, 10, TextureAddressMode.Border, Color.RosyBrown, Color.SteelBlue),
                CreateElement("SaddleBrown", 400, 100, 10, TextureAddressMode.Border, Color.SaddleBrown, Color.SteelBlue),
                CreateElement("Salmon", 400, 200, 10, TextureAddressMode.Border, Color.Salmon, Color.SteelBlue),
                CreateElement("PowderBlue", 190, 200, 10, TextureAddressMode.Border, Color.PowderBlue, Color.SteelBlue),
                CreateElement("Orange", 200, 230, 10, TextureAddressMode.Border, Color.Orange, Color.SteelBlue),
                CreateElement("Silver", 100, 170, 10, TextureAddressMode.Border, Color.Silver, Color.SteelBlue),
                CreateElement("SlateGray", 100, 170, 10, TextureAddressMode.Border, Color.SlateGray, Color.SteelBlue),
                CreateElement("Tan", 140, 110, 10, TextureAddressMode.Border, Color.Tan, Color.SteelBlue),
            };

            var texturePacker = new TexturePacker
            {
                AllowMultipack = false,
                AllowRotation  = true,
                MaxHeight      = 1024,
                MaxWidth       = 1024
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);

            // Obtain texture atlases
            var textureAtlases = texturePacker.AtlasTextureLayouts;

            Assert.Single(textureAtlases);

            if (!texturePacker.AllowNonPowerOfTwo)
            {
                Assert.True(MathUtil.IsPow2(textureAtlases[0].Width));
                Assert.True(MathUtil.IsPow2(textureAtlases[0].Height));
            }

            // Create atlas texture
            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(textureAtlases[0], false);

            SaveAndCompareTexture(atlasTexture, "TestCreateTextureAtlasToOutput");

            Assert.Equal(textureAtlases[0].Width, atlasTexture.Description.Width);
            Assert.Equal(textureAtlases[0].Height, atlasTexture.Description.Height);

            atlasTexture.Dispose();

            foreach (var texture in textureAtlases.SelectMany(textureAtlas => textureAtlas.Textures))
            {
                texture.Texture.Dispose();
            }
        }
        public void TestTextureAtlasFactoryImageParts()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElementFromFile("imagePart0", 26, TextureAddressMode.Border, TextureAddressMode.Mirror, new RotableRectangle(0, 0, 128, 128)),
                CreateElementFromFile("imagePart0", 26, TextureAddressMode.Clamp, TextureAddressMode.Clamp, new RotableRectangle(128, 128, 128, 128)),
                CreateElementFromFile("imagePart0", 26, TextureAddressMode.MirrorOnce, TextureAddressMode.Wrap, new RotableRectangle(128, 0, 128, 128)),
                CreateElementFromFile("imagePart1", 26, TextureAddressMode.Clamp, TextureAddressMode.Mirror, new RotableRectangle(376, 0, 127, 256)),
                CreateElementFromFile("imagePart1", 26, TextureAddressMode.Mirror, TextureAddressMode.Clamp, new RotableRectangle(10, 10, 254, 127)),
                CreateElement("empty", 0, 0, 26),
                CreateElementFromFile("imagePart2", 26, TextureAddressMode.Clamp, TextureAddressMode.Clamp, new RotableRectangle(0, 0, 128, 64)),
            };

            var texturePacker = new TexturePacker
            {
                AllowMultipack = false,
                AllowRotation  = true,
                MaxWidth       = 2048,
                MaxHeight      = 2048,
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);

            // Obtain texture atlases
            var textureAtlases = texturePacker.AtlasTextureLayouts;

            Assert.Single(textureAtlases);
            Assert.Equal(texturePacker.MaxWidth / 2, textureAtlases[0].Width);
            Assert.Equal(texturePacker.MaxHeight / 4, textureAtlases[0].Height);

            // Create atlas texture
            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(textureAtlases[0], false);

            Assert.Equal(textureAtlases[0].Width, atlasTexture.Description.Width);
            Assert.Equal(textureAtlases[0].Height, atlasTexture.Description.Height);

            SaveAndCompareTexture(atlasTexture, "TestTextureAtlasFactoryImageParts");

            textureElements[0].Texture.Dispose();
            atlasTexture.Dispose();
        }
        public void TestLoadImagesToCreateAtlas()
        {
            var textureElements = new List <AtlasTextureElement>();

            for (var i = 0; i < 8; ++i)
            {
                textureElements.Add(CreateElementFromFile("image" + i, 100, TextureAddressMode.Wrap, TextureAddressMode.Border));
            }

            for (var i = 0; i < 8; ++i)
            {
                textureElements.Add(CreateElementFromFile("image" + i, 100, TextureAddressMode.Mirror, TextureAddressMode.Clamp));
            }

            var texturePacker = new TexturePacker
            {
                AllowMultipack = false,
                AllowRotation  = false,
                MaxHeight      = 2048,
                MaxWidth       = 2048
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);

            // Obtain texture atlases
            var textureAtlases = texturePacker.AtlasTextureLayouts;

            // Create atlas texture
            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(textureAtlases[0], false);

            SaveAndCompareTexture(atlasTexture, "TestLoadImagesToCreateAtlas", ImageFileType.Dds);
            atlasTexture.Dispose();

            foreach (var texture in textureAtlases.SelectMany(textureAtlas => textureAtlas.Textures))
            {
                texture.Texture.Dispose();
            }
        }
        public void TestTextureAtlasFactoryRotation2()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElementFromFile("image9", 25, TextureAddressMode.Clamp, TextureAddressMode.Clamp),
                CreateElementFromFile("image10", 25, TextureAddressMode.Mirror, TextureAddressMode.Mirror),
            };

            var texturePacker = new TexturePacker
            {
                AllowMultipack     = false,
                AllowRotation      = true,
                AllowNonPowerOfTwo = true,
                MaxWidth           = 356,
                MaxHeight          = 306,
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);

            // Obtain texture atlases
            var textureAtlases = texturePacker.AtlasTextureLayouts;

            Assert.Single(textureAtlases);
            Assert.Equal(texturePacker.MaxWidth, textureAtlases[0].Width);
            Assert.Equal(texturePacker.MaxHeight, textureAtlases[0].Height);

            // Create atlas texture
            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(textureAtlases[0], false);

            Assert.Equal(textureAtlases[0].Width, atlasTexture.Description.Width);
            Assert.Equal(textureAtlases[0].Height, atlasTexture.Description.Height);

            SaveAndCompareTexture(atlasTexture, "TestTextureAtlasFactoryRotation2");

            textureElements[0].Texture.Dispose();
            atlasTexture.Dispose();
        }
        public void TestRegionOutOfTexture()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElementFromFile("image9", 10, TextureAddressMode.Mirror, TextureAddressMode.Clamp, new RotableRectangle(-100, 30, 400, 250)),
                CreateElementFromFile("image10", 10, TextureAddressMode.Wrap, TextureAddressMode.Border, new RotableRectangle(-50, -30, 300, 400, true)),
            };

            var texturePacker = new TexturePacker
            {
                AllowMultipack     = false,
                AllowRotation      = true,
                AllowNonPowerOfTwo = true,
                MaxWidth           = 1024,
                MaxHeight          = 1024,
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);

            // Obtain texture atlases
            var textureAtlases = texturePacker.AtlasTextureLayouts;

            Assert.Single(textureAtlases);

            // Create atlas texture
            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(textureAtlases[0], false);

            Assert.Equal(textureAtlases[0].Width, atlasTexture.Description.Width);
            Assert.Equal(textureAtlases[0].Height, atlasTexture.Description.Height);

            SaveAndCompareTexture(atlasTexture, "TestRegionOutOfTexture");

            textureElements[0].Texture.Dispose();
            atlasTexture.Dispose();
        }
        public void TestTextureAtlasFactory()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElement("A", 100, 200, 0, Color.MediumPurple),
            };

            var texturePacker = new TexturePacker
            {
                AllowMultipack = false,
                AllowRotation  = true,
                MaxHeight      = 2000,
                MaxWidth       = 2000
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.True(canPackAllTextures);

            // Obtain texture atlases
            var textureAtlases = texturePacker.AtlasTextureLayouts;

            Assert.Single(textureAtlases);
            Assert.True(MathUtil.IsPow2(textureAtlases[0].Width));
            Assert.True(MathUtil.IsPow2(textureAtlases[0].Height));

            // Create atlas texture
            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(textureAtlases[0], false);

            Assert.Equal(textureAtlases[0].Width, atlasTexture.Description.Width);
            Assert.Equal(textureAtlases[0].Height, atlasTexture.Description.Height);

            SaveAndCompareTexture(atlasTexture, "TestTextureAtlasFactory");

            textureElements[0].Texture.Dispose();
            atlasTexture.Dispose();
        }
        public void TestRotationElement2()
        {
            var textureElements = new List <AtlasTextureElement>
            {
                CreateElementFromFile("imageRotated1", 0, TextureAddressMode.Clamp, TextureAddressMode.Clamp)
            };

            var texturePacker = new TexturePacker
            {
                AllowMultipack = true,
                AllowRotation  = true,
                MaxWidth       = 256,
                MaxHeight      = 128,
            };

            var canPackAllTextures = texturePacker.PackTextures(textureElements);

            Assert.IsTrue(canPackAllTextures);
            Assert.AreEqual(1, texturePacker.AtlasTextureLayouts.Count);

            var atlasTexture = AtlasTextureFactory.CreateTextureAtlas(texturePacker.AtlasTextureLayouts[0]);

            SaveAndCompareTexture(atlasTexture, "TestRotationElement2");
        }
Exemple #9
0
            /// <summary>
            /// Creates and Saves texture atlas image from images in GroupAsset
            /// </summary>
            /// <param name="commandContext">The command context</param>
            /// <param name="spriteToPackedSprite">A map associating the packed sprite info to the original sprite</param>
            /// <returns>Status of building</returns>
            private ResultStatus CreateAtlasTextures(ICommandContext commandContext, out Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite)
            {
                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

                spriteToPackedSprite = new Dictionary <SpriteInfo, PackedSpriteInfo>();

                // Pack textures
                using (var texTool = new TextureTool())
                {
                    var textureElements = new List <AtlasTextureElement>();

                    // Input textures
                    var imageDictionary     = new Dictionary <string, Image>();
                    var imageInfoDictionary = new Dictionary <string, SpriteInfo>();

                    var  sprites           = Parameters.SheetAsset.Sprites;
                    var  packingParameters = Parameters.SheetAsset.Packing;
                    bool isSRgb            = Parameters.SheetAsset.IsSRGBTexture(Parameters.ColorSpace);

                    for (var i = 0; i < sprites.Count; ++i)
                    {
                        var sprite = sprites[i];
                        if (sprite.TextureRegion.Height == 0 || sprite.TextureRegion.Width == 0 || sprite.Source == null)
                        {
                            continue;
                        }

                        // Lazy load input texture and cache in the dictionary for the later use
                        Image texture;

                        if (!imageDictionary.ContainsKey(sprite.Source))
                        {
                            texture = LoadImage(texTool, new UFile(sprite.Source), isSRgb);
                            imageDictionary[sprite.Source] = texture;
                        }
                        else
                        {
                            texture = imageDictionary[sprite.Source];
                        }

                        var key = Url + "_" + i;

                        var sourceRectangle = new RotableRectangle(sprite.TextureRegion, sprite.Orientation == ImageOrientation.Rotated90);
                        textureElements.Add(new AtlasTextureElement(key, texture, sourceRectangle, packingParameters.BorderSize, sprite.BorderModeU, sprite.BorderModeV, sprite.BorderColor));

                        imageInfoDictionary[key] = sprite;
                    }

                    // find the maximum texture size supported
                    var maximumSize = TextureHelper.FindMaximumTextureSize(new TextureHelper.ImportParameters(Parameters), new Size2(int.MaxValue / 2, int.MaxValue / 2));

                    // Initialize packing configuration from GroupAsset
                    var texturePacker = new TexturePacker
                    {
                        Algorithm      = packingParameters.PackingAlgorithm,
                        AllowMultipack = packingParameters.AllowMultipacking,
                        MaxWidth       = maximumSize.Width,
                        MaxHeight      = maximumSize.Height,
                        AllowRotation  = packingParameters.AllowRotations,
                    };

                    var canPackAllTextures = texturePacker.PackTextures(textureElements);

                    if (!canPackAllTextures)
                    {
                        commandContext.Logger.Error("Failed to pack all textures");
                        return(ResultStatus.Failed);
                    }

                    // Create and save every generated texture atlas
                    for (var textureAtlasIndex = 0; textureAtlasIndex < texturePacker.AtlasTextureLayouts.Count; ++textureAtlasIndex)
                    {
                        var atlasLayout = texturePacker.AtlasTextureLayouts[textureAtlasIndex];

                        ResultStatus resultStatus;
                        using (var atlasImage = AtlasTextureFactory.CreateTextureAtlas(atlasLayout, isSRgb))
                            using (var texImage = texTool.Load(atlasImage, isSRgb))
                            {
                                var outputUrl         = SpriteSheetAsset.BuildTextureAtlasUrl(Url, textureAtlasIndex);
                                var convertParameters = new TextureHelper.ImportParameters(Parameters)
                                {
                                    OutputUrl = outputUrl
                                };
                                resultStatus = TextureHelper.ShouldUseDataContainer(Parameters.SheetAsset.IsStreamable && Parameters.SheetAsset.Type != SpriteSheetType.UI, texImage.Dimension)?
                                               TextureHelper.ImportStreamableTextureImage(assetManager, texTool, texImage, convertParameters, CancellationToken, commandContext) :
                                               TextureHelper.ImportTextureImage(assetManager, texTool, texImage, convertParameters, CancellationToken, commandContext.Logger);
                            }

                        foreach (var texture in atlasLayout.Textures)
                        {
                            spriteToPackedSprite.Add(imageInfoDictionary[texture.Name], new PackedSpriteInfo(texture.DestinationRegion, textureAtlasIndex, packingParameters.BorderSize));
                        }

                        if (resultStatus != ResultStatus.Successful)
                        {
                            // Dispose used textures
                            foreach (var image in imageDictionary.Values)
                            {
                                image.Dispose();
                            }

                            return(resultStatus);
                        }
                    }

                    // Dispose used textures
                    foreach (var image in imageDictionary.Values)
                    {
                        image.Dispose();
                    }
                }

                return(ResultStatus.Successful);
            }
            /// <summary>
            /// Creates and Saves texture atlas image from images in GroupAsset
            /// </summary>
            /// <param name="logger">Status Logger</param>
            /// <param name="spriteToPackedSprite">A map associating the packed sprite info to the original sprite</param>
            /// <returns>Status of building</returns>
            private ResultStatus CreateAtlasTextures(Logger logger, out Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite)
            {
                spriteToPackedSprite = new Dictionary <SpriteInfo, PackedSpriteInfo>();

                // Pack textures
                using (var texTool = new TextureTool())
                {
                    var textureElements = new List <AtlasTextureElement>();

                    // Input textures
                    var imageDictionary     = new Dictionary <string, Image>();
                    var imageInfoDictionary = new Dictionary <string, SpriteInfo>();

                    var sprites           = AssetParameters.SheetAsset.Sprites;
                    var packingParameters = AssetParameters.SheetAsset.Packing;

                    for (var i = 0; i < sprites.Count; ++i)
                    {
                        var sprite = sprites[i];
                        if (sprite.TextureRegion.Height == 0 || sprite.TextureRegion.Width == 0 || sprite.Source == null)
                        {
                            continue;
                        }

                        // Lazy load input texture and cache in the dictionary for the later use
                        Image texture;

                        if (!imageDictionary.ContainsKey(sprite.Source))
                        {
                            texture = LoadImage(texTool, new UFile(sprite.Source), AssetParameters.SheetAsset.SRgb);
                            imageDictionary[sprite.Source] = texture;
                        }
                        else
                        {
                            texture = imageDictionary[sprite.Source];
                        }

                        var key = Url + "_" + i;

                        var sourceRectangle = new RotableRectangle(sprite.TextureRegion, sprite.Orientation == ImageOrientation.Rotated90);
                        textureElements.Add(new AtlasTextureElement(key, texture, sourceRectangle, packingParameters.BorderSize, sprite.BorderModeU, sprite.BorderModeV, sprite.BorderColor));

                        imageInfoDictionary[key] = sprite;
                    }

                    // Initialize packing configuration from GroupAsset
                    var texturePacker = new TexturePacker
                    {
                        Algorithm      = packingParameters.PackingAlgorithm,
                        AllowMultipack = packingParameters.AllowMultipacking,
                        MaxHeight      = packingParameters.AtlasMaximumSize.Y,
                        MaxWidth       = packingParameters.AtlasMaximumSize.X,
                        AllowRotation  = packingParameters.AllowRotations,
                    };

                    var canPackAllTextures = texturePacker.PackTextures(textureElements);

                    if (!canPackAllTextures)
                    {
                        logger.Error("Failed to pack all textures");
                        return(ResultStatus.Failed);
                    }

                    // Create and save every generated texture atlas
                    for (var textureAtlasIndex = 0; textureAtlasIndex < texturePacker.AtlasTextureLayouts.Count; ++textureAtlasIndex)
                    {
                        var atlasLayout = texturePacker.AtlasTextureLayouts[textureAtlasIndex];

                        ResultStatus resultStatus;
                        using (var atlasImage = AtlasTextureFactory.CreateTextureAtlas(atlasLayout))
                            using (var texImage = texTool.Load(atlasImage))
                            {
                                var outputUrl         = SpriteSheetAsset.BuildTextureAtlasUrl(Url, textureAtlasIndex);
                                var convertParameters = new TextureHelper.ImportParameters(AssetParameters)
                                {
                                    OutputUrl = outputUrl
                                };
                                resultStatus = TextureHelper.ImportTextureImage(texTool, texImage, convertParameters, CancellationToken, logger);
                            }

                        foreach (var texture in atlasLayout.Textures)
                        {
                            spriteToPackedSprite.Add(imageInfoDictionary[texture.Name], new PackedSpriteInfo(texture.DestinationRegion, textureAtlasIndex, packingParameters.BorderSize));
                        }

                        if (resultStatus != ResultStatus.Successful)
                        {
                            // Dispose used textures
                            foreach (var image in imageDictionary.Values)
                            {
                                image.Dispose();
                            }

                            return(resultStatus);
                        }
                    }

                    // Dispose used textures
                    foreach (var image in imageDictionary.Values)
                    {
                        image.Dispose();
                    }
                }

                return(ResultStatus.Successful);
            }