hi3516 bmp yuv2rgb888


原文链接: hi3516 bmp yuv2rgb888

(7条消息)BMP格式详解_运维_Tut-CSDN博客

#include "hi_comm_ive.h"
#include "mpi_ive.h"
 
#pragma pack(push)
#pragma pack(1)
 
typedef struct{
    short type;
    int size;
    short reserved1;
    short reserved2;
    int offset;
} BMPHeader;
 
typedef struct{
    int size;
    int width;
    int height;
    short planes;
    short bitsPerPixel;
    unsigned compression;
    unsigned imageSize;
    int xPelsPerMeter;
    int yPelsPerMeter;
    int clrUsed;
    int clrImportant;
} BMPInfoHeader;
 
#pragma pack(pop)
 
 
int saveBMPFile(unsigned char* src, int width, int height, const char* name){
	BMPHeader hdr;
	BMPInfoHeader infoHdr;
    int ret = 0;
 
	FILE* fp = NULL;
    if(NULL == src) 
    {
		return (-1);
    }
 
    fp = fopen(name,"wb");
	if(NULL == fp)
    {
		printf("saveBMPFile: Err: Open!\n");
		return (-1);
	}
 
	infoHdr.size	= sizeof(BMPInfoHeader);
	infoHdr.width	= width;
	infoHdr.height	= 0 - height;
	infoHdr.planes	= 1;
	infoHdr.bitsPerPixel	= 24;
	infoHdr.compression		= 0;
	infoHdr.imageSize		= width*height;
	infoHdr.xPelsPerMeter	= 0;
	infoHdr.yPelsPerMeter	= 0;
	infoHdr.clrUsed			= 0;
	infoHdr.clrImportant	= 0;
 
	hdr.type	= 0x4D42;
	hdr.size	= 54 + infoHdr.imageSize*3;
	hdr.reserved1	= 0;
	hdr.reserved2	= 0;
	hdr.offset	= 54;
 
 
    //BGR2RGB
    int i;
    int temp;
    for(i = 0;i < width*height;i++)
    {
        temp = src[i*3];
        src[i*3] = src[i*3 + 2];
        src[i*3 + 2] = temp;
    }
 
	fwrite(&hdr, sizeof(hdr), 1, fp);
  	fwrite(&infoHdr, sizeof(infoHdr), 1, fp);
 	fwrite(src, sizeof(unsigned char), width*height*3, fp); //TODO:
    fflush(fp);
 
	if(ferror(fp)){
		printf("saveBMPFile: Err: Unknown!***\n");
	}
 
	fclose(fp);
    fp = NULL;
 
	return 0;
}
 
