XNA将单个图块保存为PNG

时间:2017-06-22 08:29:28

标签: c# xna

我有XNA的另一个问题。我有一个包含许多图块的Texture2D。然后我有一个矩形列表,它应该是每个50x50像素磁贴的边界。

现在我希望能够将任何磁贴保存为一个小的PNG文件。 这是我的代码:

//declare the rectangles and spritesets
Texture2D tileSheet;
List<Rectangle> tileSet;

//load every tile, also works great
tileSheet = Content.Load<Texture2D>(@"Tiles/Object");
int noOfTilesX = (int)tileSheet.Width / 50;
int noOfTilesY = (int)tileSheet.Height / 50;
tileSet = new List<Rectangle>(noOfTilesX * noOfTilesY);
for (int j = 0; j < noOfTilesY; j++)
{
    for (int i = 0; i < noOfTilesX; i++)
    {
        bounds = new Rectangle(i * 50, j * 50, 50, 50);
        tileSet.Add(bounds);
    }
}

//save as pngs if they do not exist
if (!File.Exists(@"C:\Test.png"))
{
    Stream stream = File.Create(@"C:\Test.png");
    //works, but it is only the complete file, i'd like to save a single tile
    tileSheet.SaveAsPng(stream, tileSheet.Width, tileSheet.Height);
}

问题是:我无法保存单个图块,它总是保存我的整个Texture2D并将其拉伸到我在参数中传递的分辨率。在互联网上搜索没有告诉我什么,它只是告诉我如何使用流来获得完整的纹理2D。

2 个答案:

答案 0 :(得分:1)

我刚刚回答了一个问题,其中某人想要通过采用更大纹理的一部分来获得新纹理,就像你的瓷砖问题一样。

您可以使用此扩展方法,然后像平常一样保存结果:

public static class TextureExtension
{
    /// <summary>
    /// Creates a new texture from an area of the texture.
    /// </summary>
    /// <param name="graphics">The current GraphicsDevice</param>
    /// <param name="rect">The dimension you want to have</param>
    /// <returns>The partial Texture.</returns>
    public static Texture2D CreateTexture(this Texture2D src, GraphicsDevice graphics, Rectangle rect)
    {
        Texture2D tex = new Texture2D(graphics, rect.Width, rect.Height);
        int count = rect.Width * rect.Height;
        Color[] data = new Color[count];
        src.GetData(0, rect, data, 0, count);
        tex.SetData(data);
        return tex;
    }
}

建议用法:

using (FileStream stream = File.OpenWrite("path"))
{
    tileTexture.CreateTexture(GraphicsDevice, new Rectangle(50, 50, 100, 100)).SaveAsJpeg(stream, 100, 100);
}

答案 1 :(得分:0)

尝试这样的事情。我没有对它进行测试,因此可能存在一些错误,但您只需为每个磁贴创建一个单独的纹理,然后保存每个纹理。

//declare the rectangles and spritesets
Texture2D tileSheet;
List<Rectangle> tileSet;

//load every tile, also works great
tileSheet = Content.Load<Texture2D>(@"Tiles/Object");
int noOfTilesX = (int)tileSheet.Width / 50;
int noOfTilesY = (int)tileSheet.Height / 50;
tileSet = new List<Rectangle>(noOfTilesX * noOfTilesY);

// Gets the color data of the tile sheet.
Color[] tileSheetPixels = new Color[tileSheet.Width * tileSheet.Height];
tileSheetPixels.GetData<Color>(tileSheetPixels);

for (int j = 0; j < noOfTilesY; j++)
{
    for (int i = 0; i < noOfTilesX; i++)
    {
        bounds = new Rectangle(i * 50, j * 50, 50, 50);
        tileSet.Add(bounds);

        // Creates a new texture for a single tile.
        Texture2D singleTile = new Texture2D(graphics, 50, 50);
        Color[] pixels = new Color[50 * 50];

        // Gets the pixels that correspond to the single tile and saves them in another
        // color array.
        for (int k = 0; k < pixels.Length; k++)
        {
            pixels[k] = new Color();

            int x = bounds.X;
            x += (k % 50);
            int y = bounds.Y;
            y += (k / 50);

            pixels[k] = tileSheetPixels[y * 50 + x];
        }

        // Sets the color data of the single tile texture to the color array
        // created above.
        singleTile.SetData<Color>(pixels);

        //save as pngs if they do not exist
        if (!File.Exists(@"C:\tile_" + i + "_" + j + ".png"))
        {
            Stream stream = File.Create(@"C:\tile_" + i + "_" + j + ".png");

            singleTile.SaveAsPng(stream, 50, 50);
        }
    }
}