我需要从内存缓冲区遮罩图像(矩形区域填充黑色)。所以我天真地用ImageFormat重新使用Bitmap类。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);
我最终找到了这里:
- https://github.com/mono/libgdiplus/blob/6.0.4/src/bitmap.c L848
所以我的问题是:c#中是否有任何现有的类,我可以重用来保存pixelformat类型的图像:
- PixelFormat。Format8bppIndexed:
- PixelFormat。Format16bppGrayScale:
- PixelFormat。Format24bppRgb:
我知道GDI+不支持保存/显示16位图像,我只需要一个具有图像样式访问的内存结构。
仅供参考,我尝试了以下hack:
var image = new Bitmap(512,512,PixelFormat.Format24bppRgb);
image.Flags = ImageFlags.ColorSpaceGray;
但是Flags
是只读的。
正如你所看到的,GDI+Bitmap
在Linux上根本不支持16bpp灰度像素格式,实际上它在Windows上的支持也相当有限。收集了两个平台的限制后,参见不同平台上可能的像素格式的限制下的表格部分。
我需要从内存缓冲区屏蔽图像
要在Linux和Windows上使用完全托管的位图内存表示,您可以使用这个库(免责声明:由我编写)。您可以通过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
默认只在Windows上被支持。Microsoft建议使用其他库,但是您仍然可以通过将"System.Drawing.EnableUnixSupport": true
添加到runtimeconfig.json
来启用Unix支持。或者,如果您决定使用我上面提到的库,只需在执行其他操作之前调用DrawingModule.Initialize()
,这将启用Unix支持,而无需编辑任何配置文件。
我认为Wpf位图应该支持16位灰度。
然而,我工作过的大多数使用16位灰度图像的系统都使用自定义数据类型。比如:
public class My16BitImage{
public ushort[] Data {get;}
public int Width {get;}
public int Height {get;}
}
请注意,为了显示图像,您很可能需要将其转换为8位图像,并且您可能需要缩放值以使最大/最小值映射到最大/最小8位值。