int main()
{
    HI_VOID *pVirtSrc = NULL;
	HI_VOID *pVirtDst = NULL;
	IVE_SRC_INFO_S stSrc;
	IVE_MEM_INFO_S stDst;
    unsigned int * pImage = NULL;
 
    stSrc.enSrcFmt = IVE_SRC_FMT_SP422;
    stSrc.stSrcMem.u32Stride = nWidth;
    stSrc.stSrcMem.u32PhyAddr = frameInfo->phyAddr;
    stSrc.u32Width = nWidth;
    stSrc.u32Height = nHeight;
 
    stDst.u32Stride = nWidth;
 
    IVE_HANDLE IveHandle;
    HI_BOOL bInstant = HI_TRUE;
    IVE_CSC_CTRL_S stCscCtrl;
    stCscCtrl.enOutFmt = IVE_CSC_OUT_FMT_PACKAGE;
    stCscCtrl.enCscMode = IVE_CSC_MODE_VIDEO_BT601_AND_BT656;
 
    //s32Ret = HI_MPI_SYS_MmzAlloc_Cached (&pstSrc->stSrcMem.u32PhyAddr,&pVirtSrc,"User", HI_NULL, pstSrc->u32Height * pstSrc->stSrcMem.u32Stride*2);
    //memset(pVirtSrc,1,pstSrc->u32Height * pstSrc->stSrcMem.u32Stride);
    ret = HI_MPI_SYS_MmzAlloc_Cached (&stDst.u32PhyAddr, &pVirtDst,"User", HI_NULL, stSrc.u32Height * stDst.u32Stride);
    //s32Ret = HI_MPI_IVE_DMA(&IveHandle, &stSrc, &stDst, bInstant);
    //HI_MPI_SYS_MmzFree(stSrc.stSrcMem.u32PhyAddr, pVirtSrc);
    HI_MPI_SYS_MmzFree(stDst.u32PhyAddr, pVirtDst);
    ret=HI_MPI_IVE_CSC(&IveHandle,&stSrc,&stDst,&stCscCtrl,bInstant);
    if(ret==HI_FAILURE)
    {
        printf("YUV Convert to RGB failed!\n");
        return HI_FAILURE;
    }
 
    pImage = HI_MPI_SYS_Mmap(stDst.u32PhyAddr, nLengthImage/2*3);
    if(NULL == pImage)
    {
        msg_print( "HI_MPI_SYS_Mmap err!\n");
        return NVD_FALSE;
    }
 
    ret = saveBMPFile((Byte*)pImage, nWidth, nHeight, "/mnt/rgb.dib");
    if(0 != ret)
    {
        printf( "saveBMPFile error\n");
        return;
    }
    printf("saveBMPFile done!\n");
 
    //uninit();
}

————————————————
版权声明:本文为CSDN博主「雷电羊」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cjsycyl/article/details/8676110

BPP bitsPerPixel 表示每个像素占用的位数

bitmap格式图片是未经压缩的,一般24bit位图(即一个像素点以24个二进制位表示)。

分别用8个二进制位表示R/G/B三种颜色,这样一共可以表示256*256*256=16777216种颜色。

8bit的位图则为黑白图像,32bit位图除16777216种颜色外还有8个bit表示光栅(有待具体研究)。

BMP图像文件被分成4个部分:位图文件头(Bitmap File Header)、位图信息头(Bitmap Info Header)、颜色表(Color Map)和位图数据(即图像数据,Data Bits或Data Body)。

第1部分为位图文件头BITMAPFILEHEADER,是一个结构体类型,该结构的长度是固定的,为14个字节。其定义如下:

typedef struct FileHeader
{

unsigned short  bfType;
unsigned int    bfSize;
unsigned short  bfReserved1;
unsigned short  bfReserved2;
unsigned int    bfOffBits;

}attribute((packed))FileHeader;

BITMAPFILEHEADER结构的各个域详细说明如下:

bfType:位图文件类型,必须是0x424D,即字符串“BM”,也就是说,所有的“*.bmp”文件的头两个字节都是“BM”。

bfSize:位图文件大小,包括这14个字节。

bfReserved1, bfReserved2:Windows保留字,暂不用。

bfOffBits:从文件头到实际的位图数据的偏移字节数,bitmap文件前3个部分(文件头、信息头、颜色表)的长度之和。

第2部分为位图信息头BITMAPINFOHEADER,也是一个结构体类型的数据结构,该结构的长度也是固定的,为40个字节。其定义如下:

typedef struct InfoHeader
{

unsigned int    biSize;
int             biWidth;
int             biHeight;
unsigned short  biPlanes;
unsigned short  biBitCount;
unsigned int    biCompression;
unsigned int    biSizeImage;
int             biXPelsPerMeter;
int             biYPelsPerMeter;
unsigned int    biClrUsed;
unsigned int    biClrImportant;

}attribute((packed))InfoHeader;
BITMAPINFOHEADER结构的各个域的详细说明如下:
biSize:本结构的长度,为40个字节。

biWidth:位图的宽度,以像素为单位。

biHeight:位图的高度,以像素为单位。

biPlanes:目标设备的级别,必须是1。

biBitCount:每个像素所占的位数(bit),其值必须为1(黑白图像)、4(16色图)、8(256色)、24(真彩色图),新的BMP格式支持32位色。

