WPF:寻找一种快速的方法来显示RGB到像素阵列(字节)以创建一个图像
问题描述:
我有一个数组=字节[512,512]在每个字段中我有一个值从0到255,然后代表灰色(从白色到黑色)每个像素。到现在为止,我用代码创建了一个代码,它为每个数组字段创建一个新的矩形(宽度为1高度1),然后将其放在画布上。这种方法很慢(至少在我的笔记本电脑上)。它通常需要30或40秒。WPF:寻找一种快速的方法来显示RGB到像素阵列(字节)以创建一个图像
如果有人能告诉我如何以其他方式做到这一点,我会非常高兴。 预先感谢您。
private void draw_a_pixel(Rectangle pixel, double top, int widthCounter)
{
Canvas.SetTop(pixel, Convert.ToInt32(top));
Canvas.SetLeft(pixel, widthCounter);
canvas1.Children.Add(pixel);
}
这是我认为需要最多时间的代码部分。
答
正如Chris所说,你应该使用WriteableBitmap
。
下面是一些材料开始:
/// <summary>
/// method that will create a source for your image object,
/// and fill it with a specified array of pixels
/// </summary>
/// <param name="pixels">your array of pixels</param>
/// <returns>your image object</returns>
public BitmapSource DrawImage(Int32[,] pixels)
{
int resX = pixels.GetUpperBound(0) + 1;
int resY = pixels.GetUpperBound(1) + 1;
WriteableBitmap writableImg = new WriteableBitmap(resX, resY, 96, 96, PixelFormats.Bgr32, null);
//lock the buffer
writableImg.Lock();
for (int i = 0; i < resX; i++)
{
for (int j = 0; j < resY; j++)
{
IntPtr backbuffer = writableImg.BackBuffer;
//the buffer is a monodimensionnal array...
backbuffer += j * writableImg.BackBufferStride;
backbuffer += i * 4;
System.Runtime.InteropServices.Marshal.WriteInt32(backbuffer, pixels[i,j]);
}
}
//specify the area to update
writableImg.AddDirtyRect(new Int32Rect(0, 0, resX, resY));
//release the buffer and show the image
writableImg.Unlock();
return writableImg;
}
您的阵列中的每个像素必须是一个Int32。 这里是一个函数,RGB颜色代码转换成的Int32
/// <summary>
/// Return the specified color code as a Int32
/// </summary>
public Int32 GetColor(byte r, byte g, byte b)
{
return Int32.Parse(Color.FromRgb(r, g, b).ToString().Trim('#'), System.Globalization.NumberStyles.HexNumber);
}
填写您的像素阵列你想要的方式。
将您的XAML添加为Image
并更新源代码。
<Image x:Name="Chart"/>
Chart.Source = DrawImage(pixels);
+0
非常感谢。你的解释是现货,你的代码样本工作100%! – N1no
答
您可以使用如下所示的方法从字节的二维数组创建灰度位图。像素阵列被复制到符合Gray8
格式的像素缓冲器中,即灰度与每像素8位。
public static BitmapSource GetBitmap(byte[,] pixels)
{
var width = pixels.GetUpperBound(0) + 1;
var height = pixels.GetUpperBound(1) + 1;
var buffer = new byte[width * height];
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
buffer[width * y + x] = pixels[x, y];
}
}
var bitmap = BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, buffer, width);
bitmap.Freeze();
return bitmap;
}
如果一个字节实际上代表的是从白到黑,而不是黑到白的范围值,只写
buffer[width * y + x] = (byte)(255 - pixels[x, y]);
你可能比在XAML
<Image x:Name="image" />
有一个图像控制
并将该位图分配给其Source属性:
image.Source = GetBitmap(pixels);
您还可以得到一个更灵活的用户界面,如果你在后台线程创建位图,像
image.Source = await Task.Run(() => GetBitmap(pixels));
像素阵列被称为图像..!看看'WriteableBitmap'。 – Chris
是的,像素逐像素不会很快......尽管30秒看起来极端。 – zzxyz
嗨克里斯我已经用WriteableBitmap尝试过,但我找不到任何如何生成它或稍后在画布上显示它的好例子。所以我希望如果你能分享一些关于这方面的知识,也许给我写了一个适用于我的案例的示例代码。 – N1no