灰度图转bmp文件 C++

直接上代码,根据不同需求可以进行改动


#include <stdio.h>
#include <iostream>

using namespace std;



/
//读写图像文件的结构和函数的定义
/
// 文件头信息, 14 字节
struct sBMPFileHeader
{
	unsigned short usImageType;//位图文件的类型,必须为BM(1-2字节)
	unsigned short ulFsize1,ulFsize2;//位图文件的大小,以字节为单位(3-6字节,低位在前)
	unsigned short usReserved1;//位图文件保留字,必须为0(7-8字节)
	unsigned short usReserved2;//位图文件保留字,必须为0(9-10字节)
	unsigned short ulBMPDateOffset1,ulBMPDateOffset2;//位图数据的起始位置,以相对于位图(11-14字节,低位在前)
    //文件头的偏移量表示,以字节为单位
#ifdef _WIN32
};
#else
}__attribute__((packed));
#endif

// BMP信息头,40个字节 
struct sBMPInfoHeader
{
	unsigned int	biSize;       //本结构所占用字节数(15-18字节)
	int			biWidth;    //位图的宽度,以像素为单位(19-22字节)
	int			biHeight;   //位图的高度,以像素为单位(23-26字节)
	unsigned short  biPlanes;   //目标设备的级别,必须为1(27-28字节)
	unsigned short  biBitCount;   //每个像素所需的位数,必须是1(双色),(29-30字节) 4(16色),8(256色)16(高彩色)或24(真彩色)之一
	unsigned int	biCompression; //位图压缩类型,必须是0(不压缩),(31-34字节) 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
	unsigned int	biSizeImage; //位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
	int			biXPelsPerMeter; //位图水平分辨率,每米像素数(39-42字节)
	int			biYPelsPerMeter; //位图垂直分辨率,每米像素数(43-46字节)
	unsigned int	biClrUsed; //位图实际使用的颜色表中的颜色数(47-50字节)
	unsigned int	biClrImportant; //位图显示过程中重要的颜色数(51-54字节)
#ifdef _WIN32
};
#else
}__attribute__((packed));
#endif

//颜色表
struct sBMPColorQuad
{
	unsigned char    rgbBlue;   //蓝色的亮度(值范围为0-255)
	unsigned char    rgbGreen;   //绿色的亮度(值范围为0-255)
	unsigned char    rgbRed; //红色的亮度(值范围为0-255)
	unsigned char    rgbReserved;//保留,必须为0
#ifdef _WIN32
};
#else
}__attribute__((packed));
#endif

struct sBMPData
{
	unsigned int width, height;
	unsigned int lBitNum;
#ifdef _WIN32
	unsigned char *data = NULL;
#else
	unsigned char *data;
#endif	
};