biCompresssion:位图压缩类型,有效的值为BI_RGB(未经压缩)、BI_RLE8、BI_RLE4、BI_BITFILEDS(均为Windows定义常量)。这里只讨论未经压缩的情况,即biCompression=BI_RGB。

biSizeImage:实际的位图数据占用的字节数,该值的大小在第4部分位图数据中有具体解释。

biXPelsPerMeter:指定目标设备的水平分辨率,单位是像素/米。

biYPelsPerMeter:指定目标设备的垂直分辨率,单位是像素/米。

biClrUsed:位图实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂。

biClrImportant:位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

第3部分为颜色表。颜色表实际上是一个RGBQUAD结构的数组,数组的长度由biClrUsed指定(如果该值为零,则由biBitCount指定,即2的biBitCount次幂个元素)。RGBQUAD结构是一个结构体类型,占4个字节,其定义如下:

typedef struct tagRGBQUAD
{

unsigned char   rgbBlue;
unsigned char   rgbGreen;
unsigned char   rgbRed;
unsigned char   rgbReserved;

}RGBQUAD;
RGBQUAD结构的各个域的详细说明如下:

rgbBlue:该颜色的蓝色分量;

rgbGreen:该颜色的绿色分量;

rgbRed:该颜色的红色分量;

rgbReserved:保留字节,暂不用。

有些位图需要颜色表;有些位图(如真彩色图)则不需要颜色表,颜色表的长度由BITMAPINFOHEADER结构中biBitCount分量决定。对于biBitCount值为1的二值图像,每像素占1bit,图像中只有两种(如黑白)颜色,颜色表也就有21=2个表项,整个颜色表的大小为 2*siezof(RGBQUAD)=2x4=8个字节;对于biBitCount值为8的灰度图像,每像素占8bit,图像中有2^8=256 颜色,颜色表也就有256个表项,且每个表项的R、G、B分量相等,整个颜色表的大小为 个字节;而对于biBitCount=24的真彩色图像,由于每像素3个字节中分别代表了R、G、B三分量的值,此时不需要颜色表,因此真彩色图的BITMAPINFOHEADER结构后面直接就是位图数据。

第4部分是位图数据,即图像数据,其紧跟在位图文件头、位图信息头和颜色表(如果有颜色表的话)之后,记录了图像的每一个像素值。对于有颜色表的位图,位图数据就是该像素颜色在调色板中的索引值;对于真彩色图,位图数据就是实际的R、G、B值(三个分量的存储顺序是B、G、R)。下面分别就2色、16色、256色和真彩色位图的位图数据进行说明:

对于2色位图,用1位就可以表示该像素的颜色,所以1个字节能存储8个像素的颜色值。
对于16色位图,用4位可以表示一个像素的颜色。所以一个字节可以存储2个像素的颜色值。
对于256色位图,1个字节刚好存储1个像素的颜色值。
 
对于真彩色位图,3个字节才能表示1个像素的颜色值。

需要注意两点:

第一,图像格式规定一个扫描行所占的字节数必须是4的倍数,不足4的倍数则要对其进行扩充。假设图像的宽为biWidth个像素、每像素biBitCount个比特,其一个扫描行所占的真实字节数的计算公式如下:

DataSizePerLine = (biWidth * biBitCount /8+ 3) / 4*4
那么,不压缩情况下位图数据的大小(BITMAPINFOHEADER结构中的biSizeImage成员)计算如下:

biSizeImage = DataSizePerLine * biHeight
第二,一般来说,BMP文件的数据是从图像的左下角开始逐行扫描图像的,即从下到上、从左到右,将图像的像素值一一记录下来,因此图像坐标零点在图像左下角。

以下代码是C语言读写bitmap格式图片的几个函数,main()函数作为测试用。

为了兼容Linux 和windows平台用fopen、fread、fseek、fclose替换掉了open、read、lseek、close系列函数。

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
//#include "window.h"
 
