图像编程学习笔记5——图像镜像
以下文字内容copy于<<数字图像处理编程入门>>,code为自己实现,是win32控制台程序。
镜象(mirror)分水平镜象和垂直镜象两种。图2.2的水平镜象和垂直镜象分别如图2.13和图2.14所示

图2.13 图2.2的水平镜象

图2.14 图2.2的垂直镜象
镜象的变换矩阵很简单。设原图宽为w,高为h,变换后,图的宽和高不变。
水平镜象的变化矩阵为:

(2.10)
垂直镜象的变化矩阵为:

(2.11)
镜象变换的源代码如下,因为和平移的那段程序很类似,程序中的注释就简单一些。
/*** 程序名: Mirror.cpp* 功 能: 实现灰度图像的水平镜像和垂直镜像* 测试图片test.bmp放在工程目录下*/#include <iostream>#include <windows.h>#include <fstream>#include <cstring>using namespace std;BITMAPFILEHEADER bmpFileHeader; //bmp文件头BITMAPINFOHEADER bmpInfoHeader; //bmp信息头RGBQUAD *pColorTable;//bmp颜色表unsigned char *pBmpData;//bmp位图数据unsigned char *pXBmpData; //水平镜像bmp位图数据unsigned char *pYBmpData; //垂直镜像bmp位图数据/*** 函数名: readBmp* 参 数: fileName -- 指向文件名的指针* 功 能: 读取将要处理的图片的信息,成功返回TRUE*/bool readBmp(char *fileName){FILE *fp = fopen(fileName,"rb"); //以二进制读方式打开if (NULL == fp){cout<<"open failure!"<<endl;return FALSE;}//获得图片数据fread(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);fread(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);pColorTable = new RGBQUAD[256];fread(pColorTable,sizeof(RGBQUAD),256,fp);int imgSize = bmpInfoHeader.biSizeImage;pBmpData = new unsigned char[imgSize];//因为大小没有改变,所以一起处理了pXBmpData = new unsigned char[imgSize];pYBmpData = new unsigned char[imgSize];fread(pBmpData,sizeof(unsigned char),imgSize,fp);fclose(fp);//关闭文件return TRUE;}/*** 函数名: mirror* 功 能: 对图片进行水平和垂直镜像操作*/void mirror(){int height = bmpInfoHeader.biHeight;int width = bmpInfoHeader.biWidth;int imgSize = bmpInfoHeader.biSizeImage;memset(pXBmpData,0,sizeof(unsigned char )*imgSize);memset(pYBmpData,0,sizeof(unsigned char )*imgSize);int lineByte = (width * 8 + 31) / 32 * 4; //每行像素的字节数for(int i = 0; i < height; i++ ){for(int j = 0; j < width; j++ ){*(pXBmpData + i*lineByte + width - 1 - j) = *(pBmpData + i*lineByte + j); //水平镜像*(pYBmpData + (height - i - 1)*lineByte + j) = *(pBmpData + i*lineByte + j); //垂直镜像}}}/*** 函数名: writeBmp* 参 数: fileName -- 处理完之后的bmp图像* 功 能: 写入文件数据到相应的文件中*/bool writeBmp(char *fileName,unsigned char *bmpData){FILE *fp = fopen(fileName,"wb"); //以二进制写方式打开if (NULL == fp){cout<<"open failure!"<<endl;return FALSE;}int imgSize = bmpInfoHeader.biSizeImage;//写入数据fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);fwrite(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);fwrite(pColorTable,sizeof(RGBQUAD),256,fp);fwrite(bmpData,sizeof(unsigned char),imgSize,fp);fclose(fp); //关闭文件return TRUE;}/*** 函数名: work* 功 能: 主要处理*/void work(){char readFileName[] = "test.bmp";if (!readBmp(readFileName)){cout<<"read failure!"<<endl;return ;}mirror();char writeFileNameX[] = "X.bmp";char writeFileNameY[] = "Y.bmp";if (!writeBmp(writeFileNameX,pXBmpData)){cout<<"X write failure!"<<endl;return ;}if (!writeBmp(writeFileNameY,pYBmpData)){cout<<"Y write failure!"<<endl;return ;}//释放delete []pColorTable;delete []pBmpData;delete []pXBmpData;delete []pYBmpData;cout<<"mirror success!"<<endl;}int main(){work();return 0;}