一尘不染

为什么在System.Drawing.Bitmap构造函数中“跨步”必须为4的倍数?

c#

我正在编写一个应用程序,要求我采用专有的位图格式(MVTec Halcon HImage)并将其转换为C#中的System.Drawing.Bitmap。

提供给我帮助实现此目的的唯一专有功能涉及我写入文件,但使用“获取指针”功能除外。

这个功能很棒,它给了我一个指向像素数据,宽度,高度和图像类型的指针。

我的问题是,当我使用构造函数创建System.Drawing.Bitmap时:

new System.Drawing.Bitmap(width, height, stride, format, scan)

我需要指定一个4的倍数的“步幅”。这可能是一个问题,因为我不确定我的函数将被打到什么尺寸的位图。假设我最终得到一个111x111像素的位图,除了将虚假列添加到图像中或减去3列之外,我无法运行此功能。

有没有办法可以绕过这个限制?


阅读 370

收藏
2020-05-19

共1个答案

一尘不染

这可以追溯到早期的CPU设计。处理位图位的最快方法是从扫描线的起点开始一次读取32位。当扫描线的第一个字节在32位地址边界上对齐时,效果最佳。换句话说,地址是4的倍数。在早期的CPU上,第一个字节未对齐的情况将花费额外的CPU周期,以便从RAM中读取两个32位字并混洗字节以创建32位值。确保每条扫描线都从对齐的地址开始(如果跨度为4的倍数,则为自动)可以避免这种情况。

在现代CPU上,这不再是真正的问题,现在对齐缓存行边界变得更加重要。尽管如此,由于应用程序的原因,跨度要求的4的倍数仍然存在。

顺便说一句,您可以使用此格式和宽度轻松计算步幅:

        int bitsPerPixel = ((int)format & 0xff00) >> 8;
        int bytesPerPixel = (bitsPerPixel + 7) / 8;
        int stride = 4 * ((width * bytesPerPixel + 3) / 4);
2020-05-19