【问题标题】:Converting an array of Pixels to an image in C#在 C# 中将像素数组转换为图像
【发布时间】:2008-12-24 23:13:54
【问题描述】:

我的 C# 程序中有一个 int 像素数组,我想将其转换为图像。问题是我正在将程序的 Java 源代码转换为等效的 C# 代码。在 java 中,该行读取将 int 像素数组显示到图像中:

Image output = createImage(new MemoryImageSource(width, height, orig, 0, width));

谁能告诉我对应的 C# 代码吗?

这里的 orig 是int 像素的数组。我搜索了 Bitmap 类,有一个名为 SetPixel 的方法,但问题是它需要一个 x,y 坐标数。但我的代码中有一个int 像素数组。另一个奇怪的事情是我的 orig 数组有负数,它们离 255 很远。在 Java 中,情况相同(这意味着 C# 和 Java 中的数组具有相同的值)并且这些值在 Java 中工作正常。

但我无法将该行翻译成 C#。请帮忙。

【问题讨论】:

  • 负值可能是因为 int 值应该是无符号的。如果它们已签名,则不会打扰任何事情,但未签名会更有意义。

标签: c# java arrays pixels


【解决方案1】:

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

【讨论】:

  • 我一直在寻找这个,但我对 rawstride 值感到困惑。你的代码对我来说就像一个魅力......谢谢...... +1 :)
  • (width * pf.BitsPerPixel + 7) / 8 中的 7 和 8 来自哪里?
【解决方案2】:

您可以使用Bitmap.LockBits 获取位图数据,然后您可以直接操作,而不是通过 SetPixel。 (How to use LockBits)

【讨论】:

  • +1。如果需要对整张图片进行处理,那么SetPixel/GetPixel是SLOW的。
【解决方案3】:

我喜欢已经展示的 WPF 选项,但这里使用的是 LockBitsBitmap

        // 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;
    }

【讨论】:

    【解决方案4】:

    好吧,我假设每个 int 都是复合 ARGB 值?如果没有简单的选项,那么 LockBits 可能值得一看 - 它会比 SetPixel 快很多,但更复杂。您还必须确保知道 int 是如何组成的(ARGB?RGBA?)。我会尝试看看是否有更明显的选择...

    【讨论】:

      【解决方案5】:

      MemoryImageSource 的构造函数的第三个参数是一个由 argb 值按顺序组成的整数数组

      该页面中的示例通过以下方式创建了这样一个数组;

      pix[index++] = (255 << 24) | (red << 16) | blue;
      

      您需要将该整数数组分解为字节数组(移位运算符会很有用),但它应该按 bgr 顺序排列,LockBits 方法才能工作。

      【讨论】:

      • 您的链接似乎已失效。
      【解决方案6】:

      我建议使用 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;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-08-01
        • 1970-01-01
        • 2016-12-23
        • 2015-01-17
        • 1970-01-01
        • 2011-08-16
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        相关资源
        最近更新 更多