图像的几何变换
#include"bmp.h"#include测试#include #include #include using namespace std;void Bitmap::translation(int offsetX, int offsetY)//平移变换{if (dataBuf == NULL)cout << "请确保已经读入图像数据!" << endl;int w, h;//长宽的循环变量int k;//像素通道的循环变量int pixelByte = bitCount / 8;//每像素的字节数int lineByte = (width_p*bitCount / 8 + 3) / 4 * 4;//每行像素的字节数unsigned char* transBuf = new unsigned char[height_p*lineByte];//分配数据存储空间memset(transBuf, 0, height_p*lineByte);//置为黑色//平移运算for (h = 0; h < height_p; h++){for (w = 0; w < width_p; w++){//输出的点在输入的点范围内if (h - offsetY >= 0 && h - offsetY <= height_p&&w - offsetX >= 0 && w - offsetX <= width_p){for (k = 0; k < pixelByte; k++){*(transBuf + h*lineByte + w*pixelByte + k)= *(dataBuf + (h - offsetY)*lineByte + (w - offsetX)*pixelByte + k);}}}}delete[] dataBuf;dataBuf = transBuf;//释放原数据内存,指向变换后的图像数据cout << "平移成功!" << endl;}void Bitmap::zoom(float ratioX, float ratioY, char interpolationWay = 'n')//缩放变换{switch (interpolationWay){case 'n':neighborInterpolation(ratioX, ratioX);break;case 'l':dbLinearInterpolatin(ratioX, ratioY);break;case 'c':cubicConvoInterpolatin(ratioX, ratioY);break;default:break;}}void Bitmap::neighborInterpolation(float ratioX, float ratioY){int pixelByte = bitCount / 8;//每像素字节数int widthOut = int(ratioX*width_p);//输出图像宽度和高度int heightOut = int(ratioY*height_p);int lineByte = (width_p*bitCount / 8 + 3) / 4 * 4;//原图像每行像素的字节数int lineByteOut = (widthOut*bitCount / 8 + 3) / 4 * 4;//变换后图像每行像素的字节数unsigned char* transBuf = new unsigned char[lineByteOut*heightOut];memset(transBuf, 0, lineByteOut*heightOut);int w, h;int k;//输出图像对应在输入图像中待插值的位置坐标int coordinateX, coordinateY;for (h = 0; h < heightOut; h++){for (w = 0; w < widthOut; w++){//输出图像(w,h)处像素映射到原图像中的坐标值,即插值坐标coordinateX = int(w / ratioX + 0.5);coordinateY = int(h / ratioY + 0.5);//若插值位置在输入图像范围内,则近邻插值if (coordinateX >= 0 && coordinateX <= width_p&&coordinateY >= 0 && coordinateY <= height_p){for (k = 0; k < pixelByte; k++){*(transBuf + h*lineByteOut + w*pixelByte + k)= *(dataBuf + coordinateY*lineByte + coordinateX*pixelByte + k);}}}}delete[] dataBuf;dataBuf = transBuf;}void Bitmap::dbLinearInterpolatin(float ratioX, float ratioY){int pixelByte = bitCount / 8;//每像素字节数int widthOut = int(ratioX*width_p);//输出图像宽度和高度int heightOut = int(ratioY*height_p);int lineByte = (width_p*bitCount / 8 + 3) / 4 * 4;//原图像每行像素的字节数int lineByteOut = (widthOut*bitCount / 8 + 3) / 4 * 4;//变换后图像每行像素的字节数unsigned char* transBuf = new unsigned char[lineByteOut*heightOut];int w, h;int k;//输出图像对应在输入图像中待插值的位置坐标float coordinateX, coordinateY;//临时变量,待插值位置向下取整的坐标int Iu, Iv;//数组,存放插值位置周围的4个像素unsigned char array[2][2];//双线性插值for (h = 0; h< heightOut; h++){for (w = 0; w< widthOut; w++){//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置coordinateX = w / ratioX;coordinateY = h / ratioY;//对插值位置坐标取整Iu = (int)coordinateX;Iv = (int)coordinateY;//若插值位置在输入图像范围内,则双线性插值if (0 <= coordinateX&&coordinateX = 0 && coordinateY 255)t = 255;//调用双线性插值函数插值并输出到transBuf中*(transBuf + h * lineByteOut + w*pixelByte + k) = t;}}else{//边缘像素采用近邻插值for (k = 0; k = 1 && coordinateY = 0 && t<1)col[i] = pow(t, 3) - 2 * pow(t, 2) + 1;else if (t >= 1 && t<2)col[i] = -pow(t, 3) + 5 * pow(t, 2) - 8 * t + 4;elsecol[i] = 0;}//对垂直方向系数数组进行计算for (i = 0; i<4; i++){t = fabs(row[i]);if (t >= 0 && t<1)row[i] = pow(t, 3) - 2 * pow(t, 2) + 1;else if (t >= 1 && t<2)row[i] = -pow(t, 3) + 5 * pow(t, 2) - 8 * t + 4;elserow[i] = 0;}//将计算好的系数与对应图像数据数组作卷积float tempArray[4], temp;//先x方向卷积for (i = 0; i<4; i++)tempArray[i] = row[0] * array[0][i] + row[1] * array[1][i] + row[2] * array[2][i] + row[3] * array[3][i];//再y方向卷积temp = 0;for (i = 0; i<4; i++)temp += tempArray[i] * col[i];//将插值结果在图像灰度级范围内输出if (temp>255)temp = 255;if (temp<0)temp = 0;//调用立方卷积插值函数插值并输出到transBuf中*(transBuf + h * lineByteOut + w*pixelByte + k) = (unsigned char)temp;}}else{//边缘像素采用近邻插值for (k = 0; k = 0) && (coordinateX <= width_p) && (coordinateY >= 0)&& (coordinateY <=height_p)){//将图像每个通道的数据进行分别插值,彩色图像pixelByte为3,//灰度图像pixelByte为1for (k = 0; k
#include"bmp.h"#includeusing namespace std;int main(){ char* fileName = "qianxun.bmp"; Bitmap* bmp = new Bitmap(); bmp->read(fileName); bmp->translation(10, 10); //bmp->zoom(2, 2, 'n');//'n','l','c';默认为'n'邻近插值缩放 //bmp->rotate(90); bmp->write("translation.bmp"); delete bmp; return 1;}