将2D颜色数组写入WPF图像

时间:2012-08-13 06:01:53

标签: wpf image colors bitmap

我的本​​质上是一个二维颜色数组,每个索引代表像素,值是该像素的颜色。为简单起见,让我们设想一个3x3像素阵列,基本上有1像素的红色行,1像素的绿色行和1像素的蓝色行:

Color[,] colorArray = new Color[3,3];

for (int i = 0; i < 3; ++i) 
{
    colorArray[0,i] = Colors.Red;
    colorArray[1,i] = Colors.Green;
    colorArray[2,i] = Colors.Blue;
}

我有一个带有图像的XAML文件(为简单起见,我们假设图像也是3x3像素)。如何将上述像素数据写入可以在该图像文件中显示的内容?

修改 我尝试过同时使用WriteableBitmapsBitmapSources,但似乎无法让它们正常运行。例如,下面的代码(我只是试图将整个屏幕画成黄色)会产生一个白色图像(借用here)。

BitmapSource示例

uint[] pixelData = new uint[width * height];
for (int y = 0; y < height; ++y)
{
    int yIndex = y * width;
    for (int x = 0; x < width; ++x)
    {
        pixelData[x + yIndex] = (0 << 24) + (255 << 16) + (255 << 8) + 255;
    }
}

var bmp = BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, width * 4);
TestImage.Source = bmp;

WriteableBitmap示例

WriteableBitmap wb = new WriteableBitmap(width, height, dpi, dpi, pf, null);
byte[] pixelData = new byte[height * width * 4];

for (int i = 0; i < (int)wb.Height; i++)
{
    for (int j = 0; j < (int)wb.Width; j++)
    {
        var color = colors[i, j];
        var idx = j * 4 + i * width * 4;

        byte blue = color.B;
        byte green = color.G;
        byte red = color.R;

        pixelData[idx] = blue;
        pixelData[idx + 1] = green;
        pixelData[idx + 2] = red;
        pixelData[idx + 3] = 255;

        //byte[] colorData = { blue, green, red, 255 };
        //Int32Rect rect = new Int32Rect(j, i, 1, 1);
        //wb.WritePixels(rect, colorData, 4, 0);
    }
}

Int32Rect rect = new Int32Rect(0, 0, width, height);
wb.WritePixels(rect, pixelData, 4, 0);
TestImage.Source = wb;

3 个答案:

答案 0 :(得分:3)

以下代码适用于位图源和32位颜色:

var height = colorArray.GetUpperBound(0) + 1;
var width = colorArray.GetUpperBound(1) + 1;
var pixelFormat = PixelFormats.Bgra32;
var stride = width * 4; // bytes per row

byte[] pixelData = new byte[height * stride];

for (int y = 0; y < height; ++y)
{
    for (int x = 0; x < width; ++x)
    {
        var color = colorArray[y, x];
        var index = (y * stride) + (x * 4);

        pixelData[index] = color.B;
        pixelData[index + 1] = color.G;
        pixelData[index + 2] = color.R;
        pixelData[index + 3] = color.A; // color.A;
    }
}

var bitmap = BitmapSource.Create(width, height, 96, 96, pixelFormat, null, pixelData, stride);
Image.Source = bitmap;

答案 1 :(得分:1)

This blog描述了如何使用BitmapSource从带有像素的字节数组创建图像。

以下是该博客的代码:

double dpi = 96;
int width = 128;
int height = 128;
byte[] pixelData = new byte[width*height];

for (int y = 0; y < height; ++y)
{
    int yIndex = y * width;
    for (int x = 0; x < width; ++x)
    {
        pixelData[x + yIndex] = (byte) (x + y);
    }
}

BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi,PixelFormats.Gray8, null, pixelData, width);

答案 2 :(得分:1)

使用WriteableBitmap课程。 WritePixels方法正是您所需要的。 (msdn

你的例子:

WriteableBitmap wb = new WriteableBitmap(3, 3, 96, 96, PixelFormats.Bgra32, null);

for (int i = 0; i < (int) wb.Height; i++)
{
    byte blue  = (byte) (i == 2 ? 255 : 0),
         green = (byte) (i == 1 ? 255 : 0),
         red   = (byte) (i == 0 ? 255 : 0);

    byte[] colorData = {blue, green, red, 255};

    for (int j = 0; j < (int) wb.Width; j++)
    {
      Int32Rect rect = new Int32Rect(j, i, 1, 1);
      wb.WritePixels(rect, colorData, 4, 0);
    }
 }

 img.Source = wb;

但是如果你想绘制一幅大图,你不应该每次写一个像素。它可能很慢。相反,您应该填充字节数组并将其复制到您的WritableBitmap实例中。