/*bmp file header*/
typedef struct FileHeader
{
	unsigned short	bfType;
	unsigned int	bfSize;
	unsigned short	bfReserved1;
	unsigned short	bfReserved2;
	unsigned int	bfOffBits;
}__attribute__((packed))FileHeader;
 
/*bmp info header*/
typedef struct InfoHeader
{
	unsigned int	biSize;
	int				biWidth;
	int				biHeight;
	unsigned short	biPlanes;
	unsigned short	biBitCount;
	unsigned int	biCompression;
	unsigned int	biSizeImage;
	int				biXPelsPerMeter;
	int 			biYPelsPerMeter;
	unsigned int	biClrUsed;
	unsigned int	biClrImportant;
}__attribute__((packed))InfoHeader;
 
//we won't use it while BitCount=24
typedef struct tagRGBQUAD
{
	unsigned char	rgbBlue;
	unsigned char	rgbGreen;
	unsigned char	rgbRed;
	unsigned char	rgbReserved;
}RGBQUAD;
	
typedef struct
{
	unsigned char b;
	unsigned char g;
	unsigned char r;
}RGB_data;
 
/*for test global variable*/
/*maybe can not use this in the project*/
unsigned char 	*pBmpBuf,*pBmpBufOne,*pBmpBufTwo,*pBmpBufThree;
RGBQUAD 		*pColorTable;
int		bmpWidth,bmpWidthback,bmpWidthsky;
int		bmpHeight,bmpHeightback,bmpHeightsky;
int		biBitCount,biBitCountback,biBitCountsky;
 
