您的位置:首页 > 其它

镜像, 转置, 锐化, 灰度,旋转

2016-08-08 15:41 141 查看
/**
* 函数名: 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: