C# C语言中int数组的BMP转换#
在C#中,我无法将int(int32[,])的灰度数组转换为BMP格式。 我尝试在阵列中循环设置BMP中的像素颜色,它确实可以工作,但最终速度非常慢,几乎无法使用。 我在谷歌上搜索了很多,但我找不到我问题的答案。 我需要将图像实时放入一个图片盒中,这样方法就需要快速 相关讨论 编辑:数组的深度为8位,但存储为int32 Edit2:刚找到这个代码C# C语言中int数组的BMP转换#,c#,visual-studio,bitmap,C#,Visual Studio,Bitmap,在C#中,我无法将int(int32[,])的灰度数组转换为BMP格式。 我尝试在阵列中循环设置BMP中的像素颜色,它确实可以工作,但最终速度非常慢,几乎无法使用。 我在谷歌上搜索了很多,但我找不到我问题的答案。 我需要将图像实时放入一个图片盒中,这样方法就需要快速 相关讨论 编辑:数组的深度为8位,但存储为int32 Edit2:刚找到这个代码 private unsafe Task<Bitmap> BitmapFromArray(Int32[,] pixels, int
private unsafe Task<Bitmap> BitmapFromArray(Int32[,] pixels, int width, int height)
{
return Task.Run(() =>
{
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
for (int y = 0; y < height; y++)
{
byte* row = (byte*)bitmapData.Scan0 + bitmapData.Stride * y;
for (int x = 0; x < width; x++)
{
byte grayShade8bit = (byte)(pixels[x, y] >> 4);
row[x * 3 + 0] = grayShade8bit;
row[x * 3 + 1] = grayShade8bit;
row[x * 3 + 2] = grayShade8bit;
}
}
bitmap.UnlockBits(bitmapData);
return bitmap;
});
}
私有不安全任务BitmapFromArray(Int32[,]像素,int宽度,int高度)
{
返回任务。运行(()=>
{
位图位图=新位图(宽度、高度、像素格式.Format24bppRgb);
BitmapData BitmapData=bitmap.LockBits(新矩形(0,0,宽度,高度),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);
对于(int y=0;y>4);
行[x*3+0]=灰色阴影8bit;
行[x*3+1]=灰色阴影8bit;
行[x*3+2]=灰色阴影8bit;
}
}
位图。解锁位(bitmapData);
返回位图;
});
}
似乎工作速度足够快,但图像几乎是黑色的。如果我取下相机的顶部,图像应该是完全白色的,但它只是显示一个真正的深灰色。我猜它是把像素值解释为32位,而不是8位。然后尝试强制转换(ushort)像素[x,y],但不起作用已解决(必须删除四位移位):
私有不安全任务BitmapFromArray(Int32[,]像素,int宽度,int高度)
{
返回任务。运行(()=>
{
位图位图=新位图(宽度、高度、像素格式.Format24bppRgb);
BitmapData BitmapData=bitmap.LockBits(新矩形(0,0,宽度,高度),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);
对于(int y=0;y
仍然不确定为什么用format8bpindexed
替换Format24bppRgb
不起作用。有什么线索吗?I实际上,但当然,你不是从字节数组开始的,你是从二维Int32
数组开始的。绕过它的简单方法就是提前对其进行转换
将字节数组作为整数是一件相当奇怪的事情。如果这是从灰度图像中读取的,我宁愿假设这是32位ARGB数据,并且你只使用每个值的最低分量(蓝色分量),但是如果将值下移4位会产生统一的暗值,我倾向于相信你的话;否则,下一个颜色组分(绿色)的位会渗进来,也会产生明亮的颜色
不管怎样,撇开沉思和事后猜测不谈,这是我的实际答案
你可能会认为,当你的每一个值被注入一个8位图像时,仅仅是亮度,但这实际上是错误的。系统中没有特定的类型。绘制
像素格式以指示8位灰度,8位图像为调色板,这意味着图像上的每个值都指调色板上的一种颜色。因此,为了实际生成一个8位灰度图像,其中字节值指示像素的亮度,您需要明确定义一个调色板,其中调色板上0到255的索引包含从(0,0,0)到(255255)的灰色。当然,这很容易生成
此代码将把数组转换为8位图像。它使用前面提到的BuildImage
函数。请注意,该函数没有使用不安全的代码。使用Marshal.Copy
意味着从未直接处理原始指针,从而使代码完全处于管理状态
public static Bitmap FromTwoDimIntArrayGray(Int32[,] data)
{
// Transform 2-dimensional Int32 array to 1-byte-per-pixel byte array
Int32 width = data.GetLength(0);
Int32 height = data.GetLength(1);
Int32 byteIndex = 0;
Byte[] dataBytes = new Byte[height * width];
for (Int32 y = 0; y < height; y++)
{
for (Int32 x = 0; x < width; x++)
{
// logical AND to be 100% sure the int32 value fits inside
// the byte even if it contains more data (like, full ARGB).
dataBytes[byteIndex] = (Byte)(((UInt32)data[x, y]) & 0xFF);
// More efficient than multiplying
byteIndex++;
}
}
// generate palette
Color[] palette = new Color[256];
for (Int32 b = 0; i < 256; b++)
palette[b] = Color.FromArgb(b, b, b);
// Build image
return BuildImage(dataBytes, width, height, width, PixelFormat.Format8bppIndexed, palette, null);
}
TwoDiminArrayGray(Int32[,]数据)中的公共静态位图
{
//将二维Int32数组转换为1字节/像素字节数组
Int32 width=data.GetLength(0);
Int32 height=data.GetLength(1);
Int32 byteIndex=0;
字节[]数据字节=新字节[高度*宽度];
对于(Int32 y=0;y<高度;y++)
{
用于(Int32 x=0;xpublic static Bitmap FromTwoDimIntArrayGray(Int32[,] data)
{
// Transform 2-dimensional Int32 array to 1-byte-per-pixel byte array
Int32 width = data.GetLength(0);
Int32 height = data.GetLength(1);
Int32 byteIndex = 0;
Byte[] dataBytes = new Byte[height * width];
for (Int32 y = 0; y < height; y++)
{
for (Int32 x = 0; x < width; x++)
{
// logical AND to be 100% sure the int32 value fits inside
// the byte even if it contains more data (like, full ARGB).
dataBytes[byteIndex] = (Byte)(((UInt32)data[x, y]) & 0xFF);
// More efficient than multiplying
byteIndex++;
}
}
// generate palette
Color[] palette = new Color[256];
for (Int32 b = 0; i < 256; b++)
palette[b] = Color.FromArgb(b, b, b);
// Build image
return BuildImage(dataBytes, width, height, width, PixelFormat.Format8bppIndexed, palette, null);
}
public static Bitmap fromTwoDimIntArrayGray(Int32[,] data)
{
Int32 width = data.GetLength(0);
Int32 height = data.GetLength(1);
Int32 stride = width * 4;
Int32 byteIndex = 0;
Byte[] dataBytes = new Byte[height * stride];
for (Int32 y = 0; y < height; y++)
{
for (Int32 x = 0; x < width; x++)
{
// UInt32 0xAARRGGBB = Byte[] { BB, GG, RR, AA }
UInt32 val = (UInt32)data[x, y];
// This code clears out everything but a specific part of the value
// and then shifts the remaining piece down to the lowest byte
dataBytes[byteIndex + 0] = (Byte)(val & 0x000000FF); // B
dataBytes[byteIndex + 1] = (Byte)((val & 0x0000FF00) >> 08); // G
dataBytes[byteIndex + 2] = (Byte)((val & 0x00FF0000) >> 16); // R
dataBytes[byteIndex + 3] = (Byte)((val & 0xFF000000) >> 24); // A
// More efficient than multiplying
byteIndex+=4;
}
}
return BuildImage(dataBytes, width, height, stride, PixelFormat.Format32bppArgb, null, null);
}