图像旋转90度

#include 
#include 

//因为在 BITMAPFILEHEADER 结构体中 bfType 为2字节,为防止字节对齐为4字节,故强制使用2字节对齐。
//详情请搜索 内存对齐
#pragma pack (2)//C编译器将按照2个字节对齐		

typedef unsigned long       DWORD;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef long LONG;


typedef struct tagBITMAPFILEHEADER {
	WORD bfType; //必须为'BM'
	DWORD bfSize; //文件大小
	WORD bfReserved1; //必须为0
	WORD bfReserved2; //必须为0
	DWORD bfOffBits;//从ITMAPFILEHEADER到存放bmp数据的偏移量
}BITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
	DWORD biSize; //此结构的大小,可用sizeof(BITMAPINFOHEAER)得到
	LONG  biWidth; //位图宽度,以象素为单位
	LONG  biHeight; //位图高度,以象素为单位
	WORD  biPlanes; //必须为1
	WORD  biBitCount;//位图象素位数,可为0,1,4,8,24,32 
	DWORD biCompression;
	DWORD biSizeImage; //(仅用于压缩)
	LONG  biXPelsPerMeter; //一米横向象素数
	LONG  biYPelsPerMeter; //一米纵向象素数
	DWORD biClrUsed;// (非零用语短颜色表)
	DWORD biClrImportant;
}BITMAPINFOHEADER, *PBITMAPINFOHEADER;


void RoateBitmap(char *srcFileName, char *dstFileName);
void RoateData(LONG width, LONG height, unsigned char * srcData, unsigned char * dstData, int Bpp);


int main()
{
	printf("DWORD: %d,  BYTE: %d,  WORD: %d,  LONG: %d.\n", sizeof(DWORD),
		sizeof(BYTE), sizeof(WORD), sizeof(LONG));

	char *srcFileName = "0.bmp";
	char *dstFileName = "dst.bmp";
	RoateBitmap(srcFileName, dstFileName);
	return 0;
}

//把位图结构分为两部分, 位图数据域(真正保存位图像素信息的) 和 非数据域(保存位图结构信息)
void RoateBitmap(char *srcFileName, char *dstFileName)
{
	FILE* fp = NULL;
	DWORD fileLen, dataLen;
	int bmpHeight, bmpWidth, bmpBpp;
	if ((fp = fopen(srcFileName, "rb")) == NULL)
	{
		printf("can't open file");
		exit(-1);
	}
	printf("open file %s successed.\n", srcFileName);

	//获取文件长度
	fseek(fp, 0, SEEK_END);//fp指向文件尾0个字节处
	fileLen = ftell(fp);//fp当前位置相对于文件首的偏移字节数
	fseek(fp, 0, SEEK_SET);


	BITMAPFILEHEADER bfhHeader;//bmp文件头
	BITMAPINFOHEADER bmiHeader; //bmp格式头
	fread(&bfhHeader, sizeof(BITMAPFILEHEADER), 1, fp);
	if (bfhHeader.bfType != ((WORD)('M' << 8) | 'B'))	//判断是否是"BM"	
	{
		printf("the file is not a bitmap! exit...\n");
		exit(-1);
	}
	if (bfhHeader.bfSize != fileLen)
	{
		printf("fileLen = %ld,  headerInfo's length = %ld\n", fileLen, bfhHeader.bfSize);
		printf("the file length contained by the bitmap file head info is not correct! exit...\n");
		exit(-1);
	}

	fread(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
	bmpHeight = bmiHeader.biHeight;		//得到高度和宽度
	bmpWidth = bmiHeader.biWidth;
	bmpBpp = bmiHeader.biBitCount;		//得到每个像素占用多少字节
	dataLen = bmiHeader.biSizeImage;	//得到位图数据域长度	
	unsigned char* srcBmpData = (unsigned char *)malloc(dataLen);		//位图数据域
	unsigned char* fileHead = (unsigned char *)malloc(bfhHeader.bfOffBits);		//非位图数据域信息
	fseek(fp, 0, SEEK_SET);
	fread(fileHead, bfhHeader.bfOffBits, 1, fp);	//读取非数据域的信息 
	fread(srcBmpData, dataLen, 1, fp);	//读取图像数据 	
	fclose(fp);
	printf("complete read data from %s, close it.\n", srcFileName);

	//交换位图的宽高 
	unsigned char* tmp;
	tmp = fileHead;
	tmp += 0x12;	//是十六进制的0x12
	*((LONG*)tmp) = bmpHeight;
	tmp += 4;
	*((LONG*)tmp) = bmpWidth;

	unsigned char * dstBmpData = (unsigned char *)malloc(dataLen);		//保存旋转后的位图数据

	printf("beginning roate bitmap.\n");
	RoateData(bmpWidth, bmpHeight, srcBmpData, dstBmpData, bmpBpp / 8);
	printf("completed roate bitmap.\n");

	printf("begining write roated data to file(%s)\n", dstFileName);
	if ((fp = fopen(dstFileName, "wb")) == NULL)
	{
		printf("can't open file");
		exit(-1);
	}
	fwrite(fileHead, bfhHeader.bfOffBits, 1, fp);
	fwrite(dstBmpData, dataLen, 1, fp);
	fclose(fp);
	printf("write data successed!\n");

	free(srcBmpData);
	free(fileHead);
	free(dstBmpData);
	return;

}

void RoateData(LONG width, LONG height, unsigned char * srcData, unsigned char * dstData, int Bpp)
{
	//Bpp  byte per pixel
	printf("current roating bitmap's byte per pixel is %d\n", Bpp);
	int i, j;
	int k;
	unsigned char *tmpSrc = srcData;
	unsigned char *tmpDst = dstData;

	width *= Bpp;		//每像素占三字节
	/*
	
	假如bmp格式src图像为2*2大小,内存中的存储顺序和逆转90度之后的存储顺序为:
	2    3                         3     1
	             ------>        
	0    1                         2     0
	注:bmp格式的图像在内存中的存储顺序为:从下至上,从左至右

	*/
	for (i = 0; i < width; i += Bpp)
	{
		for (j = height - 1; j >= 0; j--)
		{
			for (k = 0; k < Bpp; k++)
			{
				*tmpDst = *(tmpSrc + j * width + i + k);
				tmpDst++;
			}
		}
	}
}


你可能感兴趣的:(编程基础)