东南大学数字图像处理作业-C++原生实现(不调库)对BMP图像旋转和平移

1 代码

包含三个文件:把bmp.h、bmp.cpp、main.cpp
1.1 bmp.h

#pragma once
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;

//位图文件头定义
typedef struct  tagBITMAPFILEHEADER {
	//	WORD bfType;//单独读取,结构体中就不定义了
	DWORD bfSize;//文件大小
	WORD bfReserved1;//保留字
	WORD bfReserved2;//保留字
	DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数
}BITMAPFILEHEADER;

//位图信息头定义
typedef struct tagBITMAPINFOHEADER {
	DWORD biSize;//信息头大小
	DWORD biWidth;//图像宽度
	DWORD biHeight;//图像高度
	WORD biPlanes;//位平面数,必须为1
	WORD biBitCount;//每像素位数
	DWORD  biCompression; //压缩类型
	DWORD  biSizeImage; //压缩图像大小字节数
	DWORD  biXPelsPerMeter; //水平分辨率
	DWORD  biYPelsPerMeter; //垂直分辨率
	DWORD  biClrUsed; //位图实际用到的色彩数
	DWORD  biClrImportant; //本位图中重要的色彩数
}BITMAPINFOHEADER; //位图信息头定义

//彩色图像的像素信息
typedef struct tagRgbImgData
{
	BYTE blue;
	BYTE green;
	BYTE red;
}DATA;

// 灰度图像的像素信息
typedef struct tagGrayBmpData
{
	BYTE gray;
}GRAYDATA;

// 调色板的结构定义,灰度图有256个调色板
typedef struct tagRGBQUAD {
	BYTE rgbBlue;    // 蓝色的亮度(值范围为0-255) 
	BYTE rgbGreen;   // 绿色的亮度(值范围为0-255) 
	BYTE rgbRed;     // 红色的亮度(值范围为0-255) 
	BYTE rgbReserved;// 保留,必须为0 
} RGBQUAD;

double xAfterRot(int x, int y, double theta, int cx, int cy);
double yAfterRot(int x, int y, double theta, int cx, int cy);

// 检查图片类型是不是BMP
int checkImgType(const char* filename);
// 彩色BMP图像读取操作
DATA* readRgbBmp(const char* filename, WORD* bfType, BITMAPFILEHEADER* strHead, BITMAPINFOHEADER* strInfo, int* h, int* mw, int* imgSize, int* cx, int* cy);
// 灰色BMP图像读取操作
GRAYDATA* readGrayBmp(const char* filename, WORD* bfType, BITMAPFILEHEADER* strHead, BITMAPINFOHEADER* strInfo, RGBQUAD* ipRGB, int* h, int* mw, int* imgSize, int* cx, int* cy);
int modifyWidth(int biWidth);
int getImageSize(int biWidth, int biHeight, int bitCount);
DATA* scale(const DATA* src, float x, float y, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType);
GRAYDATA* scaleGray(const GRAYDATA* src, float x, float y, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType, RGBQUAD* ipRGB);


DATA* rotation(const DATA* src, double theta, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType);
GRAYDATA* rotationGray(const GRAYDATA* src, double theta, int mh, int mw,
	int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo,WORD bfType, RGBQUAD* ipRGB);

1. 2 bmp.cpp

#include <cstdio>
#include <iostream>
#include <vector>
#include<algorithm>
#include <cmath>
#define PI acos(-1)
#include <cstdlib>
#include<exception>
#include<set>
#include "bmp.h"
using namespace std;

int checkImgType(const char* filename) {
	FILE* fpi = fopen(filename, "rb");
	WORD bfType;
	if (fpi == NULL) {
		cout << filename << " 文件未能找到" << endl;
		return 0;
	}
	else {
		fread(&bfType, 1, sizeof(WORD), fpi);
		if (0x4d42 != bfType) {
			cout << "Error: The file is not a bmp image!" << endl;
			return 0;
		}
	}
	return 1;
}


int modifyWidth(int biWidth) {
	if (biWidth % 4 == 0)
		return biWidth;
	return (biWidth / 4 + 1) * 4;
}

