现在的位置: 首页 > 综合 > 正文

【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现(转载) 【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现

2014年06月15日 ⁄ 综合 ⁄ 共 3373字 ⁄ 字号 评论关闭
分类: C/C++ 图像处理

通过我这些天用C++读写bmp图像的经历,摸索再摸索,终于对bmp文件的结构、操作有了一定的了解,下面就大概介绍bmp图片纯C++的读取、旋转和保存的实现过程。

要用C++读取bmp图片文件,首先要弄清楚bmp格式图片文件的结构。可以参考这篇文章:http://blog.csdn.net/xiajun07061225/article/details/5813726

有几点需要注意的是:

在读取bmp图片的时候,一定要注意内存对齐的问题,譬如文件头,否则无法读取出正确结果。

关于图片的像素数据,每一行的像素的字节数必须是4的整数倍。如果不是,则需要补齐。一般来说,bmp图像文件的数据是从下到上,从左到右的。即从文件中最先读到的是图像最下面一行的左边第一个像素,然后是坐标第二个.....接下来是倒数第二行的第一个像素。

采用的编译环境是VS2008。

关于图像旋转,并不难。只需要搞清楚像素坐标变换公式就行。我以图像的中心点为坐标原点。先把像素在目标图像中的位置变化为坐标系中的位置,做旋转变换求出变换之前的在坐标系中的坐标,再变换为子啊图片中的位置。

公式:(x1,y1)是变换之前的坐标系中的坐标,(x2,y2)是变换之后的坐标系中的坐标。angle为逆时针旋转的角度数。

x1 = cos(angle)*x2-sin(angle)*y2;
y1 = sin(angle)*x2-cos(angle)*y2;

我的代码分为两个版本:灰度图的和彩色图的。

灰度图:

灰度图是只含亮度信息,不含彩色信息的图像。bmp格式文件中并没有灰度图这个概念,但是我们很容易地用bmp文件来表示灰度图。方法是用256色的调色板,只不过这个调色板有点特殊,每一项的RGB值都是相同的,从(0,0,0),(1,1,1),...,一直到(255,255,255)。这样,灰度图就可以用256色图来表示了。其图像数据就是调色板索引值,也就是实际的RGB的亮度值。另外因为是256色的调色板,所以图像数据中的一个字节代表一个像素。如果是彩色的256色图,图像处理后可能会产生不属于这256色的颜色,所以,图像处理一般采用灰度图。这也可以更好地将重点放在算法上。

下面是灰度图旋转代码,能处理任意尺寸的bmp灰度图,以及旋转任意角度(逆时针)。

代码包括两个文件:BmpRot.h和BmpRot.cpp

BmpRot.h:

  1. typedef unsigned char BYTE;  
  2. typedef unsigned short WORD;  
  3. typedef unsigned int DWORD;  
  4. typedef long LONG;  
  5.   
  6. //位图文件头定义;  
  7. //其中不包含文件类型信息(由于结构体的内存结构决定,  
  8. //要是加了的话将不能正确读取文件信息)  
  9. typedef struct  tagBITMAPFILEHEADER{  
  10.     //WORD bfType;//文件类型,必须是0x424D,即字符“BM”  
  11.     DWORD bfSize;//文件大小  
  12.     WORD bfReserved1;//保留字  
  13.     WORD bfReserved2;//保留字  
  14.     DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数  
  15. }BITMAPFILEHEADER;  
  16.   
  17. typedef struct tagBITMAPINFOHEADER{  
  18.     DWORD biSize;//信息头大小  
  19.     LONG biWidth;//图像宽度  
  20.     LONG biHeight;//图像高度  
  21.     WORD biPlanes;//位平面数,必须为1  
  22.     WORD biBitCount;//每像素位数  
  23.     DWORD  biCompression; //压缩类型  
  24.     DWORD  biSizeImage; //压缩图像大小字节数  
  25.     LONG  biXPelsPerMeter; //水平分辨率  
  26.     LONG  biYPelsPerMeter; //垂直分辨率  
  27.     DWORD  biClrUsed; //位图实际用到的色彩数  
  28.     DWORD  biClrImportant; //本位图中重要的色彩数  
  29. }BITMAPINFOHEADER; //位图信息头定义  
  30.   
  31. typedef struct tagRGBQUAD{  
  32.     BYTE rgbBlue; //该颜色的蓝色分量  
  33.     BYTE rgbGreen; //该颜色的绿色分量  
  34.     BYTE rgbRed; //该颜色的红色分量  
  35.     BYTE rgbReserved; //保留值  
  36. }RGBQUAD;//调色板定义  
  37.   
  38. //像素信息  
  39. typedef struct tagIMAGEDATA  
  40. {  
  41.     BYTE blue;  
  42.     //BYTE green;  
  43.     //BYTE red;  
  44. }IMAGEDATA;  

BmpRot.cpp:

  1. #include <stdio.h>  
  2. #include "BmpRot.h"  
  3. #include "stdlib.h"  
  4. #include "math.h"  
  5. #include <iostream>  
  6.   
  7. #define PI 3.14159//圆周率宏定义  
  8. #define LENGTH_NAME_BMP 30//bmp图片文件名的最大长度  
  9.   
  10. using namespace std;  
  11.   
  12. //变量定义  
  13. BITMAPFILEHEADER strHead;  
  14. RGBQUAD strPla[256];//256色调色板  
  15. BITMAPINFOHEADER strInfo;  
  16.   
  17. //显示位图文件头信息  
  18. void showBmpHead(BITMAPFILEHEADER pBmpHead){  
  19.     cout<<"位图文件头:"<<endl;  
  20.     cout<<"文件大小:"<<pBmpHead.bfSize<<endl;  
  21.     cout<<"保留字_1:"<<pBmpHead.bfReserved1<<endl;  
  22.     cout<<"保留字_2:"<<pBmpHead.bfReserved2<<endl;  
  23.     cout<<"实际位图数据的偏移字节数:"<<pBmpHead.bfOffBits<<endl<<endl;  
  24. }  
  25.   
  26. void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead){  
  27.     cout<<"位图信息头:"<<endl;  
  28.     cout<<"结构体的长度:"<<pBmpInforHead.biSize<<endl;  
  29.     cout<<"位图宽:"<<pBmpInforHead.biWidth<<endl;  
  30.     cout<<"位图高:"<<pBmpInforHead.biHeight<<endl;  
  31.     cout<<"biPlanes平面数:"<<pBmpInforHead.biPlanes<<endl;  
  32.     cout<<"biBitCount采用颜色位数:"<<pBmpInforHead.biBitCount<<endl;  
  33.     cout<<"压缩方式:"<<pBmpInforHead.biCompression<<endl;  
  34.     cout<<"biSizeImage实际位图数据占用的字节数:"<<pBmpInforHead.biSizeImage<<endl;  
  35.     cout<<"X方向分辨率:"<<pBmpInforHead.biXPelsPerMeter<<endl;  
  36.     cout<<"Y方向分辨率:"<<pBmpInforHead.biYPelsPerMeter<<endl;  

抱歉!评论已关闭.