XNA Texture2D.FromStream returns 颜色通道偶尔关闭 1
XNA Texture2D.FromStream returns color channels ocasionally off by 1
我目前正在将用作映射图像的 Texture2D
加载并保存到数据库中,以便稍后可以预加载它们。每个颜色通道都需要是加载后保存时的精确颜色。问题是 Texture2D.FromStream
有时 return 不正确的颜色通道 有时 相差 1 左右。这是不可接受的,因为映射的颜色如果不正确就没有用。
下面的示例提供了一种情况,当 alpha 设置为 100 时,RGB 255 变为 RGB 254。当将 alpha 设置为 1 或 255 时,它们 return 正确为 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
期间造成的。
好吧,我没有找到 Texture2D.FromStream
问题的原因,但我找到了 all-around 加载 Texture2D
的更好方法。在这种情况下,我改为从流中加载 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;
}
}
我目前正在将用作映射图像的 Texture2D
加载并保存到数据库中,以便稍后可以预加载它们。每个颜色通道都需要是加载后保存时的精确颜色。问题是 Texture2D.FromStream
有时 return 不正确的颜色通道 有时 相差 1 左右。这是不可接受的,因为映射的颜色如果不正确就没有用。
下面的示例提供了一种情况,当 alpha 设置为 100 时,RGB 255 变为 RGB 254。当将 alpha 设置为 1 或 255 时,它们 return 正确为 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
期间造成的。
好吧,我没有找到 Texture2D.FromStream
问题的原因,但我找到了 all-around 加载 Texture2D
的更好方法。在这种情况下,我改为从流中加载 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;
}
}