BMP图像读取数据

我们在使用Windows的画图软件,画一张图,然后保存成24位位图BMP图像后,要对这幅图像进行一系列的格式转换之前,需要先将BMP里的数据提取出来,然后再保存成BGR888的图像。

有两处细节要注意:

第一,我们直接保存成BMP图片,不知道为什么读取BMP信息很多字段为0,所以我们要自己手动设置;

第二,读取出的数据我们以为是bgr格式存放的,其实不对,其实是grb存放的,虽然我也不知道为什么会这样。

chenLeeCV.c

#include "chenLeeCV.h"
#include <stdio.h>
#include <stdlib.h>
 
ClImage* clLoadImage(char* path)
{
	ClImage* bmpImg;
	FILE* pFile;
	unsigned short fileType;
	ClBitMapFileHeader bmpFileHeader;
	ClBitMapInfoHeader bmpInfoHeader;
	int channels = 1;
	int width = 0;
	int height = 0;
	int step = 0;
	int offset = 0;
	unsigned char pixVal;
	ClRgbQuad* quad;
	int i, j, k;
 
	bmpImg = (ClImage*)malloc(sizeof(ClImage));
	pFile = fopen(path, "rb");
	if (!pFile)
	{
		free(bmpImg);
		return NULL;
	}
 
	fread(&fileType, sizeof(unsigned short), 1, pFile);
	if (fileType == 0x4D42)
	{
		printf("bmp file! \n");
 
		fread(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
		printf("==============================================\n");
		printf("bmp:\n");
		printf("bmpFileHeader.bfSize:%d \n", bmpFileHeader.bfSize);
		printf("bmpFileHeader.bfReserved1:%d \n", bmpFileHeader.bfReserved1);
		printf("bmpFileHeader.bfReserved2:%d \n", bmpFileHeader.bfReserved2);
		printf("bmpFileHeader.bfOffBits:%d \n", bmpFileHeader.bfOffBits);
//		printf("bmp文件头信息:\n");
//		printf("文件大小:%d \n", bmpFileHeader.bfSize);
//		printf("保留字:%d \n", bmpFileHeader.bfReserved1);
//		printf("保留字:%d \n", bmpFileHeader.bfReserved2);
//		printf("位图数据偏移字节数:%d \n", bmpFileHeader.bfOffBits);
 
		fread(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
		printf("==============================================\n");
		printf("bmp\n");
		printf("bmpInfoHeader.biSize:%d \n", bmpInfoHeader.biSize);
		printf("bmpInfoHeader.biWidth:%d \n", bmpInfoHeader.biWidth);
		printf("bmpInfoHeader.biHeight:%d \n", bmpInfoHeader.biHeight);
		printf("bmpInfoHeader.biPlanes:%d \n", bmpInfoHeader.biPlanes);
		printf("bmpInfoHeader.biBitCount:%d \n", bmpInfoHeader.biBitCount);
		printf("bmpInfoHeader.biCompression:%d \n", bmpInfoHeader.biCompression);
		printf("bmpInfoHeader.biSizeImage:%d \n", bmpInfoHeader.biSizeImage);
		printf("bmpInfoHeader.biXPelsPerMeter:%d \n", bmpInfoHeader.biXPelsPerMeter);
		printf("bmpInfoHeader.biYPelsPerMeter:%d \n", bmpInfoHeader.biYPelsPerMeter);
		printf("bmpInfoHeader.biClrUsed:%d \n", bmpInfoHeader.biClrUsed);
		printf("bmpInfoHeader.biClrImportant:%d \n", bmpInfoHeader.biClrImportant);
//		printf("bmp文件信息头\n");
//		printf("结构体长度:%d \n", bmpInfoHeader.biSize);
//		printf("位图宽度:%d \n", bmpInfoHeader.biWidth);
//		printf("位图高度:%d \n", bmpInfoHeader.biHeight);
//		printf("位图平面数:%d \n", bmpInfoHeader.biPlanes);
//		printf("颜色位数:%d \n", bmpInfoHeader.biBitCount);
//		printf("压缩方式:%d \n", bmpInfoHeader.biCompression);
//		printf("实际位图数据占用的字节数:%d \n", bmpInfoHeader.biSizeImage);
//		printf("X方向分辨率:%d \n", bmpInfoHeader.biXPelsPerMeter);
//		printf("Y方向分辨率:%d \n", bmpInfoHeader.biYPelsPerMeter);
//		printf("使用的颜色数:%d \n", bmpInfoHeader.biClrUsed);
//		printf("重要颜色数:%d \n", bmpInfoHeader.biClrImportant);
		printf("==============================================\n");

//      不知道为什么这里读出来的数值是0,所以只能手动设置为24
		bmpInfoHeader.biBitCount = 24;
 
		if (bmpInfoHeader.biBitCount == 8)
		{
			printf("8bit\n\n");
//			printf("该文件有调色板,即该位图为非真彩色\n\n");
			channels = 1;
			width = bmpInfoHeader.biWidth;
			height = bmpInfoHeader.biHeight;
			offset = (channels*width)%4;
			if (offset != 0)
			{
				offset = 4 - offset;
			}
			//bmpImg->mat = kzCreateMat(height, width, 1, 0);
			bmpImg->width = width;
			bmpImg->height = height;
			bmpImg->channels = 1;
			bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*height);
			step = channels*width;
 
			quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad)*256);
			fread(quad, sizeof(ClRgbQuad), 256, pFile);
			free(quad);
 
			for (i=0; i<height; i++)
			{
				for (j=0; j<width; j++)
				{
					fread(&pixVal, sizeof(unsigned char), 1, pFile);
					bmpImg->imageData[(height-1-i)*step+j] = pixVal;
				}
				if (offset != 0)
				{
					for (j=0; j<offset; j++)
					{
						fread(&pixVal, sizeof(unsigned char), 1, pFile);
					}
				}
			}			
		}
		else if (bmpInfoHeader.biBitCount == 24)
		{
			printf("24bit\n\n");
//			printf("该位图为位真彩色\n\n");
			channels = 3;//channels也是需要手动设置,不知道为啥
//			width = bmpInfoHeader.biWidth;
//			height = bmpInfoHeader.biHeight;
			width = 1920;
			height = 1080;
 
			bmpImg->width = width;
			bmpImg->height = height;
			bmpImg->channels = 3;
			bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*3*height);
			step = channels*width;
 
			offset = (channels*width)%4;
			if (offset != 0)
			{
				offset = 4 - offset;
			}
 
			for (i=0; i<height; i++)
			{
				for (j=0; j<width; j++)
				{
					for (k=0; k<3; k++)
					{
						fread(&pixVal, sizeof(unsigned char), 1, pFile);
						bmpImg->imageData[(height-1-i)*step+j*3+k] = pixVal;
					}
					//kzSetMat(bmpImg->mat, height-1-i, j, kzScalar(pixVal[0], pixVal[1], pixVal[2]));
				}
				if (offset != 0)
				{
					for (j=0; j<offset; j++)
					{
						fread(&pixVal, sizeof(unsigned char), 1, pFile);
					}
				}
			}
		}
	}
 
	return bmpImg;
}
 
