如何在内存中翻转图像?

3
我想翻转一张图像并创建一个新的Texture2D翻转后的图像。 我做了一些研究,发现这段代码可以创建一个新的Texture2D;
RenderTarget2D newTarget = new RenderTarget2D(GraphicsDevice, partWidth, partHeight)

GraphicsDevice.SetRenderTarget(newTarget);

SpriteBatch.Draw(original, Vector2.Zero, partSourceRectangle, ... )

GraphicsDevice.SetRenderTarget(null);

Texture2D newTexture = (Texture2D)newTarget;

我理解新纹理易受内存清理的影响,因此建议我使用getData/SetData来创建一个更持久的纹理。有人能为我提供具体的语法吗?

您能详细说明为什么需要在内存中翻转吗?使用纹理变换不足以满足吗?我知道您可能有自己的原因,但如果不需要在内存中翻转,您可以节省很多计算周期。 - zero298
只要结果是一个新的纹理,纹理变换就很棒。 - blink
是的,这是XNA代码。C# - blink
我不是专家,但似乎 SpriteBatch.Draw() 的重载之一可以使用比例。如果您想翻转纹理 (镜像),则可以尝试传递 -1 作为比例值。如果您想要旋转它,那么请向函数传递旋转值,而不是比例值SpriteBatch.Draw() - zero298
另外,你绝对需要一个新纹理吗?如果你不打算进行其他任何处理,那么你可以使用 SpriteBatch.Draw() 来代替生成新纹理,并将其放置在你需要的位置。 - zero298
显示剩余3条评论
1个回答

5
下一个方法将翻转的纹理保存到新的Texture2D中:
    public Texture2D SaveAsFlippedTexture2D(Texture2D input, bool vertical, bool horizontal)
    {
        Texture2D flipped = new Texture2D(input.GraphicsDevice, input.Width, input.Height);
        Color[] data = new Color[input.Width * input.Height];
        Color[] flipped_data = new Color[data.Length];

        input.GetData<Color>(data);

        for (int x = 0; x < input.Width; x++)
        {
            for (int y = 0; y < input.Height; y++)
            {
                int index = 0;
                if (horizontal && vertical)
                    index = input.Width - 1 - x + (input.Height - 1 - y) * input.Width;
                else if (horizontal && !vertical)
                    index = input.Width - 1 - x + y * input.Width;
                else if (!horizontal && vertical)
                    index = x + (input.Height - 1 - y) * input.Width;
                else if (!horizontal && !vertical)
                    index = x + y * input.Width;

                flipped_data[x + y * input.Width] = data[index];
            }
        }

        flipped.SetData<Color>(flipped_data);

        return flipped;
    }  

例如: 加载我们的纹理,然后使用该方法,将我们的纹理作为参数传递以返回新的翻转纹理到另一个纹理。您也可以在游戏Update()方法中加载您的内容。

    Texture2D texture;
    Texture2D flippedTextureHorizontal;
    Texture2D flippedTextureVertical;
    Texture2D flippedTextureVerticalHorizontal;
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        texture = Content.Load<Texture2D>("kitty-cat");
        flippedTextureHorizontal = SaveAsFlippedTexture2D(texture, false, true);
        flippedTextureVertical = SaveAsFlippedTexture2D(texture, true, false);
        flippedTextureVerticalHorizontal = SaveAsFlippedTexture2D(texture, true, true);
    }

绘图方法:

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.None, RasterizerState.CullCounterClockwise);
        spriteBatch.Draw(texture, Vector2.Zero, null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
        spriteBatch.Draw(flippedTextureHorizontal, new Vector2(texture.Width + offset, 0), null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
        spriteBatch.Draw(flippedTextureVertical, new Vector2(texture.Width * 2 + offset * 2, 0), null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
        spriteBatch.Draw(flippedTextureVerticalHorizontal, new Vector2(texture.Width * 3 + offset * 3, 0), null, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
        spriteBatch.End();
        base.Draw(gameTime);
    }

输出: 输出 该算法也可在此处找到。 以下代码可以同时实现水平和垂直翻转,但不确定是否100%正确。
test = new Texture2D(GraphicsDevice, texture.Width, texture.Height);
int size = texture.Width * texture.Height;
Color[] data = new Color[size];
texture.GetData<Color>(data);
Array.Reverse(data, texture.Width, size - texture.Width);
test.SetData<Color>(data);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接