int SaveImage(const char *pcFileName, unsigned char *pucImage, int iWidth, int iHeight)
{
	char pcTMP[255];
#ifdef _WIN32
	sprintf(pcTMP, "d:\\%s", pcFileName);
#else
	sprintf(pcTMP, "%s", pcFileName);
#endif

	FILE *bmp_file;
    //打开文件
	if (!(bmp_file = fopen(pcTMP, "wb")))
		return 1;

	int i;
	int iWidthNew_1 = iWidth;
	if ((iWidth % 4) != 0)
		iWidthNew_1 = (iWidth >> 2) << 2;
	int iCut_1 = iWidth - iWidthNew_1;
	unsigned char *pucTTTTT = new unsigned char[iWidthNew_1 * iHeight];

	unsigned char* pucOld = pucImage, *pucNew = pucTTTTT + iWidthNew_1 * (iHeight - 1);
	for (i = 0; i<iHeight; i++, pucOld += iWidth, pucNew -= iWidthNew_1)	//将图像裁剪并在y方向翻转
		memcpy(pucNew, pucOld, iWidthNew_1);

	sBMPData sbmpData;
	sbmpData.width = iWidthNew_1;
	sbmpData.height = iHeight;
	sbmpData.lBitNum = 8;
	sbmpData.data = pucTTTTT;

	struct sBMPFileHeader	bmp_file_header;
	struct sBMPInfoHeader	bmp_info_header;
	struct sBMPColorQuad	bmp_color_quad[256];

	if (sbmpData.lBitNum == 8)
	{
		bmp_file_header.usImageType = 0x4D42;//位图文件的类型,必须为BM(1-2字节)
		bmp_file_header.ulFsize1 = (unsigned short)(sbmpData.width*sbmpData.height + 0x0436);//位图文件的大小,以字节为单位(3-4字节,低位在前)
		bmp_file_header.ulFsize2 = (unsigned short)((sbmpData.width*sbmpData.height + 0x0436) >> 16);//位图文件的大小,以字节为单位(5-6字节,高位在后)
		bmp_file_header.ulBMPDateOffset1 = 0x0436;   //位图数据的起始位置,以相对于位图(11-12字节,低位在前)
		bmp_file_header.ulBMPDateOffset2 = 0x00;     //位图数据的起始位置,以相对于位图(13-14字节,高位在后)

		bmp_info_header.biSize = 0x28;    //本结构所占用字节数(15-18字节)
		bmp_info_header.biWidth = sbmpData.width; //位图的宽度,以像素为单位(19-22字节)
		bmp_info_header.biHeight = sbmpData.height; //位图的高度,以像素为单位(23-26字节)
		bmp_info_header.biPlanes = 1;  //目标设备的级别,必须为1(27-28字节)
		bmp_info_header.biBitCount = 8;//每个像素所需的位数,必须是1(双色),(29-30字节)
		bmp_info_header.biCompression = 0; //0x00 位图压缩类型,必须是0(不压缩)
		bmp_info_header.biSizeImage = 0x00;//位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
		bmp_info_header.biXPelsPerMeter = 0x0b40;//位图水平分辨率,每米像素数(39-42字节)
		bmp_info_header.biYPelsPerMeter = 0x0b40;//位图垂直分辨率,每米像素数(43-46字节)
		bmp_info_header.biClrUsed = 0x0100;//位图实际使用的颜色表中的颜色数(47-50字节)
		bmp_info_header.biClrImportant = 0;//位图显示过程中重要的颜色数(51-54字节)
		for (i = 0; i<256; i++)
		{
			bmp_color_quad[i].rgbBlue = (unsigned char)i;//蓝色的亮度(值范围为0-255)
			bmp_color_quad[i].rgbGreen = (unsigned char)i;//绿色的亮度(值范围为0-255)
			bmp_color_quad[i].rgbRed = (unsigned char)i; //红色的亮度(值范围为0-255)
			bmp_color_quad[i].rgbReserved = 0;//保留,必须为0
		}
	}
	else if (sbmpData.lBitNum == 24)
	{
		bmp_file_header.usImageType = 0x4D42;
		bmp_file_header.ulFsize1 = (unsigned short)(sbmpData.width*sbmpData.height * 3 + 0x0036);
		bmp_file_header.ulFsize2 = (unsigned short)((sbmpData.width*sbmpData.height * 3 + 0x0036) >> 16);
		bmp_file_header.ulBMPDateOffset1 = 0x0036;
		bmp_file_header.ulBMPDateOffset2 = 0x00;

		bmp_info_header.biSize = 0x28;
		bmp_info_header.biWidth = sbmpData.width;
		bmp_info_header.biHeight = sbmpData.height;
		bmp_info_header.biPlanes = 1;
		bmp_info_header.biBitCount = 24;
		bmp_info_header.biCompression = 0; //0x00
		bmp_info_header.biSizeImage = 0x00;
		bmp_info_header.biXPelsPerMeter = 0x0b40;
		bmp_info_header.biYPelsPerMeter = 0x0b40;
		bmp_info_header.biClrUsed = 0x0000;
		bmp_info_header.biClrImportant = 0;
	}
	else if (sbmpData.lBitNum == 16)
	{
		bmp_file_header.usImageType = 0x4D42;
		bmp_file_header.ulFsize1 = (unsigned short)(sbmpData.width*sbmpData.height * 2 + 0x0036);
		bmp_file_header.ulFsize2 = (unsigned short)((sbmpData.width*sbmpData.height * 2 + 0x0036) >> 16);
		bmp_file_header.ulBMPDateOffset1 = 0x0036;
		bmp_file_header.ulBMPDateOffset2 = 0x00;

		bmp_info_header.biSize = 0x28;
		bmp_info_header.biWidth = sbmpData.width;
		bmp_info_header.biHeight = sbmpData.height;
		bmp_info_header.biPlanes = 1;
		bmp_info_header.biBitCount = 16;
		bmp_info_header.biCompression = 0; //0x00
		bmp_info_header.biSizeImage = 0x00;
		bmp_info_header.biXPelsPerMeter = 0x0b40;
		bmp_info_header.biYPelsPerMeter = 0x0b40;
		bmp_info_header.biClrUsed = 0x0000;
		bmp_info_header.biClrImportant = 0;
	}

    //写文件头
	fwrite(&bmp_file_header, sizeof bmp_file_header, 1, bmp_file);
    //写信息头
    fwrite(&bmp_info_header, sizeof bmp_info_header, 1, bmp_file);
    //写图片数据
	if (sbmpData.lBitNum == 8)
	{
		for (i = 0; i<256; i++)
			fwrite(&bmp_color_quad[i], sizeof(bmp_color_quad[i]), 1, bmp_file);
		fwrite(sbmpData.data, sbmpData.width * sbmpData.height, 1, bmp_file);
	}
	else if (sbmpData.lBitNum == 24)
		fwrite(sbmpData.data, sbmpData.width * sbmpData.height * 3, 1, bmp_file);
	else if (sbmpData.lBitNum == 16)
		fwrite(sbmpData.data, sbmpData.width * sbmpData.height * 2, 1, bmp_file);
    //关闭文件
	fclose(bmp_file);
	delete[] pucTTTTT;
	return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值