int getImageSize(int biWidth, int biHeight, int bitCount) {
	int bytePerPixel = bitCount / 8;
	int LineBytes = (biWidth * bytePerPixel + 3) / 4 * 4; //这个其实也相当于是每行的宽度,但是这里的宽度指的是字节数,而不是像素数
	return LineBytes * biWidth;
}

DATA * readRgbBmp(const char* filename, WORD * bfType, BITMAPFILEHEADER* strHead, BITMAPINFOHEADER* strInfo, int* h, int* mw, int* imgSize, int * cx, int* cy) {
	FILE* fpi = fopen(filename, "rb");
	fread(bfType, 1, sizeof(WORD), fpi);
	fread(strHead, 1, sizeof(tagBITMAPFILEHEADER), fpi);
	fread(strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpi);
	*h = (*strInfo).biHeight;
	*mw = modifyWidth((*strInfo).biWidth);
	*imgSize = (*h) * (*mw);
	*cx = (*mw) / 2;
	*cy = (*h) / 2;
	DATA* imgData = new DATA[*imgSize];
	fread(imgData, 1, sizeof(DATA) * (*imgSize), fpi);
	return imgData;
}

GRAYDATA* readGrayBmp(const char* filename, WORD* bfType, BITMAPFILEHEADER* strHead, BITMAPINFOHEADER* strInfo, RGBQUAD* ipRGB, int* h, int* mw, int* imgSize, int* cx, int* cy) {
	FILE* fpi = fopen(filename, "rb");
	fread(bfType, 1, sizeof(WORD), fpi);
	fread(strHead, 1, sizeof(tagBITMAPFILEHEADER), fpi);
	fread(strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpi);
	fread(ipRGB, sizeof(RGBQUAD) * 256, 1, fpi);
	*h = (*strInfo).biHeight;
	*mw = modifyWidth( (*strInfo).biWidth );
	*imgSize = (*h) * (*mw);
	*imgSize = (*h) * (*mw);
	*cx = (*mw) / 2;
	*cy = (*h) / 2;
	//GRAYDATA* imgData = new GRAYDATA[*imgSize];
	GRAYDATA* imgData = (GRAYDATA*) malloc(sizeof(GRAYDATA) * (*imgSize));
	fread(imgData, 1, sizeof(GRAYDATA) * (*imgSize), fpi);
	return imgData;
}


