OpenCV的IplImage转bmp

来源:互联网 发布:java 图片合成pdf 编辑:程序博客网 时间:2024/05/18 00:06


最近做项目,需要VB.NET调用,C++处理的图片。

如果c++处理的结果保存在磁盘上,然后Vb再读取的话,感觉过于占用磁盘IO,不绿色不环保。

因此想用内存映射文件的方式,进程之间传输图片。VB端先创建内存映射文件,然后调用C++程序,C++程序把处理的结果写入内存映射文件,VB端再对内存映射文件进行读取。

http://blog.csdn.net/u013162930/article/details/47606875

进程之间传输图片,就会遇到一个问题,就是需要把图片以一种VB和C++都能认识的方式进行传递。

我就想把OpenCV的IplImage转成bmp,再以byte的形式传递给VB.NET端,vb再解析读取图片。

那么如何才能把IplImage转为bmp呢~


bmp文件由四部分组成:位图文件头,位图信息段,调色板,位图数据。

把这四个部分拼接到一起,就是一个完整的bmp文件了。

我想处理的图像是灰度图,也就是256色的bmp。灰度图的调色板大小为1024字节,内容是R=G=B分别从0到255,而rgbReserved一直为0.

testBitmap是要转为bmp的iplImage图片。为全局变量。

[cpp] view plaincopyprint?
  1. FILE    *fpw;  
  2. //变量定义    
  3. BITMAPFILEHEADER strHead;  
  4. BITMAPINFOHEADER strInfo;   
  5. //初始化头文件。用0来填充内存区域  
  6. SecureZeroMemory(&strHead, sizeof(strHead));    
  7. SecureZeroMemory(&strInfo, sizeof(strInfo));  
  8. //初始化灰度图调色板  
  9. RGBQUAD *strPla = (RGBQUAD *)malloc(256*sizeof(RGBQUAD));//调色板的大小为1024字节  
  10. for (int i1 = 0; i1 < 256; i1++ ){  
  11.     strPla[i1].rgbRed = strPla[i1].rgbGreen = strPla[i1].rgbBlue = i1;  
  12.     strPla[i1].rgbReserved = 0;  
  13. }             
  14.     
  15. //写bitmapFileHeader  
  16. strHead.bfType = 0x4d42;//写入字符"BM"  
  17. strHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024 + (testBitmap->width + 3)/4*4 * testBitmap->height;    
  18. strHead.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024;  
  19. //写bitmapInfoHeader  
  20. strInfo.biSize = sizeof(strInfo);  
  21. strInfo.biHeight = testBitmap->height;  
  22. strInfo.biWidth = testBitmap->width;  
  23. strInfo.biPlanes = 1;  
  24. strInfo.biBitCount = 8;  
  25. strInfo.biCompression = BI_RGB;  
  26.   
  27. //保存bmp图片    
  28. if((fpw=fopen("M://abc.bmp","wb"))==NULL){    
  29.     cout<<"create the bmp file error!"<<endl;    
  30.     return NULL;    
  31. }  
  32. fwrite(&strHead,1,sizeof(strHead),fpw);   
  33. fwrite(&strInfo,1,sizeof(strInfo),fpw);  
  34. fwrite(strPla,1,1024,fpw);  

写完了文件头、信息段及调色板,我们接下来要写数据啦。

OpenCV IplImage->imageData中的信息是正着写入的,而bmp中的数据是从下到上,从左到右写入的。

而且IplImage->imageData的大小为(IplImage->width + 3)/4*4 * IplImage->height * IplImage->nChannels.

IplImage->nChannels = 3时,每一个像素点由3个字节来表示。因为是灰度图,所以我猜想其中所写的内容是R=G=B各占一个像素,所以有了如下的写法

[cpp] view plaincopyprint?
  1. char    *imgData = testBitmap->imageData;  
  2. char    *data = NULL;  
  3. data = (char*)malloc((testBitmap->width + 3)/4*4 * testBitmap->height);  
  4. for(int i=0;i<testBitmap->height;i++) for(int j=0;j<(testBitmap->width + 3)/4*4;j++)  
  5. data[i * ((testBitmap->width + 3)/4*4) + j] = testBitmap->imageData[3*((testBitmap->height - i - 1) * ((testBitmap->width + 3)/4*4) + j)];  
  6. fwrite(data,1,(testBitmap->width + 3)/4*4 * testBitmap->height,fpw);  
  7. fclose(fpw);  

IplImage->nChannels = 1时,每一个像素点由1个字节表示。

由于图像处理中,一般用的都是灰度图,所以创建图片的时候,最好就创建nChannels=1的iplImage

[cpp] view plaincopyprint?
  1. fullColorBitmap = cvLoadImage(fileNameFull, 1);  
  2. bmpWidth    = fullColorBitmap->width;  
  3. bmpHeight   = fullColorBitmap->height;  
  4. srcBitmap = cvCreateImage( cvSize(bmpWidth,bmpHeight), 8, 1);  
  5. cvCvtColor(fullColorBitmap, srcBitmap, CV_RGB2GRAY);  
nChannels=1时,imageData和bmp的位图数据格式基本相同,仅仅是bmp的位图数据一般都是从下到上的。

biHeight除了用于描述图像的高度之外,它还有另外一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,即数据的第一行其实是图像的最后一行,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是高度值是一个正数。

由于我们的位图数据是正着的,所以可以把biheight设置为负。

[cpp] view plaincopyprint?
  1. char    *imgData = temp->imageData;  
  2. strInfo.biHeight = -strInfo.biHeight;  
  3. fwrite(imgData ,1,(testBitmap->width + 3)/4*4 * testBitmap->height,fpw);  
  4. fclose(fpw);  


微笑到此就可以把iplImage转为bmp格式的了~


转载于:http://blog.csdn.net/u013162930/article/details/47415869


0 0
原创粉丝点击