1bpp 位图:将代码从 BitmapData 转换为 ImageSharp

问题描述 投票:0回答:1

我正在尝试将现有库从 .NET 4.8 迁移到 .NET 8.0。该库加载现有的 1 bpp 位图并将其转换为数组,然后在 Zebra 库上打印。这是依赖于

BitmapData
LockBits
的当前工作代码:

public ImageData GetImageBits() {        
    BitmapData? bits = null;
     ImageData data = new();
     try {
         bits = BitmapToPrint.LockBits(
               new Rectangle(0, 0, BitmapToPrint.Width, BitmapToPrint.Height),
               ImageLockMode.ReadOnly, 
               BitmapToPrint.PixelFormat);

         if( bits is null ) {
             throw new InvalidOperationException("Error creating bitmap data");
         }

         byte[] imageBytes = new byte[bits.Height *bits.Stride];
         Marshal.Copy(bits.Scan0, imageBytes, 0, bits.Stride *bits.Height);

         int imgWidth = bits.Stride;
         int imgHeight = bits.Height;
         int realWidth = bits.Width /8; //only works for fixed size bits

         if (realWidth != imgWidth) {
             int bytesToClear = imgWidth - realWidth;
             for (int i = 0; i < imgHeight; i++) {
                 int pos = realWidth + imgWidth *i;
                 for (int counter = 0; counter < bytesToClear; counter++, pos++) {
                     imageBytes[pos] = 255;
                 }
             }
         }

         data.ImageBytes = imageBytes;
         data.ImageHeight = imgHeight;
         data.ImageWidth = imgWidth;
     }
     finally {
         if (bits != null) {
             BitmapToPrint.UnlockBits(bits);
         }
     }
     return data;
}

代码首先锁定位图,然后使用

Stride
属性(如果我没记错的话,它返回带有填充的每行的正确大小)来计算保存位图字节的数组所需的大小.

复制字节后,该方法检查位图的宽度是否大于步幅,当发生这种情况时,它将“清理”字节(将其设置为 FF)。

我正在尝试将此代码迁移到 ImageSharp,但我对位图和 ImageSharp 的有限知识使这变得很困难。既然我们谈论的是 1 bpp 位图,那么我的印象是我应该依靠

Image<L8>
来加载我的位图:

// assume we're loading the bitmap from an embedded resource
Assembly assembly = typeof(Program).Assembly;
using Stream stream = assembly.GetManifestResourceStream("DemoImages.logoCABio.bmp");
Image<L8> bitmap = Image.Load<L8>(stream);

Image<L8>
我可以获取位图的宽度和高度,但是如何恢复步幅?看来我应该能够使用与此类似的代码访问位图字节:

byte[] bytes = new byte[bitmap.Width*bitmap.Height*bitmap.PixelType.BitsPerPixel/8];
bitmap.CopyPixelDataTo(bytes);

但是,当我将

LockBits
方法中的字节数组与此方法进行比较时,它完全关闭,并且 Zebra 根本不会打印它(它只会生成几行)。

当我查看初始代码时,很容易看出 stride 是计算数组大小的一个重要属性(它也会传递给 zebra 代码,以便它可以从数组中找到“位图行” )。有人知道如何用 ImageSharp 计算这个吗?

谢谢。

bitmap .net-8.0 imagesharp
1个回答
0
投票

几个小时后,我终于让它开始工作了。关于我关于计算步幅的问题,我终于明白了:

ushort bpp = 1; // in my case, I'm working with 1bpp pixels
int stride = (int)(4 * ((((uint)BitmapToPrint.Width * bpp) + 31) / 32));
int padding = bytesPerLine - (int)(BitmapToPrint.Width * (bpp / 8F));

看起来步幅(即位图每行的字节数)应该始终与 32 位地址边界对齐。获得步幅后,您还可以轻松计算填充,以添加“丢失的字节”,使步幅与 32 位地址对齐。

现在,仍然存在一个问题:仅将

Image<L8>
实例封装的位图数组放入可传递给 Zebra 打印机的 1bpp 数组中。不幸的是,ImageSharp 不支持将子字节打包像素放入内存(这就是为什么我必须使用
L8
格式加载图像)。然而,该库能够通过
BmpEncoder
将图像导出为 1bpp 位图,并且很容易调整其代码以仅适用于 1bpp 位图数组(在我的情况下,我只需调整
Write1BitPalette
方法以确保当位图宽度不是 8 的倍数时它填充所有位)。

六项劳动的家伙们构建了如此出色的框架表示极大的赞誉!

© www.soinside.com 2019 - 2024. All rights reserved.