BMP图片读写函数

注意:

1.Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充.这一点相当重要,

2.在BMP文件中,数据矩阵的存放方式都是按照(对应于原图)行按从下到上,列按从左到右的顺序进行存放。
在这里插入图片描述
在这里插入图片描述
BMP读函数:

 #include <stdio.h>
 #include <fcntl.h>

typedef unsigned short U16;
typedef unsigned long  U32;
#pragma pack(1) //设置1字节对齐模式,pack()将对齐模式取消
/*位图文件头*/
typedef struct BMP_FILE_HEADER
{
	U16 bType;             /*  文件标识符          */
	U32 bfSize;            /*  文件的大小,单位字节 */
	U16 bReserved1;        /*  保留值,必须设置为0  */
	U16 bReserved2;        /*  保留值,必须设置为0  */
	U32 bOffset;           /*  文件头的最后到图像数据位开始的偏移量    */
} BMPFILEHEADER;

/*位图信息头*/
typedef struct BMP_INFO
{
	U32 bInfoSize;        /*  信息头的大小             */
	U32 bWidth;           /*  图像的宽度               */
	U32 bHeight;          /*  图像的高度               */
	U16 bPlanes;          /*  图像的位面数             */
	U16 bBitCount;        /*  每个像素的位数           */
	U32 bCompression;     /*  压缩类型                 */
	U32 bmpImageSize;     /*  图像的大小,以字节为单位   */
	U32 bXPelsPerMeter;   /*  水平分辨率               */
	U32 bYPelsPerMeter;   /*  垂直分辨率               */
	U32 bClrUsed;         /*  使用的色彩数             */
	U32 bClrImportant;    /*  重要的颜色数             */
} BMPINF;
#pragma pack()
/*彩色表*/
typedef struct RGB_QUAD
{
	U16 rgbBlue;         /*  蓝色强度  */
	U16 rgbGreen;        /*  绿色强度  */
	U16 rgbRed;          /*  红色强度  */
	U16 rgbReversed;     /*  保留值    */
} RGBQUAD;


 int read_bmp(const char *path, char *img_src_r, char * img_src_g, char * img_src_b, int *width, int *height)
{
	FILE* fp;
	BMPFILEHEADER fileHeader = { 0 };
	BMPINF infoHeader = { 0 };
	long offset, bmpImageSize, bytesPerPixel, size, bitCount;
	int i = 0, j = 0, count = 0;
	int lcount = 0;
	int cl[3] = { 0 };
	U16 c;
	char *bmpData;
	int lineByte = 0;
	fp = fopen(path, "rb");
	if (fp == NULL) {
		return -1;
	}

fread(&fileHeader, sizeof(BMPFILEHEADER), 1, fp);
fread(&infoHeader, sizeof(BMPINF), 1, fp);
//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)  
lineByte = (infoHeader.bWidth * infoHeader.bBitCount / 8 + 3) / 4 * 4;
//debug
infoHeader.bHeight = *height;

bmpData = (char *)malloc((infoHeader.bHeight*lineByte) * sizeof(char));
fseek(fp, fileHeader.bOffset, SEEK_SET);
fread(bmpData, 1, infoHeader.bHeight*lineByte, fp);

for (i = 0; i < infoHeader.bHeight; ++i) {
	for (j = 0; j < infoHeader.bWidth; ++j) {
		img_src_b[i*infoHeader.bWidth + j] = bmpData[i*lineByte + j * 3];
		img_src_g[i*infoHeader.bWidth + j] = bmpData[i*lineByte + j * 3 + 1];
		img_src_r[i*infoHeader.bWidth + j] = bmpData[i*lineByte + j * 3 + 2];
	}
}

free(bmpData);
fclose(fp);

return 0;

}
写函数

void saveBmp(char * filename, unsigned char * imageData, int height, int width, int channels)
{
bmpFileHead bh;
bmpHeadInfo bi;
RGBQUAD rq[256];
FILE * fout = fopen(filename, "wb");
unsigned short fileType = 0x4D42;
fwrite(&fileType, sizeof(unsigned short), 1, fout);

int step = channels * width;
int offset = step % 4;
if (offset != 0)
	step += (4 - offset);

if (channels == 1)
	bh.bfSize = height * step + 1078;
else
	bh.bfSize = height * step + 54;
bh.bfReserved1 = 0;
bh.bfReserved2 = 0;
if (channels == 1)
	bh.bfOffBits = 1078;
else
	bh.bfOffBits = 54;
fwrite(&bh, sizeof(bmpFileHead), 1, fout);

//  printf("%d\n", (int)bh.bfType);
//  printf("%ld\n", bh.bfSize);
//  printf("%d\n", (int)bh.bfReserved1);
//  printf("%d\n", (int)bh.bfReserved2);
//  printf("%ld\n", bh.bfOffBits);

int r;
for (r = 0; r < 256; r++)
{
	rq[r].rgbBlue = rq[r].rgbGreen = rq[r].rgbRed = r;
	rq[r].rgbReserved = 0;
	//  printf("%d\n", rq[r].rgbBlue);
	//  printf("%d\n", rq[r].rgbGreen);
	//  printf("%d\n", rq[r].rgbRed);
	//  printf("%d\n", rq[r].rgbReserved);
}


bi.biSize = 40;
bi.biWidth = width;
//bi.biHeight =-height;
bi.biHeight = height; //hujianhua
bi.biPlanes = 1;
bi.biBitCount = 8 * channels;
bi.biCompression = 0;
bi.biSizeImage = height*step;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

//  printf("%ld\n", bi.biSize);
//  printf("%ld\n", bi.biWidth);
//  printf("%ld\n", bi.biHeight);
//  printf("%d\n", bi.biPlanes);
//  printf("%d\n", bi.biBitCount);
//  printf("%ld\n", bi.biCompression);
//  printf("%ld\n", bi.biSizeImage);
//  printf("%ld\n", bi.biXPelsPerMeter);
//  printf("%ld\n", bi.biYPelsPerMeter);
//  printf("%ld\n", bi.biClrUsed);
//  printf("%ld\n", bi.biClrImportant);

fwrite(&bi, sizeof(bmpHeadInfo), 1, fout);
if (channels == 1)
	fwrite(&rq, 4, 256, fout);

//unsigned char dc[channels];
unsigned char def = 0;
//  fseek(fout, 1078, SEEK_SET);

int i, j, c;
for (i = height - 1; i >= 0; i--)
{
	for (j = 0; j < width; j++)
	{
		for (c = 0; c < channels; c++)
		{
			int value = imageData[(i * width + j) * channels + c];
			//  if(value > 255)
			//      printf("%d\t", value);
			fwrite(&imageData[(i * width + j) * channels + c], sizeof(unsigned char), 1, fout);
		}
	}
	if (offset != 0)
	{
		for (j = 0; j < 4 - offset; j++)
		{
			fwrite(&def, sizeof(unsigned char), 1, fout);
		}
	}
}
fclose(fout);

}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风口上的传奇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值