DATA* scale(const DATA* src, float x, float y, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType) {
	float target_x, target_y;
	int int_target_x, int_target_y;
	DATA* target = new DATA[imgSize];
	int* needItr = new int[imgSize];
	memset(target, 0, sizeof(DATA) * imgSize);
	memset(needItr, 0, sizeof(int) * imgSize);

	for (int i = 0; i < mh; i++)
		for (int j = 0; j < mw; j++) {
			target_x = (j - cx) / x + cx;
			target_y = (i - cy) / y + cy;
			int_target_x = (int)target_x;
			int_target_y = (int)target_y;
			if (int_target_x - target_x < 0 || int_target_y - target_y < 0 || int_target_x <0 || int_target_x > mw || int_target_y < 0 || int_target_y > mh) {
				target[i * mw + j].red = 0;
				target[i * mw + j].green = 0;
				target[i * mw + j].blue = 0;
				needItr[i * mw + j] = 1;
			}
			else {
				try {
					target[i * mw + j].blue = src[int_target_y * mw + int_target_x].blue;
					target[i * mw + j].red = src[int_target_y * mw + int_target_x].red;
					target[i * mw + j].green = src[int_target_y * mw + int_target_x].green;
				}
				catch (...) {
					cout << "i: " << i << "j:" << j << endl;
				}
			}
		}

	cout << "Doing the interpolation, please wait.......(0\%)" << endl;

	for (int i = 0; i < mh; i++) {
		int last = -1;
		for (int j = 0; j < mw; j++) {
			// 这里应该是找到每一行的需要插值的点
			// last的值应该是每一行中需要插值的第一个点的前面一个点
			if (needItr[i * mw + j] == 0) {
				last = j;
				continue;
			}
			else {
				// 当找到一个需要插值的点的时候
				// 首先期望找到这个插值点右侧的不需要插值的第一个点

				int k = j;
				//find next position which has value
				while (k < mw && needItr[i * mw + k] == 1) {
					k++;
				}
				if (k >= mw) {			//in the last position of the line
					if (last == -1)
						break;
					target[i * mw + j] = target[i * mw + last];
				}
				else {
					if (last == -1) {		//in the first position of the line
						target[i * mw + j] = target[i * mw + k];
					}
					else {				//in the middle
						float coe = (j - last) * 1.0 / (k - last);
						target[i * mw + j].red = (BYTE)(((int)target[i * mw + k].red - (int)target[i * mw + last].red) * coe + (int)target[i * mw + last].red);
						target[i * mw + j].green = (BYTE)(((int)target[i * mw + k].green - (int)target[i * mw + last].green) * coe + (int)target[i * mw + last].green);
						target[i * mw + j].blue = (BYTE)(((int)target[i * mw + k].blue - (int)target[i * mw + last].blue) * coe + (int)target[i * mw + last].blue);
					}
				}
			}
			needItr[i * mw + j] = 0;
		}
	}

	cout << "Doing the interpolation, please wait.......(50\%)" << endl;
	//then do the vertical interpolation
	for (int i = 0; i < mw; i++) {
		int last = -1;
		for (int j = 0; j < mh; j++) {
			if (needItr[j * mw + i] == 0) {
				last = j;
				continue;
			}
			else {
				int k = j;
				//find next position which has value
				while (k < mh && needItr[k * mw + i] == 1) {
					k++;
				}
				if (k >= mh) {			//in the last position of the line
					if (last == -1)
						break;
					target[j * mw + i] = target[last * mw + i];
				}
				else {
					if (last == -1) {		//in the first position of the line
						target[j * mw + i] = target[k * mw + i];
					}
					else {				//in the middle
						float coe = (j - last) * 1.0 / (k - last);
						target[j * mw + i].red = (BYTE)(((int)target[k * mw + i].red - (int)target[last * mw + i].red) * coe + (int)target[last * mw + i].red);
						target[j * mw + i].green = (BYTE)(((int)target[k * mw + i].green - (int)target[last * mw + i].green) * coe + (int)target[last * mw + i].green);
						target[j * mw + i].blue = (BYTE)(((int)target[k * mw + i].blue - (int)target[last * mw + i].blue) * coe + (int)target[last * mw + i].blue);
					}
				}
			}
			needItr[j * mw + i] = 0;
		}
	}


	FILE* fpo1;
	fpo1 = fopen("scale.bmp", "wb");
	BITMAPFILEHEADER newHead = strHead;
	BITMAPINFOHEADER newInfo = strInfo;
	fwrite(&bfType, 1, sizeof(WORD), fpo1);
	fwrite(&newHead, 1, sizeof(tagBITMAPFILEHEADER), fpo1);
	fwrite(&newInfo, 1, sizeof(tagBITMAPINFOHEADER), fpo1);
	fwrite(target, 1, sizeof(DATA) * (imgSize), fpo1);
	fclose(fpo1);
	delete[] needItr;
	return target;
}