#if 0
//这是保存数据为BMP的代码,未验证
bool clSaveImage(char* path, ClImage* bmpImg)
{
	FILE *pFile;
	unsigned short fileType;
	ClBitMapFileHeader bmpFileHeader;
	ClBitMapInfoHeader bmpInfoHeader;
	int step;
	int offset;
	unsigned char pixVal = '\0';
	int i, j;
	ClRgbQuad* quad;
 
	pFile = fopen(path, "wb");
	if (!pFile)
	{
		return false;
	}
 
	fileType = 0x4D42;
	fwrite(&fileType, sizeof(unsigned short), 1, pFile);
 
	if (bmpImg->channels == 3)//24位,通道,彩图
	{
		step = bmpImg->channels*bmpImg->width;
		offset = step%4;
		if (offset != 4)
		{
			step += 4-offset;
		}
 
		bmpFileHeader.bfSize = bmpImg->height*step + 54;
		bmpFileHeader.bfReserved1 = 0;
		bmpFileHeader.bfReserved2 = 0;
		bmpFileHeader.bfOffBits = 54;
		fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
 
		bmpInfoHeader.biSize = 40;
		bmpInfoHeader.biWidth = bmpImg->width;
		bmpInfoHeader.biHeight = bmpImg->height;
		bmpInfoHeader.biPlanes = 1;
		bmpInfoHeader.biBitCount = 24;
		bmpInfoHeader.biCompression = 0;
		bmpInfoHeader.biSizeImage = bmpImg->height*step;
		bmpInfoHeader.biXPelsPerMeter = 0;
		bmpInfoHeader.biYPelsPerMeter = 0;
		bmpInfoHeader.biClrUsed = 0;
		bmpInfoHeader.biClrImportant = 0;
		fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
 
		for (i=bmpImg->height-1; i>-1; i--)
		{
			for (j=0; j<bmpImg->width; j++)
			{
				pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3];
				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
				pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3+1];
				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
				pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3+2];
				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
			}
			if (offset!=0)
			{
				for (j=0; j<offset; j++)
				{
					pixVal = 0;
					fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
				}
			}
		}
	}
	else if (bmpImg->channels == 1)//8位,单通道,灰度图
	{
		step = bmpImg->width;
		offset = step%4;
		if (offset != 4)
		{
			step += 4-offset;
		}
 
		bmpFileHeader.bfSize = 54 + 256*4 + bmpImg->width;
		bmpFileHeader.bfReserved1 = 0;
		bmpFileHeader.bfReserved2 = 0;
		bmpFileHeader.bfOffBits = 54 + 256*4;
		fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
 
		bmpInfoHeader.biSize = 40;
		bmpInfoHeader.biWidth = bmpImg->width;
		bmpInfoHeader.biHeight = bmpImg->height;
		bmpInfoHeader.biPlanes = 1;
		bmpInfoHeader.biBitCount = 8;
		bmpInfoHeader.biCompression = 0;
		bmpInfoHeader.biSizeImage = bmpImg->height*step;
		bmpInfoHeader.biXPelsPerMeter = 0;
		bmpInfoHeader.biYPelsPerMeter = 0;
		bmpInfoHeader.biClrUsed = 256;
		bmpInfoHeader.biClrImportant = 256;
		fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
 
		quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad)*256);
		for (i=0; i<256; i++)
		{
			quad[i].rgbBlue = i;
			quad[i].rgbGreen = i;
			quad[i].rgbRed = i;
			quad[i].rgbReserved = 0;
		}
		fwrite(quad, sizeof(ClRgbQuad), 256, pFile);
		free(quad);
 
		for (i=bmpImg->height-1; i>-1; i--)
		{
			for (j=0; j<bmpImg->width; j++)
			{
				pixVal = bmpImg->imageData[i*bmpImg->width+j];
				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
			}
			if (offset!=0)
			{
				for (j=0; j<offset; j++)
				{
					pixVal = 0;
					fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
				}
			}
		}
	}
	fclose(pFile);
 
	return true;
}
#endif

