openCv学习笔记(十一)—位图的读取与存储(c语言实现)

来源:互联网 发布:转行it 编辑:程序博客网 时间:2024/05/21 10:00
typedef unsigned char BYTE;typedef unsigned short WORD;typedef unsigned int DWORD;typedef long LONG;//位图文件头定义;//其中不包含文件类型信息(由于结构体的内存结构决定,//要是加了的话将不能正确读取文件信息)typedef struct tagRGBQUAD{BYTE rgbBlue; //该颜色的蓝色分量BYTE rgbGreen; //该颜色的绿色分量BYTE rgbRed; //该颜色的红色分量BYTE rgbReserved; //保留值}RGBQUAD;//调色板定义typedef struct  tagBITMAPFILEHEADER{//WORD bfType;//文件类型,必须是0x424D,即字符“BM”DWORD bfSize;//文件大小WORD bfReserved1;//保留字WORD bfReserved2;//保留字DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数}BITMAPFILEHEADER;typedef struct tagBITMAPINFOHEADER{DWORD biSize;//信息头大小LONG biWidth;//图像宽度LONG biHeight;//图像高度WORD biPlanes;//位平面数,必须为1WORD biBitCount;//每像素位数DWORD  biCompression; //压缩类型DWORD  biSizeImage; //压缩图像大小字节数LONG  biXPelsPerMeter; //水平分辨率LONG  biYPelsPerMeter; //垂直分辨率DWORD  biClrUsed; //位图实际用到的色彩数DWORD  biClrImportant; //本位图中重要的色彩数}BITMAPINFOHEADER; //位图信息头定义//像素信息typedef struct tagIMAGEDATA{int *data;RGBQUAD strPla[256];//256色调色板//BYTE green;//BYTE red;}IMAGEDATA;#include <stdio.h>//#include "BmpRot.h"#include "stdlib.h"#include "math.h"#include <iostream>//#define PI 3.14159//圆周率宏定义#define LENGTH_NAME_BMP 30//bmp图片文件名的最大长度using namespace std;//变量定义//BITMAPFILEHEADER strHead;//RGBQUAD strPla[256];//256色调色板//BITMAPINFOHEADER strInfo;//显示位图文件头信息void showBmpHead(BITMAPFILEHEADER pBmpHead){cout<<"位图文件头:"<<endl;cout<<"文件大小:"<<pBmpHead.bfSize<<endl;cout<<"保留字_1:"<<pBmpHead.bfReserved1<<endl;cout<<"保留字_2:"<<pBmpHead.bfReserved2<<endl;cout<<"实际位图数据的偏移字节数:"<<pBmpHead.bfOffBits<<endl<<endl;}void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead){cout<<"位图信息头:"<<endl;cout<<"结构体的长度:"<<pBmpInforHead.biSize<<endl;cout<<"位图宽:"<<pBmpInforHead.biWidth<<endl;cout<<"位图高:"<<pBmpInforHead.biHeight<<endl;cout<<"biPlanes平面数:"<<pBmpInforHead.biPlanes<<endl;cout<<"biBitCount采用颜色位数:"<<pBmpInforHead.biBitCount<<endl;cout<<"压缩方式:"<<pBmpInforHead.biCompression<<endl;cout<<"biSizeImage实际位图数据占用的字节数:"<<pBmpInforHead.biSizeImage<<endl;cout<<"X方向分辨率:"<<pBmpInforHead.biXPelsPerMeter<<endl;cout<<"Y方向分辨率:"<<pBmpInforHead.biYPelsPerMeter<<endl;cout<<"使用的颜色数:"<<pBmpInforHead.biClrUsed<<endl;cout<<"重要颜色数:"<<pBmpInforHead.biClrImportant<<endl;}void ReadImage(char *path,tagBITMAPINFOHEADER &pBmpInforHead,BITMAPFILEHEADER &pBmpHead,IMAGEDATA *imagedata){BITMAPFILEHEADER strHead;    //RGBQUAD strPla[256];//256色调色板    BITMAPINFOHEADER strInfo;unsigned char *data;    FILE *fp;    fp=fopen(path,"rb");if(fp == NULL){cout<<"open file error"<<endl;return;}WORD bfType;fread(&bfType,1,sizeof(WORD),fp);if(0x4d42!=bfType){cout<<"the file is not a bmp file!"<<endl;return ;}//读取bmp文件的文件头和信息头fread(&strHead,1,sizeof(tagBITMAPFILEHEADER),fp);//showBmpHead(strHead);//显示文件头fread(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fp);//showBmpInforHead(strInfo);//显示文件信息头//读取调色板for(unsigned int nCounti=0;nCounti<strInfo.biClrUsed;nCounti++){fread((char *)&(imagedata->strPla[nCounti].rgbBlue),1,sizeof(BYTE),fp);fread((char *)&(imagedata->strPla[nCounti].rgbGreen),1,sizeof(BYTE),fp);fread((char *)&(imagedata->strPla[nCounti].rgbRed),1,sizeof(BYTE),fp);fread((char *)&(imagedata->strPla[nCounti].rgbReserved),1,sizeof(BYTE),fp);}    intwidth = strInfo.biWidth;int height = strInfo.biHeight;int nxy = width*height;//图像每一行的字节数必须是4的整数倍//width = (width * sizeof(BYTE) + 3) / 4 * 4;//imagedata = (IMAGEDATA*)malloc(width * height * sizeof(IMAGEDATA));data = (unsigned char*)malloc(width * height*sizeof(BYTE));    imagedata->data=(int*)malloc(width * height*sizeof(int));fread(data,sizeof(BYTE), width*height,fp);int *temp;temp = imagedata->data;for( int i = 0;  i < nxy;  i++, temp++, data++ ){*temp = (int) (255-(*data));//读取数据,取反,复制给intdat//int p=  (int) (*data);//cout<<p<<endl;//*temp=p;}fclose(fp);showBmpInforHead(strInfo);//显示文件信息头showBmpHead(strHead);//显示文件头pBmpInforHead=strInfo;pBmpHead = strHead;}void SaveImage(char *path,tagBITMAPINFOHEADER pBmpInforHead,BITMAPFILEHEADER pBmpHead,IMAGEDATA imagedata, IMAGEDATA data_result){   //保存bmp图片//RGBQUAD strPla[256];//256色调色板 FILE *fpw;if((fpw=fopen(path,"wb"))==NULL){cout<<"create the bmp file error!"<<endl;return ;}WORD bfType_w=0x4d42;fwrite(&bfType_w,1,sizeof(WORD),fpw);//fpw +=2;fwrite(&pBmpHead,1,sizeof(tagBITMAPFILEHEADER),fpw);//strInfo.biWidth = 2 * width;//strInfo.biHeight = 2 * height;fwrite(&pBmpInforHead,1,sizeof(tagBITMAPINFOHEADER),fpw);//保存调色板数据for(unsigned int nCounti=0;nCounti<pBmpInforHead.biClrUsed;nCounti++){fwrite(&imagedata.strPla[nCounti].rgbBlue,1,sizeof(BYTE),fpw);fwrite(&imagedata.strPla[nCounti].rgbGreen,1,sizeof(BYTE),fpw);fwrite(&imagedata.strPla[nCounti].rgbRed,1,sizeof(BYTE),fpw);fwrite(&imagedata.strPla[nCounti].rgbReserved,1,sizeof(BYTE),fpw);}//保存像素数据for(int i =0;i < pBmpInforHead.biHeight;++i){for(int j = 0;j < pBmpInforHead.biWidth;++j){fwrite( &((*(data_result.data + i * pBmpInforHead.biWidth + j))),1,sizeof(BYTE),fpw);//fwrite( &((*(imagedataRot + i * 2 * width + j)).green),1,sizeof(BYTE),fpw);//fwrite( &((*(imagedataRot + i * 2 * width + j)).red),1,sizeof(BYTE),fpw);}}fclose(fpw);//释放内存delete[] imagedata.data;delete[] data_result.data;}/*int main(){char strFile[LENGTH_NAME_BMP];//bmp文件名IMAGEDATA *imagedata = NULL;//动态分配存储原图片的像素信息的二维数组IMAGEDATA *imagedataRot = NULL;//动态分配存储旋转后的图片的像素信息的二维数组int width,height;//图片的宽度和高度cout<<"请输入所要读取的文件名:"<<endl;cin>>strFile;FILE *fpi,*fpw;fpi=fopen(strFile,"rb");if(fpi != NULL){//先读取文件类型WORD bfType;fread(&bfType,1,sizeof(WORD),fpi);if(0x4d42!=bfType){cout<<"the file is not a bmp file!"<<endl;return NULL;}//读取bmp文件的文件头和信息头fread(&strHead,1,sizeof(tagBITMAPFILEHEADER),fpi);//showBmpHead(strHead);//显示文件头fread(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fpi);//showBmpInforHead(strInfo);//显示文件信息头//读取调色板for(unsigned int nCounti=0;nCounti<strInfo.biClrUsed;nCounti++){fread((char *)&(strPla[nCounti].rgbBlue),1,sizeof(BYTE),fpi);fread((char *)&(strPla[nCounti].rgbGreen),1,sizeof(BYTE),fpi);fread((char *)&(strPla[nCounti].rgbRed),1,sizeof(BYTE),fpi);fread((char *)&(strPla[nCounti].rgbReserved),1,sizeof(BYTE),fpi);}width = strInfo.biWidth;height = strInfo.biHeight;//图像每一行的字节数必须是4的整数倍width = (width * sizeof(IMAGEDATA) + 3) / 4 * 4;//imagedata = (IMAGEDATA*)malloc(width * height * sizeof(IMAGEDATA));imagedata = (IMAGEDATA*)malloc(width * height);imagedataRot = (IMAGEDATA*)malloc(2 * width * 2 * height * sizeof(IMAGEDATA));//初始化原始图片的像素数组for(int i = 0;i < height;++i){for(int j = 0;j < width;++j){(*(imagedata + i * width + j)).blue = 0;//(*(imagedata + i * width + j)).green = 0;//(*(imagedata + i *  width + j)).red = 0;}}//初始化旋转后图片的像素数组for(int i = 0;i < 2 * height;++i){for(int j = 0;j < 2 * width;++j){(*(imagedataRot + i * 2 * width + j)).blue = 0;//(*(imagedataRot + i * 2 * width + j)).green = 0;//(*(imagedataRot + i * 2 * width + j)).red = 0;}}//fseek(fpi,54,SEEK_SET);//读出图片的像素数据fread(imagedata,sizeof(struct tagIMAGEDATA) * width,height,fpi);fclose(fpi);}else{cout<<"file open error!"<<endl;return NULL;}//图片旋转处理int RotateAngle;//要旋转的角度数double angle;//要旋转的弧度数int midX_pre,midY_pre,midX_aft,midY_aft;//旋转所围绕的中心点的坐标midX_pre = width / 2;midY_pre = height / 2;midX_aft = width;midY_aft = height;int pre_i,pre_j,after_i,after_j;//旋转前后对应的像素点坐标cout<<"输入要旋转的角度(0度到360度,逆时针旋转):"<<endl;cin>>RotateAngle;angle = 1.0 * RotateAngle * PI / 180;for(int i = 0;i < 2 * height;++i){for(int j = 0;j < 2 * width;++j){after_i = i - midX_aft;//坐标变换after_j = j - midY_aft;pre_i = (int)(cos((double)angle) * after_i - sin((double)angle) * after_j) + midX_pre;pre_j = (int)(sin((double)angle) * after_i + cos((double)angle) * after_j) + midY_pre;if(pre_i >= 0 && pre_i < height && pre_j >= 0 && pre_j < width)//在原图范围内*(imagedataRot + i * 2 * width + j) = *(imagedata + pre_i * width + pre_j);}}//保存bmp图片if((fpw=fopen("b.bmp","wb"))==NULL){cout<<"create the bmp file error!"<<endl;return NULL;}WORD bfType_w=0x4d42;fwrite(&bfType_w,1,sizeof(WORD),fpw);//fpw +=2;fwrite(&strHead,1,sizeof(tagBITMAPFILEHEADER),fpw);strInfo.biWidth = 2 * width;strInfo.biHeight = 2 * height;fwrite(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fpw);//保存调色板数据for(unsigned int nCounti=0;nCounti<strInfo.biClrUsed;nCounti++){fwrite(&strPla[nCounti].rgbBlue,1,sizeof(BYTE),fpw);fwrite(&strPla[nCounti].rgbGreen,1,sizeof(BYTE),fpw);fwrite(&strPla[nCounti].rgbRed,1,sizeof(BYTE),fpw);fwrite(&strPla[nCounti].rgbReserved,1,sizeof(BYTE),fpw);}//保存像素数据for(int i =0;i < 2 * height;++i){for(int j = 0;j < 2 * width;++j){fwrite( &((*(imagedataRot + i * 2 * width + j)).blue),1,sizeof(BYTE),fpw);//fwrite( &((*(imagedataRot + i * 2 * width + j)).green),1,sizeof(BYTE),fpw);//fwrite( &((*(imagedataRot + i * 2 * width + j)).red),1,sizeof(BYTE),fpw);}}fclose(fpw);//释放内存delete[] imagedata;delete[] imagedataRot;}*/
此程序实现了bmp图像的读取和存取,主要是理解位图的存储格式,这个程序就比较简单了,剩下的就是对数据流的操作。对于bmp图像结构可以看http://blog.csdn.net/caiye917015406/article/details/7849316
原创粉丝点击