GRAYDATA*  scaleGray(const GRAYDATA* src, float x, float y, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType,  RGBQUAD* ipRGB) {
	float target_x, target_y;
	int int_target_x, int_target_y;
	GRAYDATA* target = new GRAYDATA[imgSize];
	int* needItr = new int[imgSize];
	memset(target, 0, sizeof(GRAYDATA) * imgSize);
	memset(needItr, 0, sizeof(int) * imgSize);

	for (int i = 0; i < mh; i++)
		for (int j = 0; j < mw; j++) {
			target_x = (j - cx) / x + cx;
			target_y = (i - cy) / y + cy;
			int_target_x = (int)target_x;
			int_target_y = (int)target_y;
			if (int_target_x - target_x < 0 || int_target_y - target_y < 0 || int_target_x <0 || int_target_x > mw || int_target_y < 0 || int_target_y > mh) {
				target[i * mw + j].gray = 0;
				needItr[i * mw + j] = 1;
			}
			else {
				//cout << "i: " << i << "j:" << j << endl;
				try {
					target[i * mw + j].gray = src[int_target_y * mw + int_target_x].gray;
				}
				catch (...) {
					//cout << "i: " << i << "j:" << j << endl;
				}
			}
		}

	cout << "Doing the interpolation, please wait.......(0\%)" << endl;

	for (int i = 0; i < mh; i++) {
		int last = -1;
		for (int j = 0; j < mw; j++) {
			// 这里应该是找到每一行的需要插值的点
			// last的值应该是每一行中需要插值的第一个点的前面一个点
			if (needItr[i * mw + j] == 0) {
				last = j;
				continue;
			}
			else {
				// 当找到一个需要插值的点的时候
				// 首先期望找到这个插值点右侧的不需要插值的第一个点

				int k = j;
				//find next position which has value
				while (k < mw && needItr[i * mw + k] == 1) {
					k++;
				}
				if (k >= mw) {			//in the last position of the line
					if (last == -1)
						break;
					target[i * mw + j] = target[i * mw + last];
				}
				else {
					if (last == -1) {		//in the first position of the line
						target[i * mw + j] = target[i * mw + k];
					}
					else {				//in the middle
						float coe = (j - last) * 1.0 / (k - last);
						target[i * mw + j].gray = (BYTE)(((int)target[i * mw + k].gray - (int)target[i * mw + last].gray) * coe + (int)target[i * mw + last].gray);

					}
				}
			}
			needItr[i * mw + j] = 0;
		}
	}


	cout << "Doing the interpolation, please wait.......(50\%)" << endl;
	//then do the vertical interpolation
	for (int i = 0; i < mw; i++) {
		int last = -1;
		for (int j = 0; j < mh; j++) {
			if (needItr[j * mw + i] == 0) {
				last = j;
				continue;
			}
			else {
				int k = j;
				//find next position which has value
				while (k < mh && needItr[k * mw + i] == 1) {
					k++;
				}
				if (k >= mh) {			//in the last position of the line
					if (last == -1)
						break;
					target[j * mw + i] = target[last * mw + i];
				}
				else {
					if (last == -1) {		//in the first position of the line
						target[j * mw + i] = target[k * mw + i];
					}
					else {				//in the middle
						float coe = (j - last) * 1.0 / (k - last);
						target[j * mw + i].gray = (BYTE)(((int)target[k * mw + i].gray - (int)target[last * mw + i].gray) * coe + (int)target[last * mw + i].gray);

					}
				}
			}
			needItr[j * mw + i] = 0;
		}
	}

	FILE* fpo1;
	fpo1 = fopen("scaleGray.bmp", "wb");
	BITMAPFILEHEADER newHead = strHead;
	BITMAPINFOHEADER newInfo = strInfo;
	newHead.bfReserved1 = newHead.bfReserved2 = 0;
	newHead.bfOffBits = sizeof(bfType) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
	newHead.bfSize = newHead.bfOffBits + imgSize;
	newInfo.biHeight = (DWORD)mh;
	newInfo.biWidth = (DWORD)mw;
	newInfo.biSizeImage = (DWORD)(imgSize);
	fwrite(&bfType, 1, sizeof(WORD), fpo1);
	fwrite(&newHead, 1, sizeof(tagBITMAPFILEHEADER), fpo1);
	fwrite(&newInfo, 1, sizeof(tagBITMAPINFOHEADER), fpo1);
	fwrite(ipRGB, sizeof(RGBQUAD), 256, fpo1);
	fwrite(target, 1, sizeof(GRAYDATA) * (imgSize), fpo1);
	fclose(fpo1);
	delete[] needItr;
	return target;
}



