1

我有本质上是一个二维颜色数组,每个索引代表像素,值是该像素的颜色。为简单起见,让我们想象一个 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但似乎无法让它们工作。例如,下面的代码(我只是想把整个屏幕涂成黄色)会产生一个白色的图像(从这里借来的)。

位图源示例

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 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;
4

3 回答 3

4

以下代码适用于位图源和 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;
于 2012-08-14T04:52:52.507 回答
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

于 2012-08-13T08:00:48.110 回答
1

这篇博客描述了如何使用 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);
于 2012-08-13T07:56:33.027 回答