精华内容
下载资源
问答
  • 如何在WIN-TC中或TC++3.0中把一张BMP格式的图片显示出来? 下面的是编程实例>随书光盘上的代码,我在TC2.0下编译通过. 它是利用了抖动技术显示了8bit和24bit的位图(也就是256色和16M色位图,应该能满足你的需要. 不过,...
  • C语言读取bmp图像做简单显示

    千次阅读 2020-10-20 19:46:00
    C语言读取bmp图像信息做简单显示bmp文件格式读取bmp文件信息展示 bmp文件格式 bmp文件大体上分为四个部分: bmp文件构成 位图文件头BITMAPFILEHEADER 位图信息头BITMAPINFOHEADER 调色板Palette ...

    C语言读取bmp图像并做简单显示)

    bmp文件格式

    bmp文件大体上分为四个部分:

    bmp文件构成
    位图文件头BITMAPFILEHEADER
    位图信息头BITMAPINFOHEADER
    调色板Palette
    实际的位图数据ImageDate

    第一部分为位图文件头,位图文件头长度固定,为14个字节。

    typdef struct {
    WORD bfType;    //指定文件类型,必须是0x424d,即”BM”
    DWORD bfSize;   //指定文件大小
    WORD bfReserved1; //保留字
    WORD bfReserved2; //保留字
    DWORD bfOffBits; //为文件头到实际的位图数据的偏移字节数,即上图前三部分和
    }bitmapFileHeader;
    

    第二部分为位图信息头,这个结构的长度也是固定的,为40个字节。

    typedef struct {
    	DWORD biSize;  //指这个机构的长度,为40
    	LONG biWidth;  //指定图像的宽度,单位是像素
    	LONG biHeight;  //指定图像的高度,单位是像素
    	WORD biPlanes;  //平面数,必须为1,不用考虑 
    	WORD biBitCount; //指定表示颜色是要用到的位数,常用值为1(黑白二色图),
    	//4(16色图),8(256色),24(真彩色图)(新的.bmp格式支持32位色)
    	DWORD biCompression; //指定位图是否压缩,有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFILELDS
    	DWORD biSizeImage; //指定实际的位图数据占用的字节数,其实也可以从以下的公式计算出来:
    	//biSizeImage=bitWidth’*biHeight,bitWidth‘为大于等于bitWidth的4的倍数
    	LONG biXPelsPerMeter; //指定设备的水平分辨率,单位是每米的图像个数
    	LONG biYPelsPerMeter; //同上,垂直分辨率
    	DWORD biClrUsed; //指定本图像实际用到的颜色数,如果该值为零,则用到的颜色数为2^biBitCount
    	DWORD biClrImportant;// 指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的
    }bitmapInfoHeader;
    

    第三部分为调色板(真彩图像不需要调色版,bitmapInfoHeader后直接是数据)调色板实际是一个数组,共有biClrUsed个元素(如果该值为0,则有2^biBitCount个元素),数组中每个元素的类型是一个RGBQUAD结构,占四个字节,其定义如下:

    typedef struct {
    	BYTE rgbBlue; //该颜色的蓝色分量
    	BYTE rgbGreen; //该颜色的绿色分量
    	BYTE rgbRed; //该颜色的红色分量
    	BYTE rgbReserved; //保留值
    } RGBQUAD;
    

    第四部分为实际图像数据
    对于用到调色版的位图,图像数据就是该像素颜在调色板中的索引值。对于真彩图,图像数据就是实际的R、G、B值。

    需要注意两点:
    (1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。
    (2)一般来说,.bmp文件的数据是从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个像素,然后是左边第二个像素……接下来是倒数第二行左边第一个像素,左边第二个像素……依次类推 ,最后得到的是最上面一行的最右一个像素。

    读取bmp文件信息并展示

    以24位bmp图像为例
    在这里插入图片描述

    定义数据结构:

    typedef struct {
    	unsigned char bfType[2];
    	unsigned long bfSize;
    	unsigned short bfReserved1;
    	unsigned short bfReserved2;
    	unsigned long bfOffBits;
    }bitmapFileHeader;
    
    typedef struct {
    	unsigned long biSize;
    	long biWidth;
    	long biHeight;
    	unsigned short biPlanes;
    	unsigned short biBitCount;
    	unsigned long biCompression;
    	unsigned long biSizeImage;
    	long biXPixPerMeter;
    	long biYPixPerMeter;
    	unsigned long biClrused;
    	unsigned long biClrImportant;
    }bitmapInfoHeader;
    

    读入文件头:

    //仅展示,不用于实验
    int readFileHeader(FILE *fp,bitmapFileHeader*bfHeader){
    	fseek(fp,0,SEEK_SET);
    	fread(bfHeader,sizeof(bitmapFileHeader),1,fp);
    	/*
    	int i;	
    	printf("读入文件头:");
    	char*p=(char*)bfHeader;
    	for(i=0;i<sizeof(bitmapFileHeader);i++,p++){
    		printf("%02x ",*p);
    	}
    	printf("\n");
    	printf("文件头信息如下:\n");
    	printf("文件类型:%c%c\n",bfHeader->bfType[0],bfHeader->bfType[1]);
    	printf("文件大小: %d 字节\n",bfHeader->bfSize);
    	printf("位图数据偏移:%d\n",bfHeader->bfOffBits);
    	*/
    	return 0;
    }
    

    读信息头:

    //仅展示,不用于实验
    int readInfoHeader(FILE*fp,bitmapInfoHeader*biHeader){
    	fseek(fp,14,SEEK_SET);
    	fread(biHeader,sizeof(bitmapInfoHeader),1,fp);
    
    	/*
    	int i;
    	printf("读入位图信息头:\n");
    	char*p=(char*)biHeader;
    	for(i=0;i<sizeof(bitmapInfoHeader);i++,p++){
    		printf("%02x ",*p);
    		if(i%20==0&&i!=0)
    			printf("\n");
    	}
    	printf("\n");
    	printf("位图信息头信息如下:\n");
    	printf("bmp图像宽度:%d\n",biHeader->biWidth);
    	printf("bmp图像高度:%d\n",biHeader->biHeight);
    	printf("bmp图像颜色位数: %d\n",biHeader->biBitCount);
    	printf("bmp图像实际数据占用字节:%d\n",biHeader->biSizeImage);
    	*/
    	return 0;
    }
    

    读入bmp图像数据,并展示

    #include<stdio.h>
    #include<stdlib.h>
    #include<malloc.h>
    
    #pragma pack(1)  //这个选项挺重要,不加的话程序就会报错,原因参考
    //https://blog.csdn.net/qq_44310495/article/details/109181857
    
    typedef struct {
    	unsigned char bfType[2];
    	unsigned long bfSize;
    	unsigned short bfReserved1;
    	unsigned short bfReserved2;
    	unsigned long bfOffBits;
    }bitmapFileHeader;
    
    typedef struct {
    	unsigned long biSize;
    	long biWidth;
    	long biHeight;
    	unsigned short biPlanes;
    	unsigned short biBitCount;
    	unsigned long biCompression;
    	unsigned long biSizeImage;
    	long biXPixPerMeter;
    	long biYPixPerMeter;
    	unsigned long biClrused;
    	unsigned long biClrImportant;
    }bitmapInfoHeader;
    
    int main(){
    	FILE *fp,*fp_txt;
    	if((fp=fopen("d:\Temp\\skull.bmp","rb"))==NULL){
    		perror("can not open file!");
    		return -1;
    	}
    	
    	bitmapFileHeader bfHeader;
    	fread(&bfHeader,14,1,fp);
    	bitmapInfoHeader biHeader;
    	fread(&biHeader,40,1,fp);
    
    	int imSize=biHeader.biSizeImage;
    	int width=biHeader.biWidth;
    	int height=biHeader.biHeight;
    	int bitCount=biHeader.biBitCount;
    
    	fseek(fp,bfHeader.bfOffBits,SEEK_SET);
    	unsigned char*imageData=(unsigned char*)malloc(imSize*sizeof(unsigned char));
    	fread(imageData,imSize*sizeof(unsigned char),1,fp);
    
    	//图像为24位图像
    	int lineBytes=(bitCount*width+31)/32*4;//得到图像数据的bitwidth'
    	int i,j;
    	int r,g,b;
    	for(i=0;i<height;i++){ //对于每一行
    		for(j=0;j<width*3;j++){ //对于每一列
    			r=*(imageData+lineBytes*(height-1-i)+j); //从最后一行往上读
    			j++;
    			g=*(imageData+lineBytes*(height-1-i)+j);
    			j++;
    			b=*(imageData+lineBytes*(height-1-i)+j);
    			if(r==255&&g==255&&b==255) //模拟二值图像展示
    				printf("  ");
    			else
    				printf(".$");
    		}
    		printf("\n");
    	}
    	
    	free(imageData);
    	fclose(fp);
    	getchar();
    	return 0;
    }
    

    代码效果展示:
    在这里插入图片描述

    展开全文
  • c语言读取并bmp图像1如何在WIN-TC中或TC++3.0中把一张BMP格式的图片显示出来?下面的是<>随书光盘上的代码,我在TC2.0下编译通过. 它是利用了抖动技术显示了8bit和24bit的位图(也就是256色和16M色位图),应该...

    用c语言读取并示bmp图像1

    如何在WIN-TC中或TC++3.0中把一张BMP格式的图片显示出来?

    下面的是<>随书光盘上的代码,我在TC2.0下编译通过. 它是利用了抖动技术显示了8bit和24bit的位图(也就是256色和16M色位图),应该能满足你的需要. 不过,我想问下,你老师教过抖动显示吗? #include #include #include #include #define NoError 0 #define ErrorFileOpen 1 #define ErrorFileType 2 #define ErrorImageColor 3 typedef struct tagBITMAPFILEHEADER { unsigned int bfType; unsigned long bfSize; unsigned int bfReserved1; unsigned int bfReserved2; unsigned long bfoffBits; }BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER { unsigned long biSize; unsigned long biWidth; unsigned long biHeight; unsigned int biPlanes; unsigned int biBitCount; unsigned long biCompression; unsigned long biSizeImage; unsigned long biXPelsPerMeter; unsigned long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } BITMAPINFOHEADER; typedef struct tagRGBQUAD { unsigned char rgbBlue; unsigned char rgbGreen; unsigned char rgbRed; unsigned char rgbReserved; } RGBQUAD; unsigned char PalReg[17]= { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; unsigned char StandardPal[48]= { 0, 0, 0, 32, 0, 0, 0,32, 0, 32,32, 0, 0, 0,32, 32, 0,32, 0,32,32, 32,32, 32, 48, 48,48, 63, 0, 0, 0,63, 0, 63,63, 0, 0, 0,63, 63, 0,63, 0,63,63, 63,63,63, }; unsigned char LightnessMatrix [16][16]= { { 0,235,59,219,15,231,55,215,2,232,56,217,12,229,52,213}, {128,64,187,123,143,79,183,119,130,66,184,120,140,76,180,116}, {33,192,16,251,47,207,31,247,34,194,18,248,44,204,28,244}, {161,97,144,80,175,111,159,95,162,98,146,82,172,108,156,92}, {8,225,48,208,5,239,63,223,10,226,50,210,6,236,60,220}, {136,72,176,112,133,69,191,127,138,74,178,114,134,70,188,124}, {41,200,24,240,36,197,20,255,42,202,26,242,38,198,22,252}, {169,105,152,88,164,100,148,84,170,106,154,90,166,102,150,86}, {3,233,57,216,13,228,53,212,1,234,58,218,14,230,54,214}, {131,67,185,121,141,77,181,117,129,65,186,122,142,78,182,118}, {35,195,19,249,45,205,29,245,32,193,17,250,46,206,30,246},

    展开全文
  • BMP图片,是Bitmap(位图)的简称,它是windows显示图片的基本格式。在windows下,任何格式的图片文件(包括视频播放)都要转化为位图才能显示出来。各种格式的图片文件也都是在位图格式的基础上采用不同的压缩算法...

    BMP图片格式

    BMP图片,是Bitmap(位图)的简称,它是windows显示图片的基本格式。在windows下,任何格式的图片文件(包括视频播放)都要转化为位图才能显示出来。各种格式的图片文件也都是在位图格式的基础上采用不同的压缩算法生成的。

    位图文件主要分为如下3个部分:

    块名称 对应Windows结构体定义 大小(Byte)
    文件信息头 BITMAPFILEHEADER 14
    位图信息头 BITMAPINFOHEADER 40
    RGB颜色阵列 BYTE* 由图像长宽尺寸决定

    文件信息头结构体定义如下:

    typedef struct BMP_FILE_HEADER
    {
    	//WORD bType;      // 文件标识符,这里为0x4d42 
    	DWORD bSize;     // 文件的大小 
    	WORD bReserved1; // 保留值,必须设置为0  
    	WORD bReserved2; // 保留值,必须设置为0 
    	DWORD bOffset;  // 文件头的最后到图像数据位开始的偏移量,
    					//说明从文件头开始到实际的图象数据之间的字节的偏移量
    					//因为位图信息头和调色板的长度会根据不同情况而变化
    					//所以你可以用这个偏移值迅速的从文件中读取到位数据
    } BMPFILEHEADER;    // 14 字节

     

    bType 说明文件的类型,该值必需是0x4D42(十六进制ASCII码4D代表“B”,42代表“M”),也就是字符'BM'
    bSize 说明该位图文件的大小,用字节为单位
    bReserved1 保留,必须设置为0
    bfReserved2 保留,必须设置为0
    bOffBits 说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据

    位图信息头结构体定义如下:

    typedef struct BMP_INFO
    {
    	DWORD bInfoSize;            // 信息头的大小   
    	DWORD bWidth;               // 图像的宽度     
    	DWORD bHeight;              // 图像的高度,如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。  
    	WORD bPlanes;               // 图像的位面数,其值将总是被设为1 
    	WORD bBitCount;             // 每个像素的位数,这里为 24位
    	DWORD bCompression;         // 压缩类型 
    	DWORD bmpImageSize;         // 图像的大小,以字节为单位 
    	DWORD bXPelsPerMeter;       // 水平分辨率 
    	DWORD bYPelsPerMeter;       // 垂直分辨率 
    	DWORD bClrUsed;             // 位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
    	DWORD bClrImportant;        // 对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要
    } BMPINF;            // 40 字节

     

    bInfoSize 说明BITMAPINFOHEADER结构所需要的字数。
    bWidth 说明图象的宽度,以象素为单位。
    bHeight 说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是说,高度值是一个正数。
    bPlanes 为目标设备说明位面数,其值将总是被设为1。
    BitCount 说明比特数/象素,其值为1、4、8、16、24、或32。我们平时用到的图像绝大部分是24位和32位的
    bCompression 说明图象数据压缩的类型,同样我们只讨论没有压缩的类型:BI_RGB。
    bmpImageSize 说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0。
    bXPelsPerMeter 说明水平分辨率,用象素/米表示。
    bYPelsPerMeter 说明垂直分辨率,用象素/米表示。
    bClrUsed 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
    bClrImportant 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

    RGB颜色通道:

     在windows下面,RGB颜色矩阵的存储格式是BGR。颜色数据区记录着每个像素对应的颜色值。其记录方式随着颜色模式的不同而不同。

    BitCount=1
        表示位图最多有两种颜色,缺省情况下是黑色和白色,你也可以自己定义这两种颜色。图像信息头调色板中将有两个调色板项,称为索引0和索引1。图象数据阵列中的每一位表示一个象素。如果一个位是0,显示时就使用索引0的RGB值,如果位是1,则使用索引1的RGB值。
    BitCount=4
        表示位图最多有16种颜色。每个象素用4位表示,并用这4位作为彩色表的表项来查找该象素的颜色。例如,如果位图中的第一个字节为0x1F,它表示有两个象素,第一象素的颜色就在彩色表的第2表项中查找,而第二个象素的颜色就在彩色表的第16表项中查找。此时,调色板中缺省情况下会有16个RGB项。对应于索引0到索引15。
    BitCount=8
        表示位图最多有256种颜色。每个象素用8位表示,并用这8位作为彩色表的表项来查找该象素的颜色。例如,如果位图中的第一个字节为0x1F,这个象素的颜色就在彩色表的第32表项中查找。此时,缺省情况下,调色板中会有256个RGB项,对应于索引0到索引255。

    BitCount=16
        表示位图最多有65536种颜色。每个色素用16位(2个字节)表示。这种格式叫作高彩色,或叫增强型16位色,或64K色。它的情况比较复杂。

    当 biCompression成员的值是BI_RGB时,它没有调色板。16位中,最低的5位表示蓝色分量,中间的5位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0。这种格式也被称作555。

    当biCompression成员的值是BI_BITFIELDS,那么情况就复杂了,首先是原来调色板的位置被三个DWORD变量占据,称为红、绿、蓝掩码。分别用于描述红、绿、蓝分量在16位中所占的位置。在Windows95(或98)中,系统可接受两种格式的位域:555和565,在555格式下,红、绿、蓝的掩码分别是:0x7C00、0x03E0、0x001F,而在565格式下,它们则分别为:0xF800、0x07E0、0x001F。你在读取一个像素之后,可以分别用掩码“与”上像素值,从而提取出想要的颜色分量(当然还要再经过适当的左右移操作)。在NT系统中,则没有格式限制,只不过要求掩码之间不能有重叠。(注:这种格式的图像使用起来是比较麻烦的,不过因为它的显示效果接近于真彩,而图像数据又比真彩图像小的多,所以,它更多的被用于游戏软件)。

    BitCount=24
        表示位图最多有2的24次方,大约1670万种颜色。这种位图没有调色板(bmiColors成员尺寸为0),在位数组中,每3个字节代表一个象素,分别对应于颜色R、G、B。
    BitCount=32
        表示位图最多有2的32次方种颜色。这种位图的结构与16位位图结构非常类似

    当biCompression成员的值是BI_RGB时,它也没有调色板,32位中有24位用于存放RGB值,顺序是:最高位—保留,红8位、绿8位、蓝8位。这种格式也被成为888。

    当biCompression成员的值是BI_BITFIELDS时,原来调色板的位置将被三个DWORD变量占据,成为红、绿、蓝掩码,分别用于描述红、绿、蓝分量在32位中所占的位置。在Windows95(or 98)中,系统只接受888格式,也就是说三个掩码的值将只能是:0xFF0000、0xFF00、0xFF。而在NT系统中,你只要注意使掩码之间不产生重叠就行。(注:这种图像格式比较规整,因为它是DWORD对齐的,所以在内存中进行图像处理时可进行汇编级的代码优化(简单))。

    注意:
    BMP图像数据区在存储时,2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。
    对于未压缩的图像信息区的大小。除了真彩色模式外,其余的均大于或等于数据信息的大小。这是为什么呢?原因有两个:
    1.BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,设显示模式为16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。
    2.为了显示的方便,除了真彩色外,其他的每种颜色模式的行字节数要用数据“00”补齐为4的整数倍。如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。
     

    24位BMP图片

    由上面BMP图片格式可知,24位BMP图像称为真彩色图像,这种位图没有调色板,并且每三个字节代表一个像素,分别对应于R、G、B。对于24位BMP图片,大小计算公式为:图像宽度*图像高度*3字节。

    注意:每次读取图片都是三个字节三个字节地读取(分别为BGR),对于图像宽度不是4的整数倍的图片,读取像素的时候需要在读取每一行像素的时候,跳过最后所补的0。计算跳过的0的个数公式如下:4 - ((width * 3 )%4),其中width是图像的宽度。

    具体实现代码细节如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include<malloc.h>
    #include <string>
    #include <iostream>
    typedef unsigned char  BYTE;//一字节
    typedef unsigned short WORD;//两字节
    typedef unsigned long DWORD;//四字节
    typedef long LONG;
    /* 位图文件头主要是对位图文件的一些描述 位图信息头主要是对位图图像方面信息的描述 */
    
    /*************************** 位图标准信息(54字节) ******************************************/
    /* 位图文件头 (位图头的字节数 = 位图文件字节数 - 位图图像数据字节数)*/
    typedef struct BMP_FILE_HEADER
    {
    	//WORD bType;      // 文件标识符,这里为0x4d42 
    	DWORD bSize;     // 文件的大小 
    	WORD bReserved1; // 保留值,必须设置为0  
    	WORD bReserved2; // 保留值,必须设置为0 
    	DWORD bOffset;  // 文件头的最后到图像数据位开始的偏移量,
    					//说明从文件头开始到实际的图象数据之间的字节的偏移量
    					//因为位图信息头和调色板的长度会根据不同情况而变化
    					//所以你可以用这个偏移值迅速的从文件中读取到位数据
    } BMPFILEHEADER;    // 14 字节
    					/* 位图信息头 */
    typedef struct BMP_INFO
    {
    	DWORD bInfoSize;            // 信息头的大小   
    	DWORD bWidth;               // 图像的宽度     
    	DWORD bHeight;              // 图像的高度,如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。  
    	WORD bPlanes;               // 图像的位面数,其值将总是被设为1 
    	WORD bBitCount;             // 每个像素的位数,这里为 24位
    	DWORD bCompression;         // 压缩类型 
    	DWORD bmpImageSize;         // 图像的大小,以字节为单位 
    	DWORD bXPelsPerMeter;       // 水平分辨率 
    	DWORD bYPelsPerMeter;       // 垂直分辨率 
    	DWORD bClrUsed;             // 位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
    	DWORD bClrImportant;        // 对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要
    } BMPINF;            // 40 字节
    
    					 /* 彩色表:调色板 */
    					 // 24位的真彩图不需要调色板
    typedef struct RGB_QUAD
    {
    	WORD rgbBlue;     // 蓝色强度 
    	WORD rgbGreen;    // 绿色强度 
    	WORD rgbRed;      // 红色强度 
    	WORD rgbReversed; // 保留值 
    } RGBQUAD;
    
    //位图数据:这部分的内容根据BMP位图使用的位数不同而不同
    //在24位真彩图中,直接使用RGB
    //其他的小于24位的则使用调色板中颜色的索引值
    typedef struct tagIMAGEDATA
    {
    	BYTE blue;
    	BYTE green;
    	BYTE red;
    }IMAGEDATA;
    
    typedef struct {
    	int width;
    	int height;
    	
    	BYTE  *imageData;
    
    }IMAGE;
    
    //函数声明
    void rotation90();
    void rotation270();
    void rotation180();
    WORD bType;//文件标识符,BMP文件为0x4d42,这里单独读取
    BMPFILEHEADER bmpFileHeader;  // 定义一个 BMP 文件头的结构体
    BMPINF bmpInfo;               // 定义一个 BMP 文件信息结构体 	
    FILE *fp;                     // 定义一个文件指针
    IMAGE *bmpImg = (IMAGE*)malloc(sizeof(IMAGE));				//定义一个bmp指针,并分配地址空间
    BYTE  pixVal;				//定义一个一字节的数据
    
    int width,height;
    int offset;
    int i, j, k;
    
    
    int main()
    {
    
    	if ((fp = fopen("pic.bmp", "rb")) == NULL) // fp = 0x00426aa0
    	{
    		printf("Cann't open the file!\n");
    		return 0;
    	}
    	// 让 fp 指向 bmp 文件的开始 
    	// 第 2 个参数是偏移量 第三个参数是文件起始地址 所以此函数执行成功后文件指针会指向文件的开始
    	fseek(fp, 0, SEEK_SET);
    
    	fread(&bType, sizeof(WORD), 1, fp);//读取文件类型
    
    	if (bType != 0x4d42)
    	{
    		printf("不是bmp文件");
    		return 0;
    	}
    
    	fread(&bmpFileHeader, sizeof(BMPFILEHEADER), 1, fp);
    	fread(&bmpInfo, sizeof(BMPINF), 1, fp);
    
    	/*
    	// 输出BMP文件的位图文件头的所有信息
    	printf("位图文件头主要是对位图文件的一些描述:BMPFileHeader\n\n");
    	printf("文件标识符 = 0X%X\n", 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);
    	*/
    	width = bmpInfo.bWidth;
    	height = bmpInfo.bHeight;
    
    	bmpImg->width = width;
    	bmpImg->height = height;
    	bmpImg->imageData = (BYTE*)malloc(sizeof(BYTE)*width*height*3);
    
    	//如果行的字节数不是4的整数倍,则进行如下处理
    	offset = (3 * 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(BYTE), 1, fp);
    				bmpImg->imageData[i * width * 3 + j * 3 + k] = pixVal;
    			}
    		}
    		if (offset != 0)
    		{
    			for (j = 0; j < offset; j++)
    			{
    				fread(&pixVal, sizeof(BYTE), 1, fp);
    			}
    		}
    	}
    
    	//输出数据
    	//将原始图片输出
    	/*
    	for (i = 0; i<height; i++)
    	{
    		for (j = 0; j<width; j++)
    		{
    			pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3 + 1 ];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3 + 2 ];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    		}
    
    		if (offset != 0)
    		{
    			for (j = 0; j<offset; j++)
    			{
    				pixVal = 0;
    				fwrite(&pixVal, sizeof(BYTE), 1, pFile); 
    			}
    		}
    	}
    	*/
    	//rotation90();
    	rotation180();
    	//rotation270();
    	fclose(fp);
    	return 0;
    
    }
    void rotation180()
    {
    	//旋转180度
    	FILE *pFile;
    	pFile = fopen("D:\\C++-work\\rotate180.bmp", "wb");
    	if (!pFile)
    	{
    		printf("读取文件失败");
    	}
    	int step = bmpImg->width * 3;
    	offset = step % 4;
    
    	if (offset != 0)
    	{
    	step += 4 - offset;
    	offset = 4 - offset;
    	}
    
    	fwrite(&bType, sizeof(WORD), 1, pFile);
    	fwrite(&bmpFileHeader, sizeof(BMPFILEHEADER), 1, pFile);
    	fwrite(&bmpInfo, sizeof(BMPINF), 1, pFile);
    
    	for (i = height-1; i>-1; i--)
    	{
    		for (j = width-1; j>-1; j--)
    	{
    			pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3 + 1];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3 + 2];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    	}
    
    	if (offset != 0)
    	{
    		for (j = 0; j<offset; j++)
    		{
    			pixVal = 0;
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    		}
    	}
    	}
    	fclose(pFile);
    	
    }
    void rotation90()
    {
    	FILE *pFile;
    	pFile = fopen("D:\\C++-work\\rotate90.bmp", "wb");
    	if (!pFile)
    	{
    		printf("读取文件失败");
    	}
    	
    	BMPFILEHEADER new_bmpFileHeader;  // 定义一个 BMP 文件头的结构体
    	BMPINF new_bmpInfo;               // 定义一个 BMP 文件信息结构体 
    
    	int new_w = bmpInfo.bHeight;
    	int new_h = bmpInfo.bWidth;
    
    	int step = new_w * 3;
    	int offset = step % 4;
    	if (offset != 0)
    	{
    		step += 4 - offset;
    		offset = 4 - offset;
    	}
    	new_bmpFileHeader.bSize = (DWORD)(step * new_h + sizeof(WORD) + sizeof(BMPFILEHEADER) + sizeof(BMPINF));
    	new_bmpFileHeader.bReserved1 = bmpFileHeader.bReserved1;
    	new_bmpFileHeader.bReserved2 = bmpFileHeader.bReserved2;
    	new_bmpFileHeader.bOffset = bmpFileHeader.bOffset;
    	new_bmpInfo.bBitCount = bmpInfo.bBitCount;
    	new_bmpInfo.bClrImportant = bmpInfo.bClrImportant;
    	new_bmpInfo.bClrUsed = bmpInfo.bClrUsed;
    	new_bmpInfo.bCompression = bmpInfo.bCompression;
    	new_bmpInfo.bHeight = bmpInfo.bWidth;
    	new_bmpInfo.bWidth = bmpInfo.bHeight;
    	new_bmpInfo.bInfoSize = bmpInfo.bInfoSize;
    	new_bmpInfo.bmpImageSize = (DWORD)(step * new_h);
    	new_bmpInfo.bPlanes = bmpInfo.bPlanes;
    	new_bmpInfo.bXPelsPerMeter = bmpInfo.bXPelsPerMeter;
    	new_bmpInfo.bYPelsPerMeter = bmpInfo.bYPelsPerMeter;
    
    	fwrite(&bType, sizeof(WORD), 1, pFile);
    	fwrite(&new_bmpFileHeader, sizeof(BMPFILEHEADER), 1, pFile);
    	fwrite(&new_bmpInfo, sizeof(BMPINF), 1, pFile);
    
    	//旋转90度
    	for (i = width-1; i>-1; i--)
    	{
    		for (j = 0; j<height; j++)
    		{
    			pixVal = bmpImg->imageData[j*width * 3 + i * 3];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[j*width * 3 + i * 3 + 1];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[j*width * 3 + i * 3 + 2];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    		}
    
    		if (offset != 0)
    		{
    			for (j = 0; j<offset; j++)
    			{
    				pixVal = 0;
    				fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			}
    		}
    	}
    
    }
    void rotation270()
    {
    	FILE *pFile;
    	pFile = fopen("D:\\C++-work\\rotate270.bmp", "wb");
    	if (!pFile)
    	{
    		printf("读取文件失败");
    	}
    
    	BMPFILEHEADER new_bmpFileHeader;  // 定义一个 BMP 文件头的结构体
    	BMPINF new_bmpInfo;               // 定义一个 BMP 文件信息结构体 
    
    	int new_w = bmpInfo.bHeight;
    	int new_h = bmpInfo.bWidth;
    
    	int step = new_w * 3;
    	int offset = step % 4;
    	if (offset != 0)
    	{
    		step += 4 - offset;
    		offset = 4 - offset;
    	}
    	new_bmpFileHeader.bSize = (DWORD)(step * new_h + sizeof(WORD) + sizeof(BMPFILEHEADER) + sizeof(BMPINF));
    	new_bmpFileHeader.bReserved1 = bmpFileHeader.bReserved1;
    	new_bmpFileHeader.bReserved2 = bmpFileHeader.bReserved2;
    	new_bmpFileHeader.bOffset = bmpFileHeader.bOffset;
    	new_bmpInfo.bBitCount = bmpInfo.bBitCount;
    	new_bmpInfo.bClrImportant = bmpInfo.bClrImportant;
    	new_bmpInfo.bClrUsed = bmpInfo.bClrUsed;
    	new_bmpInfo.bCompression = bmpInfo.bCompression;
    	new_bmpInfo.bHeight = bmpInfo.bWidth;
    	new_bmpInfo.bWidth = bmpInfo.bHeight;
    	new_bmpInfo.bInfoSize = bmpInfo.bInfoSize;
    	new_bmpInfo.bmpImageSize = (DWORD)(step * new_h);
    	new_bmpInfo.bPlanes = bmpInfo.bPlanes;
    	new_bmpInfo.bXPelsPerMeter = bmpInfo.bXPelsPerMeter;
    	new_bmpInfo.bYPelsPerMeter = bmpInfo.bYPelsPerMeter;
    
    	fwrite(&bType, sizeof(WORD), 1, pFile);
    	fwrite(&new_bmpFileHeader, sizeof(BMPFILEHEADER), 1, pFile);
    	fwrite(&new_bmpInfo, sizeof(BMPINF), 1, pFile);
    
    	//旋转270度
    	for (i = 0; i<width;i++)
    	{
    		for (j = height-1; j>-1; j--)
    		{
    			pixVal = bmpImg->imageData[j*width * 3 + i * 3];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[j*width * 3 + i * 3 + 1];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			pixVal = bmpImg->imageData[j*width * 3 + i * 3 + 2];
    			fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    		}
    
    		if (offset != 0)
    		{
    			for (j = 0; j<offset; j++)
    			{
    				pixVal = 0;
    				fwrite(&pixVal, sizeof(BYTE), 1, pFile);
    			}
    		}
    	}
    
    }

    参考博客:https://blog.csdn.net/carson2005/article/details/6227047

    展开全文
  • BMP文件信息读取并在CMD窗口显示图片 位图的基本格式可以参考其它博客,这里不进行详细说明。 原始图片及文件信息 原始图片可以在网上下载24位颜色的位图,然后用画图工具进行裁剪编辑,为简单起见,我们限定只...

    C语言读取BMP文件信息并在CMD窗口显示图片

    位图的基本格式可以参考其它博客,这里不进行详细说明。该实验可以更加深入地理解位图的文件结构,以及C语言文件操作的方法。并且理解字节对齐的根本含义。

    原始图片及文件信息

    原始图片可以在网上下载24位颜色的位图,然后用画图工具进行裁剪编辑,为简单起见,我们限定只使用黑白两种颜色,位图的大小建议不要过大,因为CMD窗口无法显示完全。

    这里写图片描述
    这里写图片描述

    效果图


    效果图

    字节对齐

    不使用单字节对齐系统默认四字节对齐。

    这里写图片描述

    代码及说明

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <malloc.h> 
    //单字节对齐
    #pragma pack(1)
    typedef struct BitmapFileHeader
    {
        unsigned char bfType[2];//文件格式
        unsigned long bfSize;//文件大小
        unsigned short bfReserved1;//保留
        unsigned short bfReserved2;//保留
        unsigned long bfOffBits; //图片数据在文件中的偏移量
    }fileHeader;
    typedef struct BitmapInfoHeader
    {
        unsigned long biSize;//该结构的大小
        long biWidth;//文件宽度
        long biHeight;//文件高度
        unsigned short biPlanes;//平面数
        unsigned short biBitCount;//颜色位数
        unsigned long biCompression;//压缩类型
        unsigned long biSizeImage;//DIB数据区大小
        long biXPixPerMeter;
        long biYPixPerMeter;
        unsigned long biClrUsed;//颜色索引表数目
        unsigned long biClrImporant;//重要颜色数目
    }fileInfo;
    
    int main(void)
    {
        FILE *fpaa;
        if ((fpaa = fopen("aa.bmp", "rb") )== NULL)
        {
            printf("打开文件失败");
            exit(0);
        }
        printf("fpaa偏移量:  %d\n", ftell(fpaa));
        fileHeader *fh;
        printf("fileHeader结构体大小:   %d字节\n", sizeof(fileHeader));
        //如果不采样单字节对齐,申请内存时相对于aa.bmp就多出两个字节
        fh= (fileHeader *)malloc(sizeof(fileHeader));
        fread(fh, sizeof(fileHeader), 1, fpaa);
        printf("头文件格式:  %c%cP\n", fh->bfType[0], fh->bfType[1]);
        printf("头文件大小:  %d字节\n", fh->bfSize);
        printf("DIB数据在文件中的偏移量:  %d字节\n", fh->bfOffBits);
        printf("fpaa读取头文件后偏移量:  %d\n",ftell(fpaa));
        fileInfo * fi;
        fi = (fileInfo *)malloc(sizeof(fileInfo));
        fread(fi, sizeof(fileInfo), 1, fpaa);
        printf("fpaa读取信息文件后偏移量:  %d\n", ftell(fpaa));
        printf("位图信息大小: %d\n",fi->biSize);
        printf("文件宽度: %d\n", fi->biWidth);
        printf("文件高度: %d\n", fi->biHeight);
        printf("平面数: %d\n", fi->biPlanes);
        printf("颜色位数: %d\n", fi->biBitCount);
        printf("压缩类型: %d\n", fi->biCompression);
        printf("DIB数据区大小: %d\n", fi->biCompression);
        printf("颜色索引表: %d\n", fi->biClrUsed);
        printf("重要颜色: %d\n", fi->biClrImporant);
    
        printf("\n");
    
        struct color 
        {
            char r;
            char g;
            char b;
        };
        struct color *fc;
        fc = (struct color *)malloc(sizeof(struct color));
        for (int i = 1; i <=fi->biHeight; i ++)
        {
            fseek(fpaa, -((((fi->biBitCount * fi->biWidth) + 31) >> 5) << 2)*i, SEEK_END);
            for (int j = 1; j <= fi->biWidth; j ++ )
            {
                fread(fc, sizeof(struct color), 1, fpaa);
                if (fc->r == 0 & fc->g == 0 & fc->b == 0) printf("%c ",3);
                else printf("%c ", 46);
            }
            printf("\n");
            //((图像宽度*每个像素bites+31)/32)*4可保证每一列为4字节对齐,因为计算机为了速度每次取四字节,不足的要填0
            //下方表达式显示每行多出几个字节
            int k = ((((fi->biBitCount * fi->biWidth) + 31) >> 5) << 2) - ((fi->biBitCount * fi->biWidth) >> 3);
            //再将文件指针移出这几个填充字节
            fseek(fpaa, k, SEEK_CUR);
        }
    
        //可以用不同符号代替黑白
        /*int m=10;
        for (int l=1;l<100;l++)
        {
            printf("%d:%c  ", l,l);
                if (m==0)
                {
                    m = 10;
                    printf("\n");
                }
                m--;
        }
        */
        getchar();
        return 0;
    }
    展开全文
  • 记录读出BMP格式图片的过程,在屏幕上显示; 如有错误欢迎指正,如需转载请注明出处。
  • C语言bmp 8位灰度图的灰度值缩小16倍,由0-255变成0-16,调色板中数值由255行变成16行,同时调色板rgbBlue rgbRed rgbGreen数值范围由0-255变成0-1。我用c语言实现后,为什么图片不再是灰度图,有了其他颜色??...
  • 读取bmp图像做简单显示 bmp图像几何变换(移动,旋转,镜像,转置,缩放) 彩色图像转灰度图,灰度图反色 图像中值滤波与平均滤波 bmp图像锐化 图像的半影调和抖动技术 bmp图像对比度扩展 ...
  • bmp转换ascii.rar

    2020-03-14 20:37:05
    采用C语言编程读取24位*.bmp格式位图图像,并显示对应图像的ASCII字符图。(软件平台VC6.0) 将bmp图片进行黑白二值化,并在控制台终端显示对应图像的ASCII字符图
  • [disp bmp.rar] - c语言写的bmp图像读取显示例程... [bmpfor3.rar] - 从文件读取并显示bmp位图,然后保存 [运用Opengl和C实现一个人体面部的三维显示.rar] - 通过VC++和OPenGL实现人脸的三维显示,在 vc++6.0下编译通过
  • 关于DFT的部分,由于我在DFT的算法里面使用了Complex类与COMPLEX结构体(类包含了运算符的重载与一些常用函数),毕竟C语言并没有专用的复数运算可以调用。 所以在进行DFT运算时会不断调用类的构造函数与析构函数,...
  • CreateFile读取文件进行处理。 CreateFile写入文件,以供分析之用。 FileNumber 20111028 2219.7z 功能: 给文件编号。(文件有遗漏。) CreateFile读取文件。 CFile写入文件。(==修正为CreateFile) !...
  • CreateFile读取文件进行处理。 CreateFile写入文件,以供分析之用。 FileNumber 20111028 2219.7z 功能: 给文件编号。(文件有遗漏。) CreateFile读取文件。 CFile写入文件。(==修正为CreateFile) !...
  • CreateFile读取文件进行处理。 CreateFile写入文件,以供分析之用。 FileNumber 20111028 2219.7z 功能: 给文件编号。(文件有遗漏。) CreateFile读取文件。 CFile写入文件。(==修正为CreateFile) !...
  • picture'sgrey

    2009-11-21 11:42:23
    原理:在这里用C语言只简单的改变象素矩阵的RGB值,来达到彩色图转变为灰度图,没有添加调色板。 主要步骤: 1、 获取彩色图片。 2、 读取图片的像素。 3、采用精确加权平均值算法:R=G=B=R*0.299+G*0.587+B0.144...
  • 该引擎可以导入.obj模型和.bmp纹理,提供可配置的灯光着色器。 物理:物理模块可以计算同一平面中两个矩形之间的碰撞。 脚本:脚本模块允许轻松编写游戏玩法,即不同显示的网格物体的行为。 音频(OpenAL):...
  • C游戏编程从入门到精通(13M)

    热门讨论 2010-06-01 17:32:44
    73 7.5.1 小字库技术 74 7.5.2 无字库技术 80 7.6 中文特效 83 7.6.1 多字体显示 83 7.6.2 文字格式显示 83 7.7 本章小结 84 第8章 图形文件 85 8.1 bmp文件调用 85 8.1.1 bmp文件结构 86 8.1.2 256色bmp文件显示 ...
  • Format 格式化输出字符串(类C语言) CreateLink 创建文件关联 DesktopHide 隐藏桌面 SystemKeySet 禁用系统键 RegisterFile 注册文件名解除文件注册 封装过的Win32 API函数: FindWindow 查找指定窗口...
  • LcmZimo字模软件

    2012-07-17 11:51:47
    打开功能是专门用于对C语言文件自动提取显示所需要的汉字,进行点阵码数据转换的, 在您的C语言程序中,有一点需要特别留意:您的注解中请不要使用双引号,否则会引起 提取错误。 软件包中的文件ee.c作为一个简单...
  • 12864液晶中文取模软件

    热门讨论 2009-07-17 14:58:47
    这项功能在做点阵显示和修改的时候不出现下划线, 设置了以后仅仅在最后的输出文件中出现,以免干扰编辑修改。 8。扩充对windows汉字的直接提取,从16~96范围内可以任意设定选取。主要用于制作界面的 开机封面...
  • 采用每次读 1 扇区方式从失败处继续。 7.增强文件名识别,便于重命名。 7.1 文件名可以任意大小写,但是在 grldr.mbr 及 grldr.pbr 中必须大写。 7.2 在 grldr.pbr 中: FAT16、FAT32 分区使用 8.3 格式; ...
  • inih:C语言的简单.INI文件解析器,很适合嵌入式系统。 inih:inih的C++版本,只有头文件。 iniparser:INI文件解析器。 libconfig:用于处理结构化配置文件的C、C++库。 libconfuse:C的小型配置文件解析库...

空空如也

空空如也

1 2
收藏数 33
精华内容 13
关键字:

c语言读取并显示bmp

c语言 订阅