使用Winform C#和Aforge库将传入图像缓冲区转换为Bitmap的最快方法
关于InvalidateImageData参数导致LockBits耗时变化的原因
InvalidateImageData参数的本质是控制GDI+在加载图像时是否提前完成全量像素解码:
- 设为
false时,GDI+仅加载JPEG的文件头、宽高等元信息,不会完成实际的压缩数据解码操作,像素数据解码会被推迟到首次需要访问像素的时候执行,因此FromStream阶段耗时很低。当你调用LockBits时才会触发完整的JPEG解码、像素格式转换、可编辑内存缓冲区分配的所有流程,耗时自然会转移到这一步。 - 设为
true时,FromStream阶段就会完成所有解码和预处理工作,把解好的像素数据存在可直接访问的DIB内存段中,因此FromStream耗时高,但后续LockBits只需要返回已存在的内存地址即可,耗时极低。
你观察到的两种方案总耗时基本一致,只是计算环节的阶段发生了转移。
更快的JPEG缓冲区转可用像素数据的方案
- 方案1:使用优化的JPEG解码库跳过不必要操作
你只需要提取指定行的颜色值,不需要完整的Bitmap对象,优先选择libjpeg-turbo这类带SIMD指令优化的JPEG解码库,它比GDI+内置的JPEG解码器性能高30%~60%,还支持按需解码指定行区间,不需要解出全图,整体耗时可以降到0.5ms以内。 - 方案2:预分配资源复用减少重复开销
如果必须使用System.Drawing的Bitmap对象,可以提前根据摄像头的固定分辨率、像素格式预创建Bitmap对象,每次解码后直接把像素数据写入预分配Bitmap的Scan0内存地址,避免每次创建Bitmap、分配内存的额外开销,总耗时可以降低15%左右。 - 方案3:使用WIC接口替代GDI+
Windows系统自带的WIC(Windows Imaging Component)解码器对JPEG格式的优化程度远高于GDI+的旧实现,相同解码场景下性能比Bitmap.FromStream高20%以上,而且支持直接从内存缓冲区解码,不需要额外封装流。
内容的提问来源于stack exchange,提问作者Nima
相关产品推荐
相关产品推荐

