【问题标题】:Structure for holding a 16bits grayscale image保存 16 位灰度图像的结构
【发布时间】:2021-11-25 13:48:11
【问题描述】:

我需要从内存缓冲区中屏蔽图像(用黑色填充的矩形区域)。所以我天真地将Bitmap 类与ImageFormat.MemoryBmp 一起用于我的API。这在我的本地机器上运行良好:

public static void MaskBitmap(Bitmap input, Rectangle maskRegion)
{
    var bytesPerPixel = Image.GetPixelFormatSize(input.PixelFormat) / 8;
    var row = new byte[maskRegion.Width * bytesPerPixel];

    var maskData = input.LockBits(maskRegion, ImageLockMode.WriteOnly, input.PixelFormat);
    for (var i = 0; i < maskData.Height; ++i)
    {
        Marshal.Copy(row, 0, maskData.Scan0 + (i * maskData.Stride), row.Length);
    }
    input.UnlockBits(maskData);
}

然而,当部署到生产环境时,结果发现下面的代码抛出了NotImplementedException

var image16 = new Bitmap(512, 512, PixelFormat.Format16bppGrayScale);

我最终找到了它:

所以我的问题是:c# 中是否有任何现有的类可以重复使用来保存pixelformat 类型的图像:

  • PixelFormat.Format8bppIndexed:
  • PixelFormat.Format16bppGrayScale:
  • PixelFormat.Format24bppRgb:

我知道 GDI+ does not support saving/displaying 16 位图像,我只需要一个具有图像样式访问的内存结构。


仅供参考,我尝试了以下技巧:

var image = new Bitmap(512,512,PixelFormat.Format24bppRgb);
image.Flags = ImageFlags.ColorSpaceGray;

但是Flags 是只读的。

【问题讨论】:

    标签: c# linux image mask


    【解决方案1】:

    如您所见,GDI+ Bitmap 在 Linux 上根本不支持 16bpp 灰度像素格式,实际上它在 Windows 上的支持也相当有限。一旦我收集了两个平台的限制,请参阅不同平台上可能的像素格式的限制部分下的表格here

    我需要从内存缓冲区中屏蔽图像

    要在 Linux 和 Windows 上使用完全托管的位图在内存中表示,您可以使用 this 库(免责声明:由我编写)。您可以通过BitmapDataFactory.CreateBitmapData 方法创建一个 16bpp 灰度位图数据,该方法返回一个允许大量托管操作的IReadWriteBitmapData(请参阅列出可用扩展方法的链接)。您甚至可以通过ToBitmap 扩展名将其转换为实际的Bitmap,但在Linux 上,这会将结果转换为具有24bpp RGB 像素格式的Bitmap

    例子:

    var image16 = BitmapDataFactory.CreateBitmapData(new Size(512, 512), PixelFormat.Format16bppGrayScale);
    var row = image16.FirstRow;
    do
    {
        for (int x = 0; x < image16.Width; x++)
        {
            // row[x] uses a Color32 structure (8 bit per color) but raw access
            // enables you to use the full 16-bit color range:
            row.WriteRaw<ushort>(x, 32768); // 50% gray
        }
    } while (row.MoveNextRow());
    
    
    

    至于 8bpp 索引和 24bpp RGB 格式,这些在 Linux 上也受到原生 Bitmap 的支持,但请注意,从版本 .NET 6 开始 System.Drawing 将支持 only on Windows by default。 Microsoft 建议改用other libraries,但您仍然可以通过将"System.Drawing.EnableUnixSupport": true 添加到runtimeconfig.json 来启用Unix 支持。或者,如果您决定使用我上面提到的库,只需先调用 DrawingModule.Initialize(),然后调用 enables Unix 即可,无需编辑任何配置文件。

    【讨论】:

      【解决方案2】:

      我认为Wpf bitmaps应该支持16位灰度。

      但是,我使用过的大多数使用 16 位灰度图像的系统都使用自定义数据类型。比如:

      public class My16BitImage{
          public ushort[] Data {get;}
          public int Width {get;}
          public int Height {get;}
      }
      

      请注意,为了显示图像,您很可能需要将其转换为 8 位图像,并且您可能需要缩放值以使最大/最小值映射到最大/最小 8 位值。

      【讨论】:

      • 很遗憾 WPF 不能在 Linux 上使用。
      • 似乎 WPF 是 way to go
      猜你喜欢
      • 2015-08-11
      • 2015-06-29
      • 2020-05-15
      • 1970-01-01
      • 2017-07-31
      • 2012-06-13
      • 2012-11-18
      • 1970-01-01
      • 2011-12-25
      相关资源
      最近更新 更多