chenLeeCV.h

#ifndef CHENLEECV_H
#define CHENLEECV_H
 
typedef struct
{
	//unsigned short    bfType;
	unsigned long    bfSize;
	unsigned short    bfReserved1;
	unsigned short    bfReserved2;
	unsigned long    bfOffBits;
} ClBitMapFileHeader;
 
typedef struct
{
	unsigned long  biSize; 
	long   biWidth; 
	long   biHeight; 
	unsigned short   biPlanes; 
	unsigned short   biBitCount;
	unsigned long  biCompression; 
	unsigned long  biSizeImage; 
	long   biXPelsPerMeter; 
	long   biYPelsPerMeter; 
	unsigned long   biClrUsed; 
	unsigned long   biClrImportant; 
} ClBitMapInfoHeader;
 
typedef struct 
{
	unsigned char rgbBlue; //该颜色的蓝色分量
	unsigned char rgbGreen; //该颜色的绿色分量
	unsigned char rgbRed; //该颜色的红色分量
	unsigned char rgbReserved; //保留值
} ClRgbQuad;
 
typedef struct
{
	int width;
	int height;
	int channels;
	unsigned char* imageData;
}ClImage;
 
ClImage* clLoadImage(char* path);
//bool clSaveImage(char* path, ClImage* bmpImg);
 
