24位位图BMP内存像素顺序是bgr,转成32位处理更快

在图形处理领域(如 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)
第三步:降位与保存

保存时,你依然面临两个选择:

  1. 手动写文件 :用嵌套循环,每 4 字节取前 3 字节写入文件,并手动补齐每行的 stride

  2. 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 类型的,操作起来会爽快得多。

相关推荐
专注VB编程开发20年7 小时前
C#WEBVBIEW2单点监听,多点分发;异步发起,信号唤醒
vb6·多媒体开发
专注VB编程开发20年4 个月前
VB编程语言最大源码项目VFB,photoDemon(类似PS的图像处理软件)
开源·vb6·photodemon
专注VB编程开发20年6 个月前
JSA变成类似vba环境给第三方软件集成IDE功能,脚本功能
ide·microsoft·node.js·vba·wps·vb6·jsa
专注VB编程开发20年6 个月前
VB.NET2003和VB2008可以导入VB6项目
.net·vb.net·vb6·vb2008
专注VB编程开发20年7 个月前
vb.net COM DLL 示例,实现了所有 VB6 X86 数据类型的对应
开发语言·前端·vb.net·com·vb6·activex dll
专注VB编程开发20年1 年前
在 VB6 中强制设置 Word 文档的纸张尺寸
ui·c#·word·vba·vb6
专注VB编程开发20年2 年前
vb6变体数据类型,Variant 类型的实质
开发语言·c#·vb6·variant·变体
专注VB编程开发20年2 年前
vb6多线程异步,VB.NET 全用API实现:CreateThread创建多线程,等待线程完成任务
爬虫·.net·线程池·vb6·vb6多线程·抢单·vba优化
专注VB编程开发20年2 年前
让EXCEL VBA支持鼠标滚轮,vb6 IDE鼠标滚轮插件原理
vb6·addin·vb6插件·hook api