镜像, 转置, 锐化, 灰度,旋转
/** * 函数名: 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); //垂直镜像 } } }
/**
* 函数名: transpose
* 功 能: 对图像进行转置处理 */
void transpose() { int height = bmpInfoHeader.biHeight; int width = bmpInfoHeader.biWidth; int imgSize = bmpInfoHeader.biSizeImage; //转置之后高宽变了 bmpInfoHeader.biHeight = width; bmpInfoHeader.biWidth = height; memset(pNewBmpData,0,sizeof(unsigned char )*imgSize); int lineByte = (width * 8 + 31) / 32 * 4; //每行像素的字节数 int newLineByte = (height * 8 + 31) / 32 * 4; //新的lineByte for(int i = 0; i < height; i++ ) { for(int j = 0; j < width; j++ ) { *(pNewBmpData + (width - 1 - j)*newLineByte + i) = *(pBmpData + (height - 1 - i)*lineByte + j); //转置 } } }
/** * 函数名: sharpening * 功 能: 对图像进行锐化处理 */ void Laplacian() { int temp[9] = {-1,-1,-1,-1,9,-1,-1,-1,-1}; //Laplacian 模版 int height = bmpInfoHeader.biHeight; int width = bmpInfoHeader.biWidth; int imgSize = bmpInfoHeader.biSizeImage; int lineByte = (width * 8 +31) / 32 * 4; //每行像素所占字节数 //处理是基于原图的,所以原图的数据不能改变,用pNewBmpData存储改变之后的数据 memcpy(pNewBmpData,pBmpData,imgSize); //把原图数据复制给pNewBmpData //注意边界点不处理,所以i从1到高度-2,j类似 double temResult; //中间结果 for(int i = 1; i < height - 1; i++ ) { for(int j = 1; j < width - 1; j++ ) { temResult = (double)(*(pBmpData + (i-1) * lineByte + j - 1) * temp[0]); temResult += (double)(*(pBmpData + (i-1) * lineByte + j) * temp[1]); temResult += (double)(*(pBmpData + (i-1) * lineByte + j + 1) * temp[2]); temResult += (double)(*(pBmpData + (i) * lineByte + j - 1) * temp[3]); temResult += (double)(*(pBmpData + (i) * lineByte + j) * temp[4]); temResult += (double)(*(pBmpData + (i) * lineByte + j + 1) * temp[5]); temResult += (double)(*(pBmpData + (i+1) * lineByte + j - 1) * temp[6]); temResult += (double)(*(pBmpData + (i+1) * lineByte + j) * temp[7]); temResult += (double)(*(pBmpData + (i+1) * lineByte + j + 1) * temp[8]); *(pNewBmpData + i * lineByte + j) = temResult; } } }
/** * 程序名: Rotation.cpp * 功 能: 实现灰度图像的旋转,如果超出原图范围,则用白色填充 * 测试位图为test.bmp放到工程目录下 */ #include <iostream> #include <fstream> #include <cstring> #include <cmath> #include <windows.h> using namespace std; #define PI 3.1415926535 #define RADIAN(angle) (((angle)*PI)/180.0) BITMAPFILEHEADER bmpFileHeader; //bmp文件头 BITMAPINFOHEADER bmpInfoHeader; //bmp信息头 RGBQUAD *pColorTable; //bmp颜色表 unsigned char *pBmpData; //bmp位图数据 unsigned char *pNewBmpData; //旋转后bmp位图数据 int newImgSize; //旋转后图像大小 /** * 函数名: readBmp * 参 数: fileName--要读取文件的文件名 * 功 能: 读取bmp位图数据,成功返回TRUE,否则返回FALSE */ BOOL readBmp(char *fileName) { FILE *fp = fopen(fileName,"rb"); //以二进制读方式打开 if (NULL == fp) { cout<<"The file is opened 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; //文图数据的大小,4的倍数 pBmpData = new unsigned char[imgSize]; fread(pBmpData,sizeof(unsigned char),imgSize,fp); fclose(fp); return TRUE; } /** * 函数名: rotation * 参 数: rotAngle--要转换的角度 * 功 能: 实现bmp图像的旋转 */ void rotation(int rotAngle) { double cosa,sina,srcX[4],srcY[4],dstX[4],dstY[4],rad; int oldWidth,oldHeight,newWidth,newHeight; rad = (double)RADIAN(rotAngle); cosa = cos(rad); sina = sin(rad); //原图宽与高 oldWidth = bmpInfoHeader.biWidth; oldHeight = bmpInfoHeader.biHeight; //原图四个角的坐标 srcX[0] = -0.5 * oldWidth; srcY[0] = 0.5 * oldHeight; srcX[1] = 0.5 * oldWidth; srcY[1] = 0.5 * oldHeight; srcX[2] = 0.5 * oldWidth; srcY[2] = -0.5 * oldHeight; srcX[3] = -0.5 * oldWidth; srcY[3] = -0.5 * oldHeight; //新图四个角坐标 for(int i = 0; i < 4; i++ ) { dstX[i] = cosa * srcX[i] + sina * srcY[i]; dstY[i] = -sina * srcX[i] + cosa * srcY[i]; // cout<<dstY[i]<<endl; } //新图的宽与高,向上取整 bmpInfoHeader.biWidth = newWidth = (int)(max(fabs(dstX[0] - dstX[2]),fabs(dstX[1] - dstX[3])) + 0.5); bmpInfoHeader.biHeight = newHeight = (int)(max(fabs(dstY[0] - dstY[2]),fabs(dstY[1] - dstY[3])) + 0.5); // cout<<newWidth<<newHeight<<endl; //新图位图数据大小 bmpInfoHeader.biSizeImage = newImgSize = newHeight * ((newWidth * bmpInfoHeader.biBitCount + 31) / 32 * 4); pNewBmpData = new unsigned char[newImgSize]; double temp1,temp2; //计算矩阵(2.9)中的两个常数,这样不用以后每次都计算了 temp1 = -0.5 * newWidth * cosa - 0.5 * newHeight * sina + 0.5 * oldWidth; temp2 = 0.5 * newWidth * sina - 0.5 * newHeight * cosa + 0.5 * oldHeight; memset(pNewBmpData,(BYTE)255,newImgSize); //先全部填充成白色 int x0,y0,x1,y1; unsigned char *pOldTemp,*pNewTemp; int oldLineByte,newLineByte; oldLineByte = (oldWidth * bmpInfoHeader.biBitCount + 31) / 32 * 4; newLineByte = (newWidth * bmpInfoHeader.biBitCount + 31) / 32 * 4; //把旋转后的图像数据对应存储到pNewBmpData相应位置 for(y1 = 0; y1 < newHeight; y1++) { for(x1 = 0; x1 < newWidth; x1++ ) { x0 = (int)(x1 * cosa + y1 * sina + temp1); y0 = (int)(-x1 * sina + y1 * cosa + temp2); if((x0 >= 0 && x0 < oldWidth) && (y0 >= 0 && y0 < oldHeight)) //这里不能为<=oldWidth或oldHeight { pOldTemp = pBmpData + (oldHeight - 1 - y0) * oldLineByte + x0; pNewTemp = pNewBmpData + (newHeight - 1 - y1) * newLineByte + x1; *pNewTemp = *pOldTemp; } } } } /** * 函数名: writeBmp * 参 数: bmpName -- 旋转后的bmp文件名 * 功 能: 新建一个bmp文件,把旋转后的图像信息存入其中 */ void writeBmp(char *bmpName) { FILE *fp = fopen(bmpName,"wb"); //以二进制写方式打开 if(NULL == fp) cout<<"The file is opened failure"<<endl; //写入选装后图像信息 fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp); fwrite(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp); fwrite(pColorTable,sizeof(RGBQUAD),256,fp); fwrite(pNewBmpData,sizeof(unsigned char),newImgSize,fp); fclose(fp); delete []pColorTable; delete []pNewBmpData; delete []pBmpData; } /** * 函数名: work * 参 数: 无 * 功 能: 实现处理工作 */ void work() { char readBmpName[] = "test.bmp"; if ( !readBmp(readBmpName)) cout<<"The file "<<readBmpName<<"is read failure"<<endl; cout<<"please input the angle to rotate(Clockwise):"; int rotAngle; cin>>rotAngle; rotation(rotAngle); char writeBmpName[] = "test_new.bmp"; writeBmp(writeBmpName); } int main() { work(); return 0; }