任意宽度灰度BMP图像读写 V2

任意宽度灰度BMP图像读写 V2

//myRdWtIm.h

/* 
* Copyright (c) 2013,中科院苏州医工所 
* All rights reserved. 
*  
* 文件名称:myRdWtIm.h 
* 文件标识:见配置管理计划书 
* 摘    要:读写BMP图像。“格式数据”指直接从BMP读取的或能够直接写入BMP的数据,
* 其宽度满足BMP格式要求,即满足4的倍数。“有效数据”指实际图像数据,其宽度不一定
*  满足BMP格式要求。
*  
* 当前版本:1.1 
* 作    者:LYC
* 完成日期:2013年6月27日 
*/

#ifndef RWBMP_H
#define RWBMP_H

#include <windows.h>
#include <stdio.h>
#include <assert.h>

class RdWtIm
{
public:
	RdWtIm(void);
	~RdWtIm(void);

public:
	BYTE *rd8BitBmpFmt(char *imName, int *imWidth, int *imHeight);	//读8位BMP图像,返回格式图像数据。
	BYTE *rd8BitBmpNtFmt(char *imName, int *imWidth, int *imHeight);	//读8位BMP图像,返回有效图像数据。

	bool wt8BitBmpFmt(BYTE *imBuffer, int imWidth, int imHeight, char *imName); //将格式图像数据写入8位BMP图像
	bool wt8BitBmpNtFmt(BYTE *imBuffer, int imWidth, int imHeight, char *imName); //将有效图像数据写入8位BMP图像

};


#endif


//myRdWtIm.cpp

/* 
* Copyright (c) 2013,中科院苏州医工所 
* All rights reserved. 
*  
* 文件名称:myRdWtIm.h 
* 文件标识:见配置管理计划书 
* 摘    要:读写BMP图像。“格式数据”指直接从BMP读取的或能够直接写入BMP的数据,
* 其宽度满足BMP格式要求,即满足4的倍数。“有效数据”指实际图像数据,其宽度不一定
*  满足BMP格式要求。
*  
* 当前版本:1.1 
* 作    者:LYC
* 完成日期:2013年6月27日 
*/

#include "myRdWtIm.h"

RdWtIm::RdWtIm()
{

}

RdWtIm::~RdWtIm()
{

}

/*
* 函数名:rd8BitBmp()
* 功能:读取8位灰度BMP图像,返回格式数据
* 参数:
*	imName -文件路径及名字
*	imWidth -图像宽度
*	imHeight -图像高度
* 返回值:BYTE*
* 作者:LYC
* 时间:2013.6.27
*/

BYTE* RdWtIm::rd8BitBmpFmt(char *imName, int *imWidth, int *imHeight)
{
	//对参数的有效性进行检查
	assert(imName != NULL);

	//二进制读方式打开图像文件
	FILE *fp = fopen(imName, "rb");
	if(fp == NULL)
	{
		return NULL;
	}

	//跳过位图文件头
	fseek(fp, sizeof(BITMAPFILEHEADER), 0);

	//读取位图信息头
	BITMAPINFOHEADER head;
	fread(&head, sizeof(BITMAPINFOHEADER), 1, fp); 

	 //判断是否为8位灰度图像
	if (head.biBitCount != 8)
	{
		return NULL;
	}

	//获取图像宽、高信息
	*imWidth = head.biWidth ;
	*imHeight = head.biHeight ;	

	//求图像格式宽度(必须是4的倍数)
	int lineByte = ((*imWidth) * (head.biBitCount ) / 8 + 3) / 4 * 4;

	//读取颜色表
	RGBQUAD *pColorTable = new RGBQUAD[256];
	fread(pColorTable, sizeof(RGBQUAD), 256, fp);	
	delete pColorTable;

	//读格式数据
	BYTE *pBmpBuf = new BYTE[lineByte * (*imHeight)];
	fread(pBmpBuf, 1, lineByte * (*imHeight), fp);
	
	fclose(fp);

	return pBmpBuf;
}

/*
* 函数名:rd8BitBmp()
* 功能:读取8位灰度BMP图像,并返回有效图像数据
* 参数:
*	imName -文件路径及名字
*	imWidth -图像宽度
*	imHeight -图像高度
* 返回值:BYTE*
* 作者:LYC
* 时间:2013.6.27
*/