#endif

main.c

//#include "stdafx.h"
#include <stdio.h>
#include "chenLeeCV.h"

unsigned char bgr_buffer[6220800];
unsigned char yuv444_buffer[6220800];
unsigned char nv12_buffer[3110400];

unsigned char b_buffer[2073600];
unsigned char g_buffer[2073600];
unsigned char r_buffer[2073600];


int process(char *path)
{
	ClImage* img = clLoadImage(path);
	char *bgrimage_fake = "bgr_fake.data";
	FILE *fp_bgr_fake = fopen(bgrimage_fake,"a+");
	if(NULL == fp_bgr_fake)
	{
		printf("open file[%s] failed!\n", bgrimage_fake);
		return -1;
	}

	fwrite((void*)img->imageData, 1, 6220800, fp_bgr_fake);
	fclose(fp_bgr_fake);

	memset((void*)b_buffer,0,2073600);
	memset((void*)g_buffer,0,2073600);
	memset((void*)r_buffer,0,2073600);

	int i = 0;
	int j = 0;
	int k = 0;

	static int num = 1;

	for(i = 0; i < 1080; i++)
	{
		for(j = 0; j < 1920; j++)
		{
			b_buffer[i*1920+j] = *((unsigned char*)img->imageData + k);
			k++;
			g_buffer[i*1920+j] = *((unsigned char*)img->imageData + k);
			k++;
			r_buffer[i*1920+j] = *((unsigned char*)img->imageData + k);
			k++;
		}
	}
#if 0
	char *bimage = "b.data";
	FILE *fp_b = fopen(bimage,"a+");
	if(NULL == fp_b)
	{
		printf("open file[%s] failed!\n", bimage);
		return -1;
	}

	fwrite((void*)b_buffer, 1, 2073600, fp_b);
	fclose(fp_b);

	char *gimage = "g.data";
	FILE *fp_g = fopen(gimage,"a+");
	if(NULL == fp_g)
	{
		printf("open file[%s] failed!\n", gimage);
		return -1;
	}

	fwrite((void*)g_buffer, 1, 2073600, fp_g);
	fclose(fp_g);

	char *rimage = "r.data";
	FILE *fp_r = fopen(rimage,"a+");
	if(NULL == fp_r)
	{
		printf("open file[%s] failed!\n", rimage);
		return -1;
	}

	fwrite((void*)r_buffer, 1, 2073600, fp_r);
	fclose(fp_r);
#endif

	memset((void*)bgr_buffer,0,6220800);

	/* 这张bmp图是按照grbgrb这么存放的,即我们认为的b其实是真实的g,g是r,r是b,虽然不知道为什么会这样 */
	k = 0;

	for(i = 0; i < 1080; i++)
	{
		for(j = 0; j < 1920;)
		{
			bgr_buffer[i * 1920  + j] = r_buffer[k];
			bgr_buffer[i * 1920  + j + 1] = b_buffer[k];
			bgr_buffer[i * 1920  + j + 2] = g_buffer[k];
			j+=3;
			k++;
		}
	}

	char *bgrimage = "bgr.data";
	FILE *fp_bgr = fopen(bgrimage,"a+");
	if(NULL == fp_bgr)
	{
		printf("open file[%s] failed!\n", bgrimage);
		return -1;
	}

	fwrite((void*)bgr_buffer, 1, 6220800, fp_bgr);
	fclose(fp_bgr);

	return 0;
}

int main(int argc, char* argv[])
{
	int i = 0;
	char photo_path[256];

	for(i = 1; i < 61; i++)
	{
		sprintf(photo_path, "photo_test/%d.bmp",i);//这里是进行60张BMP图片处理
		process(photo_path);
	}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值