char * readBmp(char *bmpName)
{
	FILE *fp = fopen(bmpName, "rb");
	//int fp;		/*maybe fd should be more comfortably*/
	//fp = open(bmpName, O_RDONLY);
	if (NULL == fp)
	{
		printf("There is no fp!!!\n");
		return 0;
	}
    FileHeader bmpFileHeader
	fread(&bmpFileHeader, sizeof(FileHeader), 1, fp);

	// fseek(fp, sizeof(FileHeader), SEEK_SET);
	//lseek(fp, sizeof(FileHeader), SEEK_SET);
	InfoHeader bmpInfo;
	fread(&bmpInfo, sizeof(InfoHeader), 1, fp);
	//read(fp, &head, sizeof(InfoHeader));
 
	bmpWidth = bmpInfo.biWidth;
	bmpHeight = bmpInfo.biHeight;
	biBitCount = bmpInfo.biBitCount;
 


	// 输出BMP文件的位图文件头的所有信息
	printf("位图文件头主要是对位图文件的一些描述:BMPFileHeader\n\n");
	printf("文件标识符 = 0X%X\n", bmpFileHeader.bfType);
	printf("BMP 文件大小 = %d 字节\n", bmpFileHeader.bfSize);
	printf("保留值1 = %d \n", bmpFileHeader.bfReserved1);
	printf("保留值2 = %d \n", bmpFileHeader.bfReserved2);
	printf("文件头的最后到图像数据位开始的偏移量 = %d 字节\n", bmpFileHeader.bfOffBits);
 
	// 输出BMP文件的位图信息头的所有信息
	printf("\n\n位图信息头主要是对位图图像方面信息的描述:BMPInfo\n\n");
	printf("信息头的大小 = %d 字节\n", bmpInfo.biSize);
	printf("位图的宽度 = %d \n", bmpInfo.biWidth);
	printf("位图的高度 = %d \n", bmpInfo.biHeight);
	printf("图像的位面数(位面数是调色板的数量,默认为1个调色板) = %d \n", bmpInfo.biPlanes); 
	printf("每个像素的位数 = %d 位\n", bmpInfo.biBitCount);
	printf("压缩类型 = %d \n", bmpInfo.biCompression);
	printf("图像的大小 = %d 字节\n", bmpInfo.biSizeImage);
	printf("水平分辨率 = %d \n", bmpInfo.biXPelsPerMeter);
	printf("垂直分辨率 = %d \n", bmpInfo.biYPelsPerMeter);
	printf("使用的色彩数 = %d \n", bmpInfo.biClrUsed);
	printf("重要的色彩数 = %d \n", bmpInfo.biClrImportant);
 
	printf("\n\n\n压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)");
 
	int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;
	if (biBitCount == 8)
	{
		//pColorTable=new RGBQUAD[256];
		pColorTable = (RGBQUAD *)malloc(sizeof(RGBQUAD) * 1024);
		fread(pColorTable, sizeof(RGBQUAD), 256, fp);
	}
 
	pBmpBuf = (unsigned char *)malloc(sizeof(unsigned char) * lineByte * bmpHeight);
	fread(pBmpBuf, 1, lineByte * bmpHeight, fp);
	fclose(fp);
	
	return pBmpBuf;
}
 
 
int saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable)
{
	if(imgBuf == NULL)
	{
		printf("imgBuf is NULL!!\n");
		return -1;
	}
 
	int colorTablesize = 0;
	if (biBitCount == 8)
	{
		colorTablesize=1024;
	}
	
	int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
 
	FILE *fp = fopen(bmpName, "wb");
	if (fp == NULL)
	{
		printf("fopen error...\n");
		return -1;
	}
	
	FileHeader fileHead;
	fileHead.bfType=0x4D42;
 
	fileHead.bfSize = sizeof(FileHeader) + sizeof(InfoHeader) + colorTablesize + lineByte * height;
	
	fileHead.bfReserved1 = 0;
	fileHead.bfReserved2 = 0;
 
	fileHead.bfOffBits = 54 + colorTablesize;
 
	fwrite(&fileHead, sizeof(FileHeader), 1, fp);
 
	InfoHeader infoHead;
	infoHead.biBitCount = biBitCount;
	infoHead.biClrImportant = 0;
	infoHead.biClrUsed = 0;
	infoHead.biCompression = 0;
	infoHead.biHeight = height;
	infoHead.biPlanes = 1;
	infoHead.biSize = 40;
	infoHead.biSizeImage = lineByte * height;
	infoHead.biWidth = width;
	infoHead.biXPelsPerMeter = 0;
	infoHead.biYPelsPerMeter = 0;
 
	fwrite(&infoHead, sizeof(InfoHeader), 1, fp);
 
	if (biBitCount == 8)
	{
		fwrite(pColorTable,sizeof(RGBQUAD),256,fp);
	}
	
	fwrite(imgBuf, height * lineByte, 1, fp);
 
	fclose(fp);
	
	return 0;
}
 
 
/* main function test program*/
#if 1
int main(int argc, char *argv[])
{
	char *readPath = argv[1];
	readBmp(readPath);
 
	printf("width = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);
 
	char writePath[] = "logo256copy.bmp";
	saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
 
	free(pBmpBuf);
	if (biBitCount == 8)
	{
		free(pColorTable);
	}
	
	return 0;
}
#endif
 
#if 0
extern int a1,b1,n;
extern int a[50],b[50];
 
//int reviseBitMap(void)
int main(int argc,char *argv[])
{
	int i,j;
	int x,y;
	int k;
 
	char readPathOne[] = "back.bmp";
	pBmpBufOne = readBmp(readPathOne);
	printf("width = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);
	bmpWidthback = bmpWidth;
	bmpHeightback = bmpHeight;
	biBitCountback = biBitCount;
	int lineByteback = (bmpWidthback * biBitCountback / 8 + 3) / 4 * 4;
 
	char readPathThree[] = "sky.bmp";
	pBmpBufThree = readBmp(readPathThree);
	printf("width = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);
	bmpWidthsky = bmpWidth;
	bmpHeightsky = bmpHeight;
	biBitCountsky = biBitCount;
	int lineBytesky = (bmpWidthsky * biBitCountsky / 8 + 3) / 4 * 4;
 
	char readPathTwo[] = "plane.bmp";
	pBmpBufTwo = readBmp(readPathTwo);
	printf("wdith = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);
	int lineByteplane = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;		
 
	if (biBitCount == 8)
	{
		for (i = 0; i < bmpHeight / 2; i++)
		{
			for (j = 0; j < bmpWidth / 2; j++)
			{
				*(pBmpBuf + i * lineByteplane + j) = 0;
			}
		}
	}
	else if (biBitCount == 24)
	{
		x = a[a1];
		y = b[b1];
		for (i = 0; i < bmpHeight; i++)
		{
			for(j=0;j<bmpWidth;j++)
			{
				for(k=0;k<3;k++)
				{
					*(pBmpBufOne+(x+i)*lineByteback+(y+j)*3+k) &= (*(pBmpBufThree+i*lineBytesky+j*3+k));
					*(pBmpBufOne+(x+i)*lineByteback+(y+j)*3+k) |= (*(pBmpBufTwo+i*lineByteplane+j*3+k));
					if (lineBytesky != lineByteplane)
					{
						printf("............................\n");
					}
				}
			}
		}
		char writePath[]="hncuduplicate.bmp";
         saveBmp(writePath,pBmpBufOne,bmpWidthback,bmpHeightback,biBitCountback,pColorTable);
	}
	
	free(pBmpBufOne);
	free(pBmpBufTwo);
	free(pBmpBufThree);
	
	if (biBitCount == 8)
	{
		free(pColorTable);
	}
	
	return 0;
}
 
#endif

————————————————
版权声明:本文为CSDN博主「super_bert」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/embedded_sky/article/details/42042741

#include <stdio.h>
#include <stdlib.h>
 
/* 定义WORD为两个字节的类型 */
typedef unsigned short WORD;
/* 定义DWORD为四个字节的类型 */
typedef unsigned long DWORD;
 
/* 位图文件头主要是对位图文件的一些描述 位图信息头主要是对位图图像方面信息的描述 */
/*************************** 位图标准信息(54字节) ******************************************/
/* 位图文件头 (位图头的字节数 = 位图文件字节数 - 位图图像数据字节数)*/
typedef struct FileHeader
{
	unsigned short	bfType;
	unsigned int	bfSize;
	unsigned short	bfReserved1;
	unsigned short	bfReserved2;
	unsigned int	bfOffBits;
}__attribute__((packed))FileHeader;
 
/*bmp info header*/
typedef struct InfoHeader
{
	unsigned int	biSize;
	int				biWidth;
	int				biHeight;
	unsigned short	biPlanes;
	unsigned short	biBitCount;
	unsigned int	biCompression;
	unsigned int	biSizeImage;
	int				biXPelsPerMeter;
	int 			biYPelsPerMeter;
	unsigned int	biClrUsed;
	unsigned int	biClrImportant;
}__attribute__((packed))InfoHeader;
 
typedef struct BMP_FILE_HEADER
{
	WORD bType;      // 文件标识符 
	DWORD bSize;     // 文件的大小 
	WORD bReserved1; // 保留值,必须设置为0  
	WORD bReserved2; // 保留值,必须设置为0 
	DWORD bOffset;   // 文件头的最后到图像数据位开始的偏移量 
} __attribute__((packed))BMPFILEHEADER;     // 14 字节
 
/* 位图信息头 */
typedef struct BMP_INFO
{
	DWORD bInfoSize;            // 信息头的大小   
	DWORD bWidth;               // 图像的宽度     
	DWORD bHeight;              // 图像的高度     
	WORD bPlanes;               // 图像的位面数   
	WORD bBitCount;             // 每个像素的位数 
	DWORD bCompression;         // 压缩类型 
	DWORD bmpImageSize;         // 图像的大小,以字节为单位 
	DWORD bXPelsPerMeter;       // 水平分辨率 
	DWORD bYPelsPerMeter;       // 垂直分辨率 
	DWORD bClrUsed;             // 使用的色彩数 
	DWORD bClrImportant;        // 重要的颜色数 
}__attribute__((packed))BMPINF;            // 40 字节
 
/* 彩色表:调色板 */
typedef struct RGB_QUAD 
{
	WORD rgbBlue;     // 蓝色强度 
	WORD rgbGreen;    // 绿色强度 
	WORD rgbRed;      // 红色强度 
	WORD rgbReversed; // 保留值 
} RGBQUAD;
 
int main(char argc, const char *argv[])
{
	int i = sizeof(BMPFILEHEADER);
	int j = sizeof(long);
	FILE *fp;                     // 定义一个文件指针
	BMPFILEHEADER bmpFileHeader;  // 定义一个 BMP 文件头的结构体
	BMPINF bmpInfo;               // 定义一个 BMP 文件信息结构体 
 
 
	// "rb" 只读打开一个二进制文件,只允许读数据。'b'指的是让这个库函数以二进制形式打开此文件。
	// 读取失败会返回空指针,读取成功后,fp 会指向一块具有 bmp 属性的内存,我们可以对这块内存开始操作
	if((fp = fopen(argv[1], "rb")) == NULL) // fp = 0x00426aa0
	{
		printf("Cann't open the file!\n");
		return 0;
	}
 
	// 让 fp 指向 bmp 文件的开始 
	// 第 2 个参数是偏移量 第三个参数是文件起始地址 所以此函数执行成功后文件指针会指向文件的开始
	fseek(fp, 0, SEEK_SET);                            // fp = 0x00426aa0
 
	// 读取文件信息
	/*
		参数1: 读出数据的存放缓冲区
		参数2: 读取多少个字节的数据
		参数3: 读取几包这样的数据
		参数4: 文件指针(源数据)
	*/
	fread(&bmpFileHeader, sizeof(BMPFILEHEADER), 1, fp); 
	
	fread(&bmpInfo, sizeof(bmpInfo), 1, fp);
 
 
	// 输出BMP文件的位图文件头的所有信息
	printf("位图文件头主要是对位图文件的一些描述:BMPFileHeader\n\n");
	printf("文件标识符 = 0X%X\n", bmpFileHeader.bType);
	printf("BMP 文件大小 = %d 字节\n", bmpFileHeader.bSize);
	printf("保留值1 = %d \n", bmpFileHeader.bReserved1);
	printf("保留值2 = %d \n", bmpFileHeader.bReserved2);
	printf("文件头的最后到图像数据位开始的偏移量 = %d 字节\n", bmpFileHeader.bOffset);
 
	// 输出BMP文件的位图信息头的所有信息
	printf("\n\n位图信息头主要是对位图图像方面信息的描述:BMPInfo\n\n");
	printf("信息头的大小 = %d 字节\n", bmpInfo.bInfoSize);
	printf("位图的高度 = %d \n", bmpInfo.bHeight);
	printf("位图的宽度 = %d \n", bmpInfo.bWidth);
	printf("图像的位面数(位面数是调色板的数量,默认为1个调色板) = %d \n", bmpInfo.bPlanes); 
	printf("每个像素的位数 = %d 位\n", bmpInfo.bBitCount);
	printf("压缩类型 = %d \n", bmpInfo.bCompression);
	printf("图像的大小 = %d 字节\n", bmpInfo.bmpImageSize);
	printf("水平分辨率 = %d \n", bmpInfo.bXPelsPerMeter);
	printf("垂直分辨率 = %d \n", bmpInfo.bYPelsPerMeter);
	printf("使用的色彩数 = %d \n", bmpInfo.bClrUsed);
	printf("重要的色彩数 = %d \n", bmpInfo.bClrImportant);
 
	printf("\n\n\n压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)");
 
	fclose(fp);
 
	while(1);
 
	return 0;
}

————————————————
版权声明:本文为CSDN博主「技术先生」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weiaipan1314/article/details/51753288

`