BYTE* RdWtIm::rd8BitBmpNtFmt(char *imName, int *imWidth, int *imHeight)
{
	//对参数的有效性进行检查
	assert(imName != NULL);

	//二进制读方式打开图像文件
	FILE *fp = fopen(imName, "rb");
	if(fp == NULL)
	{
		return NULL;
	}

	//跳过位图文件头
	fseek(fp, sizeof(BITMAPFILEHEADER), 0);

	//读取位图信息头
	BITMAPINFOHEADER head;
	fread(&head, sizeof(BITMAPINFOHEADER), 1, fp); 

	//判断是否为8位灰度图像
	if (head.biBitCount != 8)
	{
		return NULL;
	}

	//获取图像宽、高信息
	*imWidth = head.biWidth ;
	*imHeight = head.biHeight ;	

	//求图像格式宽度(必须是4的倍数)
	int lineByte = ((*imWidth) * (head.biBitCount ) / 8 + 3) / 4 * 4;

	//读取颜色表
	RGBQUAD *pColorTable = new RGBQUAD[256];
	fread(pColorTable, sizeof(RGBQUAD), 256, fp);	
	delete pColorTable;

	//读格式数据
	BYTE *pBmpBuf = new BYTE[lineByte * (*imHeight)];
	fread(pBmpBuf, 1, lineByte * (*imHeight), fp);
	fclose(fp);

	//提取有效数据
	if (*imWidth < lineByte)
	{
		BYTE *pBmpBufData = new BYTE[(*imWidth) * (*imHeight)]();
		for (int i=0; i<*imHeight; i++)
		{
			for (int j=0; j<*imWidth; j++)
			{
				*(pBmpBufData + i * (*imWidth) + j) = *(pBmpBuf + i * lineByte + j);	
			}
		}
		delete pBmpBuf;
		return pBmpBufData; //有效数据
	}
	else
	{
		return pBmpBuf;	
	}
}

/*
* 函数名:wt8BitBmpFmt()
* 功能:将格式图像数据写入8位BMP图像
* 参数:
*	imBuffer - 格式图像数据
*	imWidth -图像宽度
*	imHeight -图像高度
*	imName -文件路径及名字
* 返回值:bool
* 作者:LYC
* 时间:2013.6.27
*/

bool RdWtIm::wt8BitBmpFmt(BYTE *imBuffer, int imWidth, int imHeight, char *imName) 
{
	//对参数的有效性进行检查
	assert((imBuffer != NULL) && (imWidth > 0) && (imHeight > 0) && (imName != NULL));

	//每个像素所占的位数(bit)
	int biBitCount = 8;	

	//颜色表大小,以字节为单位,灰度图像颜色表为1024字节
	int colorTablesize = 1024;

	//待存储图像数据每行字节数为4的倍数
	int lineByte = (imWidth * biBitCount / 8 + 3) / 4 * 4;

	//以二进制写的方式打开文件
	FILE *fp = fopen(imName, "wb");
	if(fp == NULL)
	{
		return false;
	}

	//申请位图文件头结构变量,填写文件头信息
	BITMAPFILEHEADER fileHead;
	fileHead.bfType = 0x4D42;	//bmp类型

	//bfSize是图像文件4个组成部分之和
	fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*imHeight;
	fileHead.bfReserved1 = 0;
	fileHead.bfReserved2 = 0;

	//bfOffBits是图像文件前3个部分所需空间之和
	fileHead.bfOffBits = 54 + colorTablesize;

	//写文件头进文件
	fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);

	//申请位图信息头结构变量,填写信息头信息
	BITMAPINFOHEADER head;
	head.biSize = 40;	 //本结构的长度
	head.biWidth = imWidth;	//位图的宽度,以像素为单位
	head.biHeight  = imHeight; //位图的宽度,以像素为单位
	head.biPlanes  = 1; //目标设备的级别,必须是1
	head.biBitCount = 8; //每个像素所占的位数(bit),其值必须为1(黑白图像),4(16色图),8(256色),24(真彩色图)
	head.biCompression = BI_RGB; //位图压缩类型,有效的值为BI_RGB(未经压缩)、BI_RLE4,BI_RLE8,BI_BITFIEDS(均为Windows定义常量)。
	head.biSizeImage  = lineByte*imHeight;	//实际的位图数据占用的字节数
	head.biXPelsPerMeter = 0; //指定目标数据的水平分辨率,单位是像素/米。
	head.biYPelsPerMeter = 0; //指定目标数据的垂直分辨率,单位是像素/米。
	head.biClrUsed = 0; //位图实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂
	head.biClrImportant  = 0; //位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

	//写位图信息头进内存
	fwrite(&head, sizeof(BITMAPINFOHEADER), 1, fp);

	//申请颜色表所需要的空间,写颜色表进文件
	RGBQUAD *pColorTable = new RGBQUAD[256];
	for (int i=0; i<256; i++)
	{
		pColorTable[i].rgbRed = i;
		pColorTable[i].rgbGreen = i;
		pColorTable[i].rgbBlue = i;
		pColorTable[i].rgbReserved = 0;
	}
	fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);
	delete pColorTable;

	//写格式图像数据写进文件
	fwrite(imBuffer, imHeight*lineByte, 1, fp);

	//关闭文件
	fclose(fp); 

	return true;
}

