读取bmp格式图片(二)

来源:互联网 发布:淘宝店招素材图 编辑:程序博客网 时间:2024/05/18 17:02

准备工作已经完成。

先建立一个bmp.h头文件。

参考代码:http://pengqianhe.googlepages.com/   Author:彭千贺

代码如下:

#ifndef BMP_H_INCLUDED#define BMP_H_INCLUDEDtypedef unsigned short WORD;typedef unsigned long DWORD;typedef long LONG;typedef unsigned char BYTE;// BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。其结构定义如下:typedef struct tagBITMAPFILEHEADER{ // bmfhWORD bfType;  // 位图文件的类型,必须为BMDWORD bfSize;// 位图文件的大小,以字节为单位WORD bfReserved1;// 位图文件保留字,必须为0WORD bfReserved2;// 位图文件保留字,必须为0DWORD bfOffBits;// 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位}BITMAPFILEHEADER;// BMP位图信息头数据用于说明位图的尺寸等信息。其结构定义如下:typedef struct tagBITMAPINFOHEADER{ // bmihDWORD biSize;// 本结构所占用字节数LONG biWidth;  // 位图的宽度,以像素为单位LONG biHeight; // 位图的高度,以像素为单位WORD biPlanes; // 目标设备的级别,必须为1WORD biBitCount;// 每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一DWORD biCompression;  // 位图压缩类型,必须是 0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一DWORD biSizeImage;// 位图的大小,以字节为单位LONG biXPelsPerMeter;// 位图水平分辨率,每米像素数LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数DWORD biClrImportant;// 位图显示过程中重要的颜色数}BITMAPINFOHEADER;// 颜色表用于说明位图中的颜色,有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:// 颜色表中RGBQUAD结构数据的个数有biBitCount来确定:// 当biBitCount=1,4,8时,分别有2,16,256个表项;    当biBitCount=24时,没有颜色表项。typedef struct tagRGBQUAD{ // rgbqBYTE rgbBlue;// 蓝色的亮度(值范围为0-255)BYTE rgbGreen; // 绿色的亮度(值范围为0-255)  BYTE rgbRed;// 红色的亮度(值范围为0-255)  BYTE rgbReserved;// 保留,必须为0  }RGBQUAD; // 位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:typedef struct tagBITMAPINFO{BITMAPINFOHEADER bmiHeader;// 位图信息头  RGBQUAD bmiColors[1];// 位图信息头  }BITMAPINFO;#endif // BMP_H_INCLUDED

然后是主函数:


#include <stdio.h>#include <stdlib.h>#include <string.h>#include <malloc.h>#include <ctype.h>#include <process.h>#include "BMP.h"BITMAPFILEHEADER bmfh;BITMAPINFOHEADER bmih;BYTE *imgData;bool bReadBMFH=false;bool bReadBMIH=false;bool bReadPixel=false;//检查路径是否合法:文件能打开;以 bmp 为后缀名int CheckFilePath(char *filepath);//读入位图的文件头int ReadFileHeader(char *filepath,BITMAPFILEHEADER *bmfh);//打印位图的文件头void PrintFileHeader(BITMAPFILEHEADER *bmfh);//读入位图的信息头int ReadInfoHeader(char *filepath,BITMAPINFOHEADER *bmih);//打印位图的信息头void PrintInfoHeader(BITMAPINFOHEADER *bmih);//创建 8 位位图的调色板int CreatePalette(RGBQUAD pal[]);//读入位图的像素数据int ReadPixelData(char *filepath,BYTE *imgData);//计算每行像素所占的字节数LONG GetLineBytes(int imgWidth,int bitCount);//打印位图的像素数据void PrintPixelData(BYTE *imgData,int width,int height,int bitCount);//打印菜单选项void PrintMenu();//另存为位图int SaveAsImage(char *filepath);//显示位图void ShowImage(char * filepath);//保存文件头int SaveFileHeader(FILE* fp);//保存信息头int SaveInfoHeader(FILE* fp);//保存调色板int SaveColorPalette(FILE *fp);//保存像素数据int SavePixelData(FILE* fp);// 主函数int main(){// 要打开的bmp文件路径存储数组char filepath[256];// 徐保存的路径存储char saveasfilepath[256];// 变量与常用参数int i;int width;int height;int bitCount;// 在头文件已经定义:typedef unsigned long DWORD;DWORD dwLineBytes;int select;    int q=0;// system 命令即是cmd命令system("echo off");system("color 2"); // 调整字体颜色printf("-----------TIMimage-----------\n");printf("Input the path of the BMP file:\n");gets(filepath);// 测试路径下是否有此文件i=CheckFilePath(filepath);if(i==-1){return -1;}do{// 如果路径合法,则打印相关程序功能选项PrintMenu();scanf("%u",&select);// 测试用户选择switch(select){case 0:{printf("Input the path of the BMP file:\n");scanf("%s",filepath);CheckFilePath(filepath);break;}case 1:{i=ReadFileHeader(filepath,&bmfh);if(i!=-1){printf("Read the file header successfully.\n");bReadBMFH=true;break;}else{printf("Read the file header failed.\n");bReadBMFH=false;q=1;break;}}case 2:{i=ReadInfoHeader(filepath,&bmih);if(i!=-1){printf("Read the info header successfully.\n");bReadBMIH=true;break;}else{printf("Read the info header failed.\n");bReadBMIH=false;q=1;break;}}case 3:{if(!bReadBMIH){printf("Please read the info header at first.\n");break;}height=bmih.biHeight;width=bmih.biWidth;bitCount=bmih.biBitCount;dwLineBytes=GetLineBytes(width,bitCount);imgData=(BYTE*)malloc(dwLineBytes*height*sizeof(BYTE));if(!imgData){printf("Can not allocate memory for the image.\n");q=1;break;}i=ReadPixelData(filepath,imgData);if(i==-1){printf("Read the pixel data failed.\n");bReadPixel=false;q=1;break;}else{printf("Read the pixel data successfully.\n");bReadPixel=true;break;}}case 4:{if(bReadBMFH){PrintFileHeader(&bmfh);break;}else{printf("Please read the file header at first.\n");break;}}case 5:{if(bReadBMIH){PrintInfoHeader(&bmih);break;}else{printf("Please read the info header at first.\n");break;}}case 6:{if(bReadPixel){PrintPixelData(imgData,width,height,bitCount);break;}else{printf("Please read the pixel data at first.\n");break;}}case 7:{ShowImage(filepath);break;}case 8:{printf("Input the path(ex. d://poon.bmp) you want to save:\n");scanf("%s",saveasfilepath);i=SaveAsImage(saveasfilepath);if(i==-1){printf("Error: failed to save the image.\n");break;}break;}default:q=1;break;}select=9527;} while (q==0);return 0;}// 测试路径或文件是否合法int CheckFilePath(char *filepath){FILE *fp;int len=strlen(filepath)/sizeof(char); // 求路径的长度char ext[3];// 如果路径不为空if(filepath[0]!=int('\"')){// 将路径的后缀复制入ext[];strncpy(ext,&filepath[len-3],3);// 根据文件后缀,判断文件格式if(!(ext[0]=='b' && ext[1]=='m' && ext[2]=='p')){printf("Error: The file is not a BMP file.\n");printf("Error: The extention of the filename must be 'bmp',not 'BMP'\n");return -1;}// 如果格式正确,打开文件fp=fopen(filepath,"r");// 如果打不开,则路径错误if(!fp){printf("Error: The path is not correct.\n");return -1;}// 关闭文件fclose(fp);}else{printf("Error: The path must not include blank space.\n");return -1;}return 0;}// 打印选择项目的调用函数void PrintMenu(){printf(" -----Choose Your Operation-----\n");printf("| 0-----Input the image path |\n");printf("| 1-----Read the file header |\n");printf("| 2-----Read the info header |\n");printf("| 3-----Read the pixel data |\n");printf("| 4-----Print the file header |\n");printf("| 5-----Print the info header |\n");printf("| 6-----Print the pixel data |\n");printf("| 7-----View the original image |\n");printf("| 8-----Save as the image |\n");printf("| other-----Exit the program |\n");printf(" -------------------------------\n");}// 读取bmp文件头// 各个信息对应结构体的内容int ReadFileHeader(char *filepath,BITMAPFILEHEADER *bmfh){FILE *fp;fp=fopen(filepath,"rb");if(!fp){printf("Can not open the file:%s\n",filepath);return -1;}if(fread(&bmfh->bfType,sizeof(WORD),1,fp)!=1){printf("Can not read bfType in the file header.\n");fclose(fp);return -1;}if(fread(&bmfh->bfSize,sizeof(DWORD),1,fp)!=1){printf("Can not read bfSize in the file header.\n");fclose(fp);return -1;}if(fread(&bmfh->bfReserved1,sizeof(WORD),1,fp)!=1){printf("Can not read bfReserved1 in the file header.\n");fclose(fp);return -1;}if(fread(&bmfh->bfReserved2,sizeof(WORD),1,fp)!=1){printf("Can not read bfReserved2 in the file header.\n");fclose(fp);return -1;}if(fread(&bmfh->bfOffBits,sizeof(DWORD),1,fp)!=1){printf("Can not read bfOffBits in the file header.\n");fclose(fp);return -1;}fclose(fp);return 0;}// 读取信息头int ReadInfoHeader(char *filepath,BITMAPINFOHEADER *bmih){FILE *fp;fp=fopen(filepath,"rb");if(!fp){printf("Can not open the file:%s\n",filepath);return -1;}fseek(fp,14,SEEK_SET);if(fread(&bmih->biSize,sizeof(DWORD),1,fp)!=1){printf("Can not read biSize in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biWidth,sizeof(LONG),1,fp)!=1){printf("Can not read biWidth in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biHeight,sizeof(LONG),1,fp)!=1){printf("Can not read biHeight in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biPlanes,sizeof(WORD),1,fp)!=1){printf("Can not read biPlanes in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biBitCount,sizeof(WORD),1,fp)!=1){printf("Can not read biBitCount in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biCompression,sizeof(DWORD),1,fp)!=1){printf("Can not read biCompression in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biSizeImage,sizeof(DWORD),1,fp)!=1){printf("Can not read biSizeImage in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biXPelsPerMeter,sizeof(LONG),1,fp)!=1){printf("Can not read biXPelsPerMeter in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biYPelsPerMeter,sizeof(LONG),1,fp)!=1){printf("Can not read biYPelsPerMeter in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biClrUsed,sizeof(DWORD),1,fp)!=1){printf("Can not read biClrUsed in the info header.\n");fclose(fp);return -1;}if(fread(&bmih->biClrImportant,sizeof(DWORD),1,fp)!=1){printf("Can not read biClrImportant in the info header.\n");fclose(fp);return -1;}fclose(fp);return 0;}//创建 8 位位图的调色板int CreatePalette(RGBQUAD pal[]){int i;if(sizeof(pal)/sizeof(RGBQUAD)!=256){printf("The size of the palette must be 256.\n");return -1;}for(i=0;i<256;i++){pal[i].rgbBlue=i;pal[i].rgbGreen=i;pal[i].rgbRed=i;pal[i].rgbReserved=0;}return 0;}//读入位图的像素数据int ReadPixelData(char *filepath,BYTE *imgData){BITMAPINFOHEADER bmih;BITMAPFILEHEADER bmfh;BYTE *data;FILE *fp;int n;int width;int height;int bitCount;DWORD dwLineBytes;n=ReadFileHeader(filepath,&bmfh);if(n==-1){printf("Can not read the file header of the BMP file.\n");return -1;}n=ReadInfoHeader(filepath,&bmih);if(n==-1){printf("Can not read the info header of the BMP file.\n");return -1;}width=bmih.biWidth;height=bmih.biHeight;bitCount=bmih.biBitCount;dwLineBytes=GetLineBytes(width,bitCount);if(_msize(imgData)!=(dwLineBytes*height)){printf("The size you allocate for the pixel data is not right.\n");printf("Fittable size: %ld bytes.\n",(dwLineBytes*height));printf("Your size: %ld bytes.\n",sizeof(imgData));return -1;}data=(BYTE*)malloc(dwLineBytes*height*sizeof(BYTE));if(!data){printf("Can not allocate memory for the pixel data.\n");return -1;}fp=fopen(filepath,"rb");if(!fp){printf("Can not open the file: %s\n",filepath);free(data);return -1;}if(bitCount==8){fseek(fp,bmfh.bfOffBits,SEEK_SET);}else if(bitCount==24){fseek(fp,bmfh.bfOffBits,SEEK_SET);}else{printf("Only Support: 8 or 24 bits.\n");free(data);fclose(fp);return -1;}n=fread(data,dwLineBytes*height*sizeof(BYTE),1,fp);if(n==0){if(feof(fp)){}if(ferror(fp)){printf("Can not read the pixel data.\n");free(data);fclose(fp);return -1;}}memcpy(imgData,data,dwLineBytes*height*sizeof(BYTE));free(data);fclose(fp);return 0;}void PrintFileHeader(BITMAPFILEHEADER *bmfh){printf("The contents in the file header of the BMP file:\n");printf("bfOffBits: %ld\n",bmfh->bfOffBits);printf("bfReserved1: %ld\n",bmfh->bfReserved1);printf("bfReserved2: %ld\n",bmfh->bfReserved2);printf("bfSize: %ld\n",bmfh->bfSize);printf("bfType: %ld\n",bmfh->bfType);}void PrintInfoHeader(BITMAPINFOHEADER *bmih){printf("The content in the info header of the BMP file:\n");printf("biBitCount: %ld\n",bmih->biBitCount);printf("biClrImportant: %ld\n",bmih->biClrImportant);printf("biClrUsed: %ld\n",bmih->biClrUsed);printf("biCompression: %ld\n",bmih->biCompression);printf("biHeight: %ld\n",bmih->biHeight);printf("biPlanes: %ld\n",bmih->biPlanes);printf("biSize: %ld\n",bmih->biSize);printf("biSizeImage: %ld\n",bmih->biSizeImage);printf("biWidth: %ld\n",bmih->biWidth);printf("biXPelsPerMeter: %ld\n",bmih->biXPelsPerMeter);printf("biYPelsPerMeter: %ld\n",bmih->biYPelsPerMeter);}LONG GetLineBytes(int imgWidth,int bitCount){return (imgWidth*bitCount+31)/32*4;}void PrintPixelData(BYTE *imgData,int width,int height,int bitCount){int i;int j;int p;DWORD dwLineBytes=GetLineBytes(width,bitCount);if(bitCount==8){for(i=0;i<height;i++){for(j=0;j<width;j++){p=*(imgData+dwLineBytes*(height-1-i)+j);printf("%d,",p);}printf("\n");}}else if(bitCount==24){for(i=0;i<height;i++){for(j=0;j<width*3;j++){printf("(");p=*(imgData+dwLineBytes*(height-1-i)+j);printf("%d,",p);j++;p=*(imgData+dwLineBytes*(height-1-i)+j);printf("%d,",p);j++;p=*(imgData+dwLineBytes*(height-1-i)+j);printf("%d) ",p);}printf("\n");}}else{printf("Only supported: 8 or 24 bits.\n");}}int SaveAsImage(char *filepath){FILE *fp;fp=fopen(filepath,"wb");if(!fp){printf("Error: can not create the file.\n");return -1;}SaveFileHeader(fp);SaveInfoHeader(fp);if(bmih.biBitCount==8){SaveColorPalette(fp);}SavePixelData(fp);fclose(fp);printf("Save As the image successfully.\n");return 0;}void ShowImage(char * filepath){char cmd[266];strcpy(cmd,"start ");strcat(cmd,filepath);printf("%s\n",cmd);system(cmd);}int SaveFileHeader(FILE *fp){if(!bReadBMFH){printf("Please read the file header at first.\n");return -1;}if(fwrite(&bmfh.bfType,sizeof(WORD),1,fp)!=1){printf("Can not write bfType in the file header.\n");fclose(fp);return -1;}if(fwrite(&bmfh.bfSize,sizeof(DWORD),1,fp)!=1){printf("Can not write bfSize in the file header.\n");fclose(fp);return -1;}if(fwrite(&bmfh.bfReserved1,sizeof(WORD),1,fp)!=1){printf("Can not write bfReserved1 in the file header.\n");fclose(fp);return -1;}if(fwrite(&bmfh.bfReserved2,sizeof(WORD),1,fp)!=1){printf("Can not write bfReserved2 in the file header.\n");fclose(fp);return -1;}if(fwrite(&bmfh.bfOffBits,sizeof(DWORD),1,fp)!=1){printf("Can not write bfOffBits in the file header.\n");fclose(fp);return -1;}return 0;}int SaveInfoHeader(FILE *fp){if(!bReadBMIH){printf("Please read the info header at first.\n");return -1;}if(fwrite(&bmih.biSize,sizeof(DWORD),1,fp)!=1){printf("Can not write biSize in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biWidth,sizeof(LONG),1,fp)!=1){printf("Can not write biWidth in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biHeight,sizeof(LONG),1,fp)!=1){printf("Can not write biHeight in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biPlanes,sizeof(WORD),1,fp)!=1){printf("Can not write biPlanes in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biBitCount,sizeof(WORD),1,fp)!=1){printf("Can not write biBitCount in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biCompression,sizeof(DWORD),1,fp)!=1){printf("Can not write biCompression in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biSizeImage,sizeof(DWORD),1,fp)!=1){printf("Can not write biSizeImage in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biXPelsPerMeter,sizeof(LONG),1,fp)!=1){printf("Can not write biXPelsPerMeter in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biYPelsPerMeter,sizeof(LONG),1,fp)!=1){printf("Can not write biYPelsPerMeter in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biClrUsed,sizeof(DWORD),1,fp)!=1){printf("Can not write biClrUsed in the info header.\n");fclose(fp);return -1;}if(fwrite(&bmih.biClrImportant,sizeof(DWORD),1,fp)!=1){printf("Can not write biClrImportant in the info header.\n");fclose(fp);return -1;}return 0;}int SaveColorPalette(FILE *fp){int i;RGBQUAD pal[256];if(!bReadBMIH){printf("Please read the info header at first.\n");return -1;}if(bmih.biBitCount!=8){printf("Only 8 bits image hase color palette.\n");return -1;}for(i=0;i<256;i++){pal[i].rgbReserved=0;pal[i].rgbBlue=i;pal[i].rgbGreen=i;pal[i].rgbRed=i;}if(fwrite(pal,sizeof(RGBQUAD),256,fp)!=256){printf("Error: can not write the color palette.\n");fclose(fp);return -1;}return 0;}int SavePixelData(FILE* fp){int height=bmih.biHeight;DWORD dwLineBytes=GetLineBytes(bmih.biWidth,bmih.biBitCount);if(!bReadPixel){printf("Please read the pixel data at first.\n");return -1;}if(fwrite(imgData,height*dwLineBytes,1,fp)!=1){printf("Error: can not write the pixel data.\n");fclose(fp);return -1;}return 0;}

运行效果:




图片的属性:



读取结果:




原创粉丝点击