DATA * rotation(const DATA* src, double theta, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType) {
	float target_x = 0, target_y = 0;
	int int_target_x, int_target_y;

	DATA* target = new DATA[imgSize];
	int* needItr = new int[imgSize];
	int* noneedItr = new int[imgSize];

	memset(target, 0, sizeof(DATA) * imgSize);
	memset(needItr, 0, sizeof(int) * imgSize);
	memset(noneedItr, 0, sizeof(int) * imgSize);

	int count1 = 0;
	// 这里面越界的点很少啊
	for (int i = 0; i < mh; i++)
		for (int j = 0; j < mw; j++) {
			/*target_x, target_y = xyAfterRot(j - cx, i - cy, theta);
			target_x  += cx;
			target_y  += cy;*/
			target_x = (int)xAfterRot(j, i, theta, cx, cy);
			target_y = (int)yAfterRot(j, i, theta, cx, cy);
			int_target_x = (int)target_x;
			int_target_y = (int)target_y;

			//int_target_x - target_x < 0 || int_target_y - target_y < 0
			if (int_target_x <0 || int_target_x > mw || int_target_y < 0 || int_target_y > mh) {
				target[i * mw + j].red = 0;
				target[i * mw + j].green = 0;
				target[i * mw + j].blue = 0;
				needItr[i * mw + j] = 1;
				count1 += 1;
			}
			else {
				target[i * mw + j].blue = src[int_target_y * mw + int_target_x].blue;
				target[i * mw + j].red = src[int_target_y * mw + int_target_x].red;
				target[i * mw + j].green = src[int_target_y * mw + int_target_x].green;
				//cout << "here rotate "<<endl;
			}
		}

	cout << "count1" << float(count1) / (mh * mw) << endl;

	FILE* fpo1;
	fpo1 = fopen("rotation.bmp", "wb");
	BITMAPFILEHEADER newHead = strHead;
	BITMAPINFOHEADER newInfo = strInfo;
	fwrite(&bfType, 1, sizeof(WORD), fpo1);
	fwrite(&newHead, 1, sizeof(tagBITMAPFILEHEADER), fpo1);
	fwrite(&newInfo, 1, sizeof(tagBITMAPINFOHEADER), fpo1);
	fwrite(target, 1, sizeof(DATA) * (imgSize), fpo1);
	fclose(fpo1);
	delete[] needItr;
	return target;
}


GRAYDATA* rotationGray(const GRAYDATA* src, double theta, int mh, int mw, int imgSize, int cx, int cy, BITMAPFILEHEADER strHead, BITMAPINFOHEADER strInfo, WORD bfType, RGBQUAD* ipRGB) {
	float target_x = 0, target_y = 0;
	int int_target_x, int_target_y;

	GRAYDATA* target = new GRAYDATA[imgSize];
	int* needItr = new int[imgSize];
	int* noneedItr = new int[imgSize];

	memset(target, 0, sizeof(GRAYDATA) * imgSize);
	memset(needItr, 0, sizeof(int) * imgSize);
	memset(noneedItr, 0, sizeof(int) * imgSize);

	int count1 = 0;
	// 这里面越界的点很少啊
	for (int i = 0; i < mh; i++)
		for (int j = 0; j < mw; j++) {
			/*target_x, target_y = xyAfterRot(j - cx, i - cy, theta);
			target_x  += cx;
			target_y  += cy;*/
			target_x = (int)xAfterRot(j, i, theta, cx ,cy);
			target_y = (int)yAfterRot(j, i, theta, cx,  cy);
			int_target_x = (int)target_x;
			int_target_y = (int)target_y;

			//int_target_x - target_x < 0 || int_target_y - target_y < 0
			if (int_target_x <0 || int_target_x > mw || int_target_y < 0 || int_target_y > mh) {
				target[i * mw + j].gray = 0;
				needItr[i * mw + j] = 1;
				count1 += 1;
			}
			else {
				target[i * mw + j].gray = src[int_target_y * mw + int_target_x].gray;

				//cout << "here rotate "<<endl;
			}
		}

	cout << "count1" << float(count1) / (mh * mw) << endl;

	FILE* fpo1;
	fpo1 = fopen("rotationGray.bmp", "wb");
	BITMAPFILEHEADER newHead = strHead;
	BITMAPINFOHEADER newInfo = strInfo;
	newHead.bfReserved1 = newHead.bfReserved2 = 0;
	newHead.bfOffBits = sizeof(bfType) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
	newHead.bfSize = newHead.bfOffBits + imgSize;
	newInfo.biHeight = (DWORD)mh;
	newInfo.biWidth = (DWORD)mw;
	newInfo.biSizeImage = (DWORD)(imgSize);
	fwrite(&bfType, 1, sizeof(WORD), fpo1);
	fwrite(&newHead, 1, sizeof(tagBITMAPFILEHEADER), fpo1);
	fwrite(&newInfo, 1, sizeof(tagBITMAPINFOHEADER), fpo1);
	fwrite(ipRGB, sizeof(RGBQUAD), 256, fpo1);
	fwrite(target, 1, sizeof(GRAYDATA) * (imgSize), fpo1);
	fclose(fpo1);
	return target;
}



