XNA Texture2D.FromStream以1为单位暂时返回颜色通道

问题描述 投票:0回答:1

我目前正在加载并将用作映射图像的Texture2Ds保存到数据库中,以便以后可以预加载它们。每个颜色通道需要是加载后保存时的精确颜色。问题是Texture2D.FromStream有时返回错误的颜色通道,有时会偏差1左右。这是不可接受的,因为如果映射的颜色不正确,则它们是无用的。

下面的示例提供了一种情况,当alpha设置为100时,RGB为255,将其更改为RGB为254.当将alpha设置为1或255时,它们正确地返回255,其他alpha值导致相同的问题为100。

Texture2D tex = new Texture2D(GraphicsDevice, 20, 20, false, SurfaceFormat.Color);
Color[] data = new Color[tex.Width * tex.Height];
for (int i = 0; i < data.Length; i++) {
    data[i] = new Color(255, 255, 255, 100);
}
tex.SetData<Color>(data);
using (Stream stream = File.Open("TestAlpha.png", FileMode.OpenOrCreate)) {
    tex.SaveAsPng(stream, tex.Width, tex.Height);
    stream.Position = 0;
    tex = Texture2D.FromStream(GraphicsDevice, stream);
    tex.GetData<Color>(data);
    Console.WriteLine(data[0]); // Returns (R:254 G:254 B:254 A:100)
}

当我在Paint.NET中查看保存的图像时,我已经确认png具有正确的RGB 255,因此它只能是在Texture2D.FromStream期间引起的。

c# xna textures
1个回答
0
投票

好吧,我没有找到Texture2D.FromStream问题的原因,但我找到了一个更全面的方法来加载Texture2Ds。在这种情况下,我从流中加载GDI Bitmap,获取其数据,并将其传输到新创建的Texture2D

我打算使用它,无论Texture2D.FromSteam是否可以修复,但我仍然想知道是否有人知道它是怎么回事。

对于那些新手,请确保将System.Drawing作为参考包含在默认情况下不存在于XNA项目中。

public static unsafe Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream) {
    // Load through GDI Bitmap because it doesn't cause issues with alpha
    using (Bitmap bitmap = (Bitmap) Bitmap.FromStream(stream)) {
        // Create a texture and array to output the bitmap to
        Texture2D texture = new Texture2D(graphicsDevice,
            bitmap.Width, bitmap.Height, false, SurfaceFormat.Color);
        Color[] data = new Color[bitmap.Width * bitmap.Height];

        // Get the pixels from the bitmap
        Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
        BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly,
            PixelFormat.Format32bppArgb);

        // Write the pixels to the data buffer
        byte* ptr = (byte*) bmpData.Scan0;
        for (int i = 0; i < data.Length; i++) {
            // Go through every color and reverse red and blue channels
            data[i] = new Color(ptr[2], ptr[1], ptr[0], ptr[3]);
            ptr += 4;
        }

        bitmap.UnlockBits(bmpData);

        // Assign the data to the texture
        texture.SetData<Color>(data);

        // Fun fact: All this extra work is actually 50% faster than
        // Texture2D.FromStream! It's not only broken, but slow as well.

        return texture;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.