BMP图像格式

文件参照:http://blog.csdn.net/o_sun_o/article/details/8351037


代码:

.h 文件:  BmpRot.h

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

//位图文件头定义;
//其中不包含文件类型信息(由于结构体的内存结构决定,
//要是加了的话将不能正确读取文件信息)
typedef struct  tagBITMAPFILEHEADER{
	//WORD bfType;//文件类型,必须是0x424D,即字符“BM”
	DWORD bfSize;//文件大小
	WORD bfReserved1;//保留字
	WORD bfReserved2;//保留字
	DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数
}BITMAPFILEHEADER;

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

typedef struct tagRGBQUAD{
	BYTE rgbBlue; //该颜色的蓝色分量
	BYTE rgbGreen; //该颜色的绿色分量
	BYTE rgbRed; //该颜色的红色分量
	BYTE rgbReserved; //保留值
}RGBQUAD;//调色板定义

//像素信息
typedef struct tagIMAGEDATA
{
	BYTE blue;
	BYTE green;
	BYTE red;
}IMAGEDATA;


.cpp文件:BmpRot.cpp

#include <stdio.h>
#include "BmpRot.h"
#include "stdlib.h"
#include "math.h"
#include "iostream"

#define PI 3.14159//圆周率宏定义
#define LENGTH_NAME_BMP 30//bmp图片文件名的最大长度

using namespace std;

//变量定义
BITMAPFILEHEADER strHead;
RGBQUAD strPla[256];//256色调色板
BITMAPINFOHEADER strInfo;


//显示位图文件头信息
void showBmpHead(BITMAPFILEHEADER pBmpHead){
	cout << "位图文件头:" << endl;
	cout << "文件大小:" << pBmpHead.bfSize << endl;
	cout << "保留字_1:" << pBmpHead.bfReserved1 << endl;
	cout << "保留字_2:" << pBmpHead.bfReserved2 << endl;
	cout << "实际位图数据的偏移字节数:" << pBmpHead.bfOffBits << endl << endl;
}

void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead){
	cout << "位图信息头:" << endl;
	cout << "结构体的长度:" << pBmpInforHead.biSize << endl;
	cout << "位图宽:" << pBmpInforHead.biWidth << endl;
	cout << "位图高:" << pBmpInforHead.biHeight << endl;
	cout << "biPlanes平面数:" << pBmpInforHead.biPlanes << endl;
	cout << "biBitCount采用颜色位数:" << pBmpInforHead.biBitCount << endl;
	cout << "压缩方式:" << pBmpInforHead.biCompression << endl;
	cout << "biSizeImage实际位图数据占用的字节数:" << pBmpInforHead.biSizeImage << endl;
	cout << "X方向分辨率:" << pBmpInforHead.biXPelsPerMeter << endl;
	cout << "Y方向分辨率:" << pBmpInforHead.biYPelsPerMeter << endl;
	cout << "使用的颜色数:" << pBmpInforHead.biClrUsed << endl;
	cout << "重要颜色数:" << pBmpInforHead.biClrImportant << endl;
}