/*
* 函数名:wt8BitBmpFmt()
* 功能:将有效图像数据写入8位BMP图像
* 参数:
*	imBuffer - 格式图像数据
*	imWidth -图像宽度
*	imHeight -图像高度
*	imName -文件路径及名字
* 返回值:bool
* 作者:LYC
* 时间:2013.6.27
*/

bool RdWtIm::wt8BitBmpNtFmt(BYTE *imBuffer, int imWidth, int imHeight, char *imName)
{
	//对参数的有效性进行检查
	assert((imBuffer != NULL) && (imWidth > 0) && (imHeight > 0) && (imName != NULL));

	//每个像素所占的位数(bit)
	int biBitCount = 8;	

	//颜色表大小,以字节为单位,灰度图像颜色表为1024字节
	int colorTablesize = 1024;

	//待存储图像数据每行字节数为4的倍数
	int lineByte = (imWidth * biBitCount / 8 + 3) / 4 * 4;

	//以二进制写的方式打开文件
	FILE *fp = fopen(imName, "wb");
	if(fp == NULL)
	{
		return false;
	}

	//申请位图文件头结构变量,填写文件头信息
	BITMAPFILEHEADER fileHead;
	fileHead.bfType = 0x4D42;	//bmp类型

	//bfSize是图像文件4个组成部分之和
	fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*imHeight;
	fileHead.bfReserved1 = 0;
	fileHead.bfReserved2 = 0;

	//bfOffBits是图像文件前3个部分所需空间之和
	fileHead.bfOffBits = 54 + colorTablesize;

	//写文件头进文件
	fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);

	//申请位图信息头结构变量,填写信息头信息
	BITMAPINFOHEADER head;
	head.biSize = 40;	 //本结构的长度
	head.biWidth = imWidth;	//位图的宽度,以像素为单位
	head.biHeight  = imHeight; //位图的宽度,以像素为单位
	head.biPlanes  = 1; //目标设备的级别,必须是1
	head.biBitCount = 8; //每个像素所占的位数(bit),其值必须为1(黑白图像),4(16色图),8(256色),24(真彩色图)
	head.biCompression = BI_RGB; //位图压缩类型,有效的值为BI_RGB(未经压缩)、BI_RLE4,BI_RLE8,BI_BITFIEDS(均为Windows定义常量)。
	head.biSizeImage  = lineByte*imHeight;	//实际的位图数据占用的字节数
	head.biXPelsPerMeter = 0; //指定目标数据的水平分辨率,单位是像素/米。
	head.biYPelsPerMeter = 0; //指定目标数据的垂直分辨率,单位是像素/米。
	head.biClrUsed = 0; //位图实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂
	head.biClrImportant  = 0; //位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

	//写位图信息头进内存
	fwrite(&head, sizeof(BITMAPINFOHEADER), 1, fp);

	//申请颜色表所需要的空间,写颜色表进文件
	RGBQUAD *pColorTable = new RGBQUAD[256];
	for (int i=0; i<256; i++)
	{
		pColorTable[i].rgbRed = i;
		pColorTable[i].rgbGreen = i;
		pColorTable[i].rgbBlue = i;
		pColorTable[i].rgbReserved = 0;
	}
	fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);
	delete pColorTable;

	//判断位图数据宽度是否正确,并写数据进入BMP
	if (imWidth < lineByte)	//如果有效数据宽度小于BMP格式宽度
	{
		BYTE *imgBufBMP = new BYTE [lineByte*imHeight](); //申请格式空间并初始化

		//将有效数据赋给用于写BMP的数据空间
		for (int i=0;i<imHeight;i++) 
		{
			for (int j=0;j<imWidth;j++)
			{
				*(imgBufBMP+i*lineByte+j) = *(imBuffer + i*imWidth + j);	
			}
		}

		//写BMP格式要求的图数据写进文件
		fwrite(imgBufBMP, imHeight*lineByte, 1, fp);
	}
	else
	{
		//写有效图数据写进文件
		fwrite(imBuffer, imHeight*lineByte, 1, fp);
	}

	//关闭文件
	fclose(fp); 

	return true;
}


神爱世人,甚至将他的独生子(耶稣)赐给他们,叫一切信他的,不至灭亡,反得永生。
                                                                                                                                                                         ——【圣经·约翰福音3:16】

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东山一角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值