bmp转mat

Timon---老赵 2020-06-01 10:19:13
现有一段代码是保存bmp图像的,如何能不去硬盘读图片,直接从内存获取图片的mat类型
static int i = 0;
int dataSize = 0;
char appExePath[256] = { 0 };
char appDir[256] = { 0 };
char saveBmpPath[256] = { 0 };
HINSTANCE hInst = AfxGetApp()->m_hInstance;
GetModuleFileName(hInst, appExePath, sizeof(appExePath));
_splitpath(appExePath, NULL, appDir, NULL, NULL);

Dahua::Infra::CTime currentTime = Dahua::Infra::CTime::getCurrentTime();


sprintf((char*)saveBmpPath, "%s\\Image\\Pic_%4d-%.2d-%.2d-%.2d-%.2d-%.2d_blockId#%d.bmp",
appDir, currentTime.year, currentTime.month, currentTime.day, currentTime.hour, currentTime.minute, currentTime.second, frameBuffer->bufPtr());

//sprintf(saveBmpPath, "%s\\Image\\Pic_blockId#%d.bmp", appDir, frameBuffer->BlockId());

HANDLE hFile = CreateFile(saveBmpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{

return;
}

unsigned int uRgbQuadLen = 0; //调色板,只有8bit以下才需要
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;

// 设置BMP文件头
bmpFileHeader.bfType = 0x4D42; // 文件头类型 'BM'(42 4D)
bmpFileHeader.bfSize = sizeof(bmpFileHeader) + sizeof(bmpInfoHeader) + frameBuffer->imageWidth() * frameBuffer->imageHeight() * 3; //文件大小
bmpFileHeader.bfReserved1 = 0; //保留字
bmpFileHeader.bfReserved2 = 0; //保留字

// 设置BMP信息头
bmpInfoHeader.biSize = 40; //信息头所占字节数
bmpInfoHeader.biWidth = frameBuffer->imageWidth(); //位图宽度
bmpInfoHeader.biHeight = frameBuffer->imageHeight(); //位图高度
bmpInfoHeader.biPlanes = 1; //位图平面数

/* 转码 */
if (frameBuffer->imagePixelFormat() == Dahua::GenICam::gvspPixelMono8)
{
dataSize = frameBuffer->bufSize();
bmpInfoHeader.biHeight = -frameBuffer->imageHeight();
bmpInfoHeader.biBitCount = 8;
uRgbQuadLen = sizeof(RGBQUAD) * 256;
bmpFileHeader.bfSize = sizeof(bmpFileHeader) + sizeof(bmpInfoHeader) + uRgbQuadLen + frameBuffer->imageWidth() * frameBuffer->imageHeight();
}
else
{
dataSize = frameBuffer->imageWidth() * frameBuffer->imageHeight() * 3;
bmpInfoHeader.biHeight = -frameBuffer->imageHeight(); //rgb数据保存为bmp,上下会颠倒,需要设置height为负值
bmpInfoHeader.biBitCount = 24; //像素位数
}

bmpFileHeader.bfOffBits = 54 + uRgbQuadLen; //位图像素数据的起始位置

bmpInfoHeader.biCompression = 0; //压缩类型,0 即不压缩
bmpInfoHeader.biSizeImage = 0;
bmpInfoHeader.biXPelsPerMeter = 0;
bmpInfoHeader.biYPelsPerMeter = 0;
bmpInfoHeader.biClrUsed = 0;
bmpInfoHeader.biClrImportant = 0;

DWORD dwWrite = 0;
WriteFile(hFile, &bmpFileHeader, sizeof(BITMAPFILEHEADER), &dwWrite, NULL);
WriteFile(hFile, &(bmpInfoHeader), sizeof(BITMAPINFOHEADER), &dwWrite, NULL);

if (frameBuffer->imagePixelFormat() == Dahua::GenICam::gvspPixelMono8)
{
static bool sbRgbQuadInit = false;
if (!sbRgbQuadInit)
{
for (int i = 0; i < 256; ++i)
{
g_rgbQuad[i].rgbBlue = g_rgbQuad[i].rgbGreen = g_rgbQuad[i].rgbRed = i;
}
sbRgbQuadInit = true;
}
WriteFile(hFile, g_rgbQuad, uRgbQuadLen, &dwWrite, NULL);
}

WriteFile(hFile, (BYTE*)(frameBuffer->bufPtr()), dataSize, &dwWrite, NULL);
CloseHandle(hFile);

下面是我找的转mat代码,但是保存的图片不一样
int bufsize = -bmpInfoHeader.biHeight*bmpInfoHeader.biWidth * 3;
uchar* buf = new uchar[bufsize];
uchar* reversebuf = new uchar[bufsize];
for (int rows = 0; rows < -bmpInfoHeader.biHeight; rows++)
{
for (int cols = 0; cols < bmpInfoHeader.biWidth; cols++)
{

memcpy(reversebuf + (rows*bmpInfoHeader.biWidth * 3),
buf + ((-bmpInfoHeader.biHeight - rows - 1)*bmpInfoHeader.biWidth * 3),
bmpInfoHeader.biWidth * 3);
}
}
Mat bmpmat1(-bmpInfoHeader.biHeight, bmpInfoHeader.biWidth, CV_8UC3);//定义Mat矩阵
memcpy(bmpmat1.data, reversebuf, bufsize);//复制图像数据
imshow("bmp to mat", bmpmat1);//显示图像


...全文
341 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
smwhotjay 2020-06-02
  • 打赏
  • 举报
回复
你需要找文件内存指针作为参数的api. 而不是文件名。

同时把输出写入文件的操作改成写入内存buff.
  • 打赏
  • 举报
回复
引用 2 楼 Timon---老赵 的回复:
主要是我看不懂厂家的写图程序,想在他写图的同时生成mat,而不需要再次读取磁盘。也就是想在第一段代码之后,利用一些第一段代码的信息,直接内存生存mat矩阵。

写图片的点阵信息主要是这个
frameBuffer->bufPtr()
看一下frameBuffer的数据组织方式就好,你给到的代码里面没有。需要你自己去看源码了。
Timon---老赵 2020-06-02
  • 打赏
  • 举报
回复
Mat bmpmat1 = cv::Mat(frameBuffer->imageHeight(), frameBuffer->imageWidth(), CV_8U, (BYTE*)(frameBuffer->bufPtr()));
Timon---老赵 2020-06-01
  • 打赏
  • 举报
回复
引用 1 楼 zjq9931 的回复:
这里有一个,可以直接获取像素值:
https://blog.csdn.net/wangyaninglm/article/details/41868599?ops_request_misc=&request_id=&biz_id=102&utm_term=GDI+%20shiter&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-41868599
主要是我看不懂厂家的写图程序,想在他写图的同时生成mat,而不需要再次读取磁盘。也就是想在第一段代码之后,利用一些第一段代码的信息,直接内存生存mat矩阵。
  • 打赏
  • 举报
回复
这里有一个,可以直接获取像素值:
https://blog.csdn.net/wangyaninglm/article/details/41868599?ops_request_misc=&request_id=&biz_id=102&utm_term=GDI+%20shiter&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-41868599

64,663

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