double xAfterRot(int x, int y, double theta, int cx, int cy) {
	x = x - cx;
	y = y - cy;
	double result = x * cos(theta) - y * sin(theta);
	//double result = x * cos(theta) + y * sin(theta);
	return result += cx;
}
double yAfterRot(int x, int y, double theta, int cx, int cy) {
	x = x - cx;
	y = y - cy;
	double result = x * sin(theta) + y * cos(theta);
	//double result = -x * sin(theta) + y * cos(theta);

	return result += cy;
}

1.3 main.cpp

#include "bmp.cpp"
using namespace std;


int main() {
	const char* filename1 = (char*)"D:\\TestEverything\\BmpCenteredManipuation\\Debug\\Coman.bmp"; //彩色图像
	const char* filename2 = (char*)"D:\\TestEverything\\BmpCenteredManipuation\\Debug\\barbara.bmp"; //灰度图像
	BITMAPFILEHEADER strHead1, strHead2;
	BITMAPINFOHEADER strInfo1, strInfo2;
	int h1, h2, mw1, mw2, imgSize1, imgSize2;
	DATA* imgData1, *imgData3;
	GRAYDATA* imgData2, *imgData4;
	WORD bfType1, bfType2;
	RGBQUAD* ipRGB = (RGBQUAD*)malloc(sizeof(RGBQUAD) * 256);
	int cx1, cx2, cy1, cy2;


	if (checkImgType(filename1)) {
		imgData1 = readRgbBmp(filename1, &bfType1, &strHead1, &strInfo1, &h1, &mw1, &imgSize1, &cx1, &cy1);
		float mulX, mulY;
		cout << "Scale, input the x coefficient (0.1<x<4.0): ";
		cin >> mulX;
		cout << "Scale, input the y coefficient (0.1<y<4.0): ";
		cin >> mulY;
		imgData3 = scale(imgData1, mulX, mulY, h1, mw1, imgSize1, cx1, cy1, strHead1, strInfo1, bfType1);

		double theta;
		cout << "Rotation, input the angle to be rotate (0 < theta < 360): ";
		cin >> theta;
		theta = theta / 180 * PI;
		rotation(imgData3, theta, h1, mw1, imgSize1, cx1, cy1, strHead1, strInfo1, bfType1);
	}
	if (checkImgType(filename2)) {
		imgData2 = readGrayBmp(filename2, &bfType2, &strHead2, &strInfo2, ipRGB, &h2, &mw2, &imgSize2, &cx2, &cy2);
		float mulX, mulY;
		cout << "Scale, input the x coefficient (0.1<x<4.0): ";
		cin >> mulX;
		cout << "Scale, input the y coefficient (0.1<y<4.0): ";
		cin >> mulY;
		imgData4 = scaleGray(imgData2, mulX, mulY, h2, mw2, imgSize2, cx2, cy2, strHead2, strInfo2, bfType2, ipRGB);

		const char* filename4 = (char*)"D:\TestEverything\BmpCenteredManipuation\BmpCenteredManipuation\scaleGray.bmp"; //彩色图像

		double theta;
		cout << "Rotation, input the angle to be rotate (0 < theta < 360): ";
		cin >> theta;
		theta = theta / 180 * PI;
		rotationGray(imgData4, theta, h2, mw2, imgSize2, cx2, cy2, strHead2, strInfo2, bfType2, ipRGB);

	}
	return 0;
}


2 实现效果

  1. 1 灰度图
    在这里插入图片描述

在这里插入图片描述
2.2 彩色图
在这里插入图片描述
在这里插入图片描述

3 实现难点

BMP的存储结构;转化时的矩阵变换操作

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值