1. 程式人生 > >C語言實現BMP影象旋轉(任意角度)

C語言實現BMP影象旋轉(任意角度)

實現對對任意角度的旋轉,具體數學推導網上找。如果各位讀者需要使用,只需要將開啟檔案的位置改為你的位置,輸入不同的角度即可:


#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define CV_PI 3.1415926

int main(){
	FILE *fp = fopen("./01.bmp", "rb");
	if (fp == 0){
		printf("檔案開啟失敗\n");
		return 0;
	}

	BITMAPFILEHEADER fileHead;
	BITMAPINFOHEADER infoHead;
	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);

	int width = infoHead.biWidth;
	int height = infoHead.biHeight;
	int biCount = infoHead.biBitCount;
	int lineByte = (width*biCount / 8 + 3) / 4 * 4;

	RGBQUAD *pColorTable;

	pColorTable = new RGBQUAD[256];
	fread(pColorTable, sizeof(RGBQUAD), 256, fp);

	unsigned char *pBmpBufSrc,*pBmpBufDst;
	pBmpBufSrc = new unsigned char[lineByte*height];
	fread(pBmpBufSrc, lineByte*height, 1, fp);
	fclose(fp);

	double angle;
	printf("請輸入需要旋轉的角度:  ");
	scanf("%lf", &angle);

	double sita = angle*CV_PI / 180;
	double a = (width - 1) / 2;
	double b = (height - 1) / 2;

	double x1 = -a*cos(sita) - b*sin(sita);
	double y1 = -a*sin(sita) + b*cos(sita);

	double x2 = a*cos(sita) - b*sin(sita);
	double y2 = a*sin(sita) + b*cos(sita);

	double x3 = a*cos(sita) + b*sin(sita);
	double y3 = a*sin(sita) - b*cos(sita);

	double x4 = -a*cos(sita) + b*sin(sita);
	double y4 = -a*sin(sita) - b*cos(sita);

	int w1 = round(fmax(abs(x1 - x3), abs(x2 - x4)));
	int h1 = round(fmax(abs(y1 - y3), abs(y2 - y4)));

	double c = (w1 - 1) / 2;
	double d = (h1 - 1) / 2;

	double f1 = -c*cos(sita) + d*sin(sita) + a;
	double f2 = -c*sin(sita) - d*cos(sita) + b;

	int lineByte1 = (w1*biCount / 8 + 3) / 4 * 4;
	pBmpBufDst = new unsigned char[lineByte1*h1];

	for (int i = 0; i < h1; ++i){
		for (int j = 0; j < w1; ++j){
			unsigned char *p;
			p = (unsigned char *)(pBmpBufDst + i*lineByte1 + j);
			(*p) = 255;
		}
	}


	for (int i = 0; i < h1; ++i){
		for (int j = 0; j < w1; ++j){
			int x = round(j*cos(sita) - i*sin(sita) + f1);
			int y = round(j*sin(sita) + i*cos(sita) + f2);
			if (x>0 && x<width && y>0 && y < height){
				unsigned char *p1, *p2;
				p1 = (unsigned char *)(pBmpBufDst + i*lineByte1 + j); // 新影象
				p2 = (unsigned char *)(pBmpBufSrc + y*lineByte + x);  // 原影象
				(*p1) = (*p2);
			}
		}
		continue;
	}

	char *DstName = "rotate.bmp";
	FILE *fpo = fopen(DstName, "wb");
	if (fpo == 0)
		return 0;
	int colorTableSize = 0;
	if (biCount == 8)
		colorTableSize = 1024;
	BITMAPFILEHEADER dstFileHead;
	dstFileHead.bfOffBits = 14 + 40 + colorTableSize;
	dstFileHead.bfReserved1 = 0;
	dstFileHead.bfReserved2 = 0;
	dstFileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize + lineByte1*h1;
	dstFileHead.bfType = 0x4D42;
	fwrite(&dstFileHead, sizeof(dstFileHead), 1, fpo);
	
	BITMAPINFOHEADER dstInfoHead;
	dstInfoHead.biBitCount = biCount;
	dstInfoHead.biClrImportant = 0;
	dstInfoHead.biClrUsed = 0;
	dstInfoHead.biCompression = 0;
	dstInfoHead.biHeight = h1;
	dstInfoHead.biPlanes = 1;
	dstInfoHead.biSize = 40;
	dstInfoHead.biSizeImage = lineByte1*h1;
	dstInfoHead.biWidth = w1;
	dstInfoHead.biXPelsPerMeter = 0;
	dstInfoHead.biYPelsPerMeter = 0;
	fwrite(&dstInfoHead, sizeof(BITMAPINFOHEADER), 1, fpo);
	
	fwrite(pColorTable, sizeof(RGBQUAD), 256, fpo);
	fwrite(pBmpBufDst, lineByte1*h1, 1, fpo);
	fclose(fpo);

	system("pause");
	return 1;
}

 

        原圖                             右旋轉30度                                      右旋轉45                                 右旋轉60度                           右旋轉90度