在图形处理领域(如 GDI+ 或 Photoshop 内部),通常都会将图片统一升位到 32位 (ARGB) 进行计算。处理完后,只有在最后落盘保存时才压缩回 24位。
这样做有三个不可替代的优势:
1. 极致的计算速度 (DWord Alignment)
在 32 位模式下,每个像素正好占 4 字节 。这刚好是一个 Long 的长度,也是 CPU 处理内存最舒服的步进。
-
24位定位 :
n = y * stride + x * 3(涉及乘法,且不能被 2 的幂整除) -
32位定位 :
n = y * W + x(如果 W 是 2 的幂,CPU 甚至可以用位移指令完成计算)
2. 内存对齐 (No Padding)
32 位图片的每一行字节数(W \\times 4)永远是 4 的倍数。这意味着你完全不需要考虑 stride 补齐字节。每一行都是紧凑且对齐的。
3. 支持透明度 (Alpha Channel)
虽然 BMP 24位不支持透明,但在 32 位内存中处理时,你可以利用那多出来的第 4 个字节存储透明度,实现图层混合(Alpha Blending)。
实现流程建议
第一步:加载与升位
不要手动读取,最快的方法是利用 Windows 的 DIB (Device Independent Bitmap)。
使用 CreateDIBSection 创建一个 32 位的内存画布,然后把 24 位 BMP 贴上去。
第二步:高速处理
这时你可以使用你最想要的 Long 数组 绑定技术:
VBA
' 此时每一格就是一个像素,直接赋值
像素Long(x + y * W) = &HFF0000 ' 纯蓝色 (假设是 0x00BBGGRR)
第三步:降位与保存
保存时,你依然面临两个选择:
-
手动写文件 :用嵌套循环,每 4 字节取前 3 字节写入文件,并手动补齐每行的
stride。 -
API 转换 :利用
GetDIBits直接将 32 位内存数据转换并填充到一张 24 位的位图句柄中,然后保存。
性能对比表
| 特性 | 24位直接处理 (Byte) | 32位内存处理 (Long) |
|---|---|---|
| 内存定位 | 复杂 (x*3) |
极简 (x + y*W) |
| 写入次数 | 3 次 (B, G, R) | 1 次 (Long) |
| 逻辑复杂度 | 需计算 Stride | 无需考虑 Stride |
| 额外开销 | 无 | 初始转换 + 最终降位 |
总结建议
-
如果你只是修改几个点 (比如打个水印、画几条线):直接用 24 位 Byte 数组,转换的开销远大于处理的收益。
-
如果你要做大规模图像算法 (比如全图滤镜、高斯模糊、图像合成):必须升位到 32 位。这种情况下,算法省下来的时间是极其可观的。
如果你决定走 32 位路线,你的 LongPtrX64 结构体中 SizeOfType 就要设为 4 (VT_I4),这样绑定出来的 Value() 数组就是 Long 类型的,操作起来会爽快得多。