提问人: 提问时间:12/25/2008 最后编辑:Jeff Atwood 更新时间:11/23/2020 访问量:18078
在 C 中将像素数组转换为图像#
Converting an array of Pixels to an image in C#
问:
我的 C# 程序中有一个像素数组,我想将其转换为图像。问题是我正在将程序的 Java 源代码转换为等效的 C# 代码。在 java 中,该行显示 int 像素数组为 image:int
Image output = createImage(new MemoryImageSource(width, height, orig, 0, width));
有人可以告诉我 C# 等效项吗?
这里 orig 是像素数组。我搜索了 Bitmap 类,并且调用了一个方法,但问题是它需要一个 x,y 坐标号。但是我的代码中有一个像素数组。另一件奇怪的事情是我的 orig 数组是负数,它们离 255 很远。在 Java 中,情况相同(这意味着 C# 和 Java 中的数组都具有等效的值),并且这些值在 Java 中工作正常。int
SetPixel
int
但是我无法将该行翻译成 C#。请帮忙。
答:
可以使用 Bitmap.LockBits 获取位图数据,然后可以直接操作这些数据,而不是通过 SetPixel。(如何使用 LockBits)
评论
好吧,我假设每个 int 都是复合 ARGB 值?如果没有一个简单的选项,那么 LockBits 可能值得一看 - 它会比 快得多,但更复杂。你还必须确保你知道 int 是如何组成的(ARGB?RGBA?我会试着看看是否有更明显的选择......SetPixel
使用 WPF,可以直接从数组创建位图(图像)。然后,您可以对此图像进行编码或显示或玩转它:
int width = 200;
int height = 200;
//
// Here is the pixel format of your data, set it to the proper value for your data
//
PixelFormat pf = PixelFormats.Bgr32;
int rawStride = (width * pf.BitsPerPixel + 7) / 8;
//
// Here is your raw data
//
int[] rawImage = new int[rawStride * height / 4];
//
// Create the BitmapSource
//
BitmapSource bitmap = BitmapSource.Create(
width, height,
96, 96, pf, null,
rawImage, rawStride);
评论
(width * pf.BitsPerPixel + 7) / 8
我建议使用 LockBits,但较慢的基于 SetPixel 的算法可能看起来像
// width - how many int's per row
// array - array of integers
Bitmap createImage(int width, int[] array)
{
int height = array.Length / width;
Bitmap bmp = new Bitmap(width, height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < array.Length; x += width)
{
bmp.SetPixel(x, y, Color.FromArgb(array[i]));
}
}
return bmp;
}
MemoryImageSource 构造函数的第三个参数是一个整数数组,由按该顺序排列的 argb 值组成
该页面中的示例通过以下方式创建此类数组;
pix[index++] = (255 << 24) | (red << 16) | blue;
您需要将该整数数组分解为字节数组(移位运算符很有用),但它应该按 bgr 顺序排列,以便 LockBits 方法正常工作。
评论
我喜欢已经介绍的 WPF 选项,但这里它使用 和 :LockBits
Bitmap
// get the raw image data
int width, height;
int[] data = GetData(out width, out height);
// create a bitmap and manipulate it
Bitmap bmp = new Bitmap(width,height, PixelFormat.Format32bppArgb);
BitmapData bits = bmp.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, bmp.PixelFormat);
unsafe
{
for (int y = 0; y < height; y++)
{
int* row = (int*)((byte*)bits.Scan0 + (y * bits.Stride));
for (int x = 0; x < width; x++)
{
row[x] = data[y * width + x];
}
}
}
bmp.UnlockBits(bits);
使用(作为测试数据):
public static int[] GetData(out int width, out int height)
{
// diagonal gradient over a rectangle
width = 127;
height = 128;
int[] data = new int[width * height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int val = x + y;
data[y * width + x] = 0xFF << 24 | (val << 16) | (val << 8) | val;
}
}
return data;
}
评论