C# 高效保存工业相机8位图像为BMP文件

259 阅读4分钟

前言

在工业视觉和机器视觉领域,图像处理的性能至关重要。尤其是在高速图像采集场景中,如何快速、高效地将图像数据保存为标准格式(如 BMP),是一个常见但又容易被忽视的问题。

本文介绍了一种直接基于图像指针句柄,无需通过 Bitmap 或中间拷贝操作,将 8bit 灰度图像保存为标准 BMP 文件的方法。该方法适用于从工业相机获取原始图像数据后需要立即存储或传输的高性能场景,实测保存一张图像仅需 2~3ms,非常适合用于实时图像处理系统。

正文

一、问题背景

在使用工业相机进行图像采集时,通常会得到一个指向图像内存区域的指针句柄(即 IntPtr)。如果直接将其转换为 Bitmap 再调用 .Save() 方法保存,虽然实现简单,但其背后进行了不必要的数据拷贝操作,影响性能。

为了提升效率,我们可以直接操作图像指针并手动构建 BMP 文件结构,从而避免中间转换过程,实现高效的图像保存。

二、BMP 图像文件结构简述

BMP 文件由以下几部分组成:

1、BMP 文件头(BITMAPFILEHEADER):固定大小 14 字节

2、BMP 信息头(BITMAPINFOHEADER):固定大小 40 字节

3、调色板(Palette):对于 8bit 图像,需要 256 色调色板,共 1024 字节

4、像素数据(Pixel Data)

由于我们只处理 8bit 图像,因此只需创建灰度调色板即可。

三、实现步骤

1、创建 FileStream 对象

首先,我们需要创建一个 FileStream 实例来写入图像数据。

private void SaveAs8BitBitmap(string filePath)
{
    using var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
}

2、创建并缓存文件头与信息头

由于图像尺寸通常不变,文件头和信息头可以预先创建并缓存,提高效率。

定义常量与全局变量:

const int HEADERSIZE = 14 + 40;
byte* _headerPtr; // BMP信息头
int _width, _height;
IntPtr _pBits; // 图像数据指针
int _totalBytes; // 图像总字节数
int paletteSize = 256 * 4;
byte* _palettePtr;

// 在构造函数或其他初始化方法中分配内存
_headerPtr = (byte*)Marshal.AllocHGlobal(HEADERSIZE);
_palettePtr = (byte*)Marshal.AllocHGlobal(paletteSize);

创建文件头和信息头的 Span 数据:

private ReadOnlySpan<byte> CreateHeaderSpan()
{
    // 构建 BITMAPFILEHEADER 和 BITMAPINFOHEADER
    // …具体代码略(参考后续图示)
    return new ReadOnlySpan<byte>(_headerPtr, HEADERSIZE);
}

释放资源:

public void Dispose()
{
    Marshal.FreeHGlobal((IntPtr)_headerPtr);
    Marshal.FreeHGlobal((IntPtr)_palettePtr);
}

3、构建调色板

对于 8bit 图像,我们只需要 256 级灰度调色板:

for (int i = 0; i < 256; i++)
{
    span.Fill((byte)i);
    Buffer.MemoryCopy(temp, _palettePtr + (i << 2), size, size);
}

4、写入图像数据

最后,将图像指针的数据直接写入流中:

fs.Write(CreateHeaderSpan());
fs.Write(new ReadOnlySpan<byte>(_palettePtr, paletteSize));
fs.Write(new ReadOnlySpan<byte>((byte*)_pBits, _totalBytes));

这种方式完全跳过了 Bitmap 的创建和数据复制,实现了极致性能优化。

四、性能测试结果

经过实际测试,在普通 PC 上(CPU: Intel i5-12400F,内存16GB),保存一张分辨率为 1280x1024 的 8bit 图像,耗时仅为 2~3ms

总结

本文介绍了一种C# 中直接通过图像指针句柄保存 8bit 图像为 BMP 格式的高效方式。主要优点包括:

  • 无需创建 Bitmap,避免了额外的内存拷贝;

  • 文件头和调色板可缓存复用,提升连续保存效率;

  • 支持嵌入到工业相机图像采集流程中,满足高帧率图像处理需求;

  • 性能优异,单张图像保存时间仅需 2~3ms

此技术方案特别适合应用于工业检测、视觉引导、智能监控等对图像处理速度要求较高的场合。同时,也为开发者提供了一个低层控制图像格式生成的思路,便于进一步扩展自定义图像处理逻辑。

关键词:C#、工业相机、8bit图像、BMP图像保存、图像处理、高性能、内存操作、指针编程

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:码上dotNet

出处:mp.weixin.qq.com/s/EYiiiwilnC9uBmZLiDv27g

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!