【问题标题】:Writing a 2D array of colors to a WPF image将二维颜色数组写入 WPF 图像
【发布时间】:2012-08-09 08:41:56
【问题描述】:

我有本质上是一个二维颜色数组,每个索引代表像素,值是该像素的颜色。为简单起见,让我们想象一个 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)。

位图源示例

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;

【问题讨论】:

    标签: wpf image colors bitmap


    【解决方案1】:

    以下代码适用于位图源和 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;
    

    【讨论】:

      【解决方案2】:

      使用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 实例中。

      【讨论】:

      • 在问题中查看我编辑的代码。你能弄清楚问题是什么吗?我是否必须将每个通道(R、G、B、A)放在一个单独的字节中?
      • 除了一次写一个像素真的不是很有用。关键是弄清楚步长是多少,以便可以正确读取字节数组。
      【解决方案3】:

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

      【讨论】:

      • 我对 strideLength 参数以及应该进入该像素阵列的内容感到非常困惑。我用一个无效的WriteableBitmaps 示例更新了我的问题。
      • 哎呀,我的意思是BitmapSource
      猜你喜欢
      • 1970-01-01
      • 2017-01-03
      • 1970-01-01
      • 1970-01-01
      • 2012-04-07
      • 1970-01-01
      • 2021-02-10
      • 2019-08-14
      • 2018-03-08
      相关资源
      最近更新 更多