int main(){
	char strFile[LENGTH_NAME_BMP];//bmp文件名
	IMAGEDATA *imagedata = NULL;//动态分配存储原图片的像素信息的二维数组
	IMAGEDATA *imagedataRot = NULL;//动态分配存储旋转后的图片的像素信息的二维数组
	int width, height;//图片的宽度和高度

	const char *txtname = "C://Users//Administrator//Desktop//ConsoleApplication2//HS1P-2013-07-24-15-30.txt";

	//cout << "请输入所要读取的文件名:" << endl;
	//cin >> strFile;
	FILE *fpi, *fpw;
	//fpi = fopen(strFile, "rb");
	fpi = fopen("10.bmp", "rb");
	if (fpi != NULL){
		//先读取文件类型
		WORD bfType;
		fread(&bfType, 1, sizeof(WORD), fpi);
		if (0x4d42 != bfType)
		{
			cout << "the file is not a bmp file!" << endl;
			return NULL;
		}
		//读取bmp文件的文件头和信息头
		fread(&strHead, 1, sizeof(tagBITMAPFILEHEADER), fpi);
		showBmpHead(strHead);//显示文件头
		fread(&strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpi);
		showBmpInforHead(strInfo);//显示文件信息头

		unsigned char *bmpData = new unsigned char[strInfo.biHeight*strInfo.biWidth * 3];
		fseek(fpi, strHead.bfOffBits, SEEK_SET);
		fread(bmpData, 1, strInfo.biHeight*strInfo.biWidth * 3, fpi);
		FILE *temp;
		if ((temp = fopen(txtname, "wb")) == NULL)//写TXT文件
		{
			cout << "the file can not be built!" << endl;
			exit(1);
		}


		for (int i = 0; i<strInfo.biHeight; i++)
		{
			for (int j = 0; j<strInfo.biWidth; j++)
			{
				fprintf(temp, "%d ", bmpData[i*strInfo.biWidth * 3 + j * 3]);
				fprintf(temp, "%d ", bmpData[i*strInfo.biWidth * 3 + j * 3 + 1]);
				fprintf(temp, "%d \n", bmpData[i*strInfo.biWidth * 3 + j * 3 + 2]);

				//fprintf(temp,"%d ",bmpData[i*bmpInfHeader.biWidth + j]);//黑白图像
			}
			fprintf(temp, "\n");
		}


		//读取调色板
		for (unsigned int nCounti = 0; nCounti<strInfo.biClrUsed; nCounti++)
		{
			//存储的时候,一般去掉保留字rgbReserved
			fread((char *)&strPla[nCounti].rgbBlue, 1, sizeof(BYTE), fpi);
			fread((char *)&strPla[nCounti].rgbGreen, 1, sizeof(BYTE), fpi);
			fread((char *)&strPla[nCounti].rgbRed, 1, sizeof(BYTE), fpi);
			cout << "strPla[nCounti].rgbBlue" << strPla[nCounti].rgbBlue << endl;
			cout << "strPla[nCounti].rgbGreen" << strPla[nCounti].rgbGreen << endl;
			cout << "strPla[nCounti].rgbRed" << strPla[nCounti].rgbRed << endl;
		}

		width = strInfo.biWidth;
		height = strInfo.biHeight;
		imagedata = (IMAGEDATA*)malloc(width * height * sizeof(IMAGEDATA));
		imagedataRot = (IMAGEDATA*)malloc(2 * width * 2 * height * sizeof(IMAGEDATA));

		for (int i = 0; i < height; ++i)
		{
			for (int j = 0; j < width; ++j)
			{
				(*(imagedata + i * width + j)).blue = 0;
				(*(imagedata + i * width + j)).green = 0;
				(*(imagedata + i *  width + j)).red = 0;
			}
		}

	
		//初始化旋转后图片的像素数组
		for (int i = 0; i < 2 * height; ++i)
		{
			for (int j = 0; j < 2 * width; ++j)
			{
				cout << (*(imagedataRot + i * 2 * width + j)).blue << endl;
				(*(imagedataRot + i * 2 * width + j)).blue = 0;
				(*(imagedataRot + i * 2 * width + j)).green = 0;
				(*(imagedataRot + i * 2 * width + j)).red = 0;
			}
		}
          //fseek(fpi,54,SEEK_SET);
		//读出图片的像素数据
		fread(imagedata, sizeof(struct tagIMAGEDATA) * width, height, fpi);
		/*
		for(int i = 0;i < height;++i)
		{
		fread(imagedata + i * width * sizeof(IMAGEDATA),sizeof(struct tagIMAGEDATA) * width,height,fpi);
		}*/
		fclose(fpi);
	}
	else
	{
		cout << "file open error!" << endl;
		return NULL;
	}

	//图片旋转处理
	int RotateAngle;//要旋转的角度数
	double angle;//要旋转的弧度数
	int midX_pre, midY_pre, midX_aft, midY_aft;//旋转所围绕的中心点的坐标
	midX_pre = width / 2;
	midY_pre = height / 2;
	midX_aft = width;
	midY_aft = height;
	int pre_i, pre_j, after_i, after_j;//旋转前后对应的像素点坐标
	cout << "输入要旋转的角度(0度到360度,逆时针旋转):" << endl;
	cin >> RotateAngle;
	angle = 1.0 * RotateAngle * PI / 180;
	for (int i = 0; i < 2 * height; ++i)
	{
		for (int j = 0; j < 2 * width; ++j)
		{
			after_i = i - midY_aft;//坐标变换
			after_j = j - midX_aft;
			pre_i = (int)(cos((double)angle) * after_i - sin((double)angle) * after_j) + midY_pre;
			pre_j = (int)(sin((double)angle) * after_i + cos((double)angle) * after_j) + midX_pre;
			if (pre_i >= 0 && pre_i < height && pre_j >= 0 && pre_j < width)//在原图范围内
				*(imagedataRot + i * 2 * width + j) = *(imagedata + pre_i * width + pre_j);
		}
	}

	//保存bmp图片
	if ((fpw = fopen("b.bmp", "wb")) == NULL)
	{
		cout << "create the bmp file error!" << endl;
		return NULL;
	}
	WORD bfType_w = 0x4d42;
	fwrite(&bfType_w, 1, sizeof(WORD), fpw);
	//fpw +=2;
	fwrite(&strHead, 1, sizeof(tagBITMAPFILEHEADER), fpw);
	strInfo.biWidth = 2 * width;
	strInfo.biHeight = 2 * height;
	fwrite(&strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpw);
	//保存调色板数据
	for (unsigned int nCounti = 0; nCounti<strInfo.biClrUsed; nCounti++)
	{
		fwrite(&strPla[nCounti].rgbBlue, 1, sizeof(BYTE), fpw);
		fwrite(&strPla[nCounti].rgbGreen, 1, sizeof(BYTE), fpw);
		fwrite(&strPla[nCounti].rgbRed, 1, sizeof(BYTE), fpw);
	}
	//保存像素数据
	for (int i = 0; i < 2 * height; ++i)
	{
		for (int j = 0; j < 2 * width; ++j)
		{
			fwrite(&(*(imagedataRot + i * 2 * width + j)).red, 1, sizeof(BYTE), fpw);//注意三条语句的顺序:否则颜色会发生变化
			fwrite(&(*(imagedataRot + i * 2 * width + j)).green, 1, sizeof(BYTE), fpw);
			fwrite(&(*(imagedataRot + i * 2 * width + j)).blue, 1, sizeof(BYTE), fpw);
		}
	}
	fclose(fpw);

	//释放内存
	delete[] imagedata;
	delete[] imagedataRot;
}



如果出现错误:

 warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

 

解决方法:
右击工程 - 属性 - 配置属性 - C/C++  -预处理器-预处理器定义

 

命令行增加 _CRT_SECURE_NO_WARNINGS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值