c++实现bmp文件的读写

来源:互联网 发布:淘宝客订单虚假交易 编辑:程序博客网 时间:2024/04/28 19:01


程序分为bmp相关的三个文件以及一个实例文件:

 1.bmp格式文件的结构体定义--  bmpstruct.h

 2.bmp格式文件的类定义文件-- cBMPimage.h

 3.bmp格式文件的类实现文件 - cBMPimage.cpp

  4示例文件--main.c

 

1.bmpstruct.h

#ifndef BMPSTRUCT#define BMPSTRUCT//~~~~~~~~~~~~~~~~~~结构体定义~~~~~~~~~~~~~~~~~~~~~~~~//typedef struct tagBMPHEADER{unsigned short bfType; //文件类型unsigned long bfSize; //bmp文件长度WORD Reserved1;WORD Reserved2;unsigned long bfOffset; //文件描述区长度,16色为118,256色为1078}BMPHEADER;//现在算一下,有3个int,2个long,正好3*2+2*4=14字节//图像信息区typedef struct  tagBMPINFOHEADER{DWORD biSize;LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXplosPerMeter;LONG biYplosPerMeter;DWORD biClrUsed;DWORD biClrImportant;} BMPINFOHEADER;// 2+2*9*4 =40 字节?有疑问//调色板typedef struct tagBMPRGBQUAD{BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserve;} BMPRGBQUAD;//位图数据typedef struct  tagIMAGEDATA{BYTE red;BYTE green;BYTE blue;}IMAGEDATA;#endif


2.cBMPimage.h

#pragma once#include <stdio.h>#include  <windows.h>#include "bmpstruct.h"class cBMPimage{public:BMPHEADER file;BMPINFOHEADER info;BMPRGBQUAD *palette;IMAGEDATA *imagedata;public:cBMPimage(void);~cBMPimage(void);public:int GetBmpSize(FILE *fp) ;int bmpload(const char* filename);int bmpsave(const char* filename);int bmpcopypara(cBMPimage *bmpimage);};

 

  3.cBMPimage.cpp  (实际使用时最好将printf去掉)

#include "cBMPimage.h"cBMPimage::cBMPimage(void){palette = NULL;imagedata = NULL;}cBMPimage::~cBMPimage(void){if (palette!=NULL){free(palette);palette = NULL;}if (imagedata!=NULL){free(imagedata);imagedata= NULL;}}int cBMPimage::GetBmpSize( FILE *fp ){long curpos;   // attention! this is a long type.   int len;  curpos = ftell(fp);  fseek(fp, 0, SEEK_END);  len = ftell(fp);  fseek(fp, curpos, SEEK_SET);   return len;  }int cBMPimage::bmpload( const char* filename ){FILE *fp;int bTrueClr=1;unsigned char *cp1, *cp2, *sp; int i, j;  int Width;  unsigned char *paletteIndex; if ((fp = fopen(filename,"rb+")) == NULL) // must be "rb" to indicate the position of the file while the pointer is moving!   {  printf("Can not open file\n");  system("pause");  exit(0);  }fread(&file,sizeof(unsigned short),1,fp);//??????????sp = (unsigned char*)&file;sp = sp+4;fread(sp,sizeof(struct tagBMPHEADER)-4,1,fp);fread(&info,sizeof(struct tagBMPINFOHEADER),1,fp);if (info.biBitCount==1||\info.biBitCount==4||\info.biBitCount==8){palette = (BMPRGBQUAD *)malloc(sizeof(BMPRGBQUAD)*(1<<info.biBitCount));fread(palette,sizeof(BMPRGBQUAD)*(1<<info.biBitCount),1,fp);bTrueClr = 0;}if (file.bfType != 0x4d42)  {  printf("The type of the image is not supported\n");  }  if (info.biCompression != 0)  {  printf("The compression type are not supported.\n");  }  if (file.bfSize != GetBmpSize(fp))  {  printf("The size of the file is not matched\n");  }  cp1 = (unsigned char *)&(file.bfType);  cp2 = cp1 + 1;  printf("%c", *cp1);  printf("%c\n", *cp2);  printf("File size: %lu\n", file.bfSize);  printf("Offset from the BOF to the virtual image data: %lu\n", file.bfOffset);  // print the info value.   printf("The size of the infoheader is: %lu\n", info.biSize);  printf("Width: %ld\n", info.biWidth);  printf("Height: %ld\n", info.biHeight);  printf("Planes: %d\n", info.biPlanes);  printf("Bit Depth: %d\n", info.biBitCount);  printf("Compression type: %lu\n", info.biCompression);  printf("Image data size: %lu\n", info.biSizeImage);  printf("XperMeter: %ld\n", info.biXplosPerMeter);  printf("YperMeter: %ld\n", info.biYplosPerMeter);  printf("Color used: %lu\n", info.biClrUsed);  printf("Important color: %lu\n", info.biClrImportant);  Width = (info.biWidth*info.biBitCount + 31)/8/4*4;//int pic_width = Width/4;// print the pixel of the imagedata   imagedata = (IMAGEDATA *)malloc( sizeof(unsigned char)*Width*info.biHeight);paletteIndex = (unsigned char *)malloc(sizeof(unsigned char)*Width*info.biHeight);  if (!bTrueClr)  {  fread(paletteIndex, sizeof(unsigned char)*Width*info.biHeight, 1, fp);  for (i = 0; i < info.biHeight; i++)  {  for (j = 0; j < Width; j++)  {  (*(imagedata + i * info.biHeight + j)).blue = palette[(BYTE)(*(paletteIndex + i*info.biHeight + j))].rgbBlue;  (*(imagedata + i * info.biHeight + j)).green = palette[(BYTE)(*(paletteIndex + i*info.biHeight + j))].rgbGreen;  (*(imagedata + i * info.biHeight + j)).red= palette[(BYTE)(*(paletteIndex + i*info.biHeight + j))].rgbRed;  }  }  }  else  {  fread(imagedata, sizeof(unsigned char)*Width*info.biHeight, 1, fp);}  fclose(fp);  //system("pause");  free(paletteIndex);  return 0;  }int cBMPimage::bmpcopypara( cBMPimage *pbmpimage ){file.bfOffset = pbmpimage->file.bfOffset;file.bfSize = pbmpimage->file.bfSize;file.bfType = pbmpimage->file.bfType;info.biBitCount = pbmpimage->info.biBitCount;info.biClrImportant = pbmpimage->info.biClrImportant;info.biClrUsed = pbmpimage->info.biClrUsed;info.biCompression = pbmpimage->info.biCompression;info.biHeight = pbmpimage->info.biHeight;info.biPlanes = pbmpimage->info.biPlanes;info.biSize = pbmpimage->info.biSize;info.biSizeImage = pbmpimage->info.biSizeImage;info.biWidth = pbmpimage->info.biWidth;info.biXplosPerMeter = pbmpimage->info.biXplosPerMeter;info.biYplosPerMeter = pbmpimage->info.biYplosPerMeter;if (pbmpimage->palette ==NULL){  palette = NULL;}else{int sizepale = sizeof(BMPRGBQUAD)*(1<<info.biBitCount);palette = (BMPRGBQUAD *)malloc(sizepale);memcpy(palette,pbmpimage->palette,sizepale);}return 1;}int cBMPimage::bmpsave( const char* filename ){FILE *fp = NULL;if (!(fp=fopen(filename,"wb+"))){printf("无法打开文件%s!\n",filename);return -1;}if(fwrite(&file.bfType,sizeof(WORD),1,fp)!=1){printf("Can not write bfType in the file header.\n");fclose(fp);return -1;}if(fwrite(&file.bfSize,sizeof(DWORD),1,fp)!=1){printf("Can not write bfSize in the file header.\n");fclose(fp);return -1;}if(fwrite(&file.Reserved1,sizeof(WORD),1,fp)!=1){printf("Can not write bfReserved1 in the file header.\n");fclose(fp);return -1;}if(fwrite(&file.Reserved2,sizeof(WORD),1,fp)!=1){printf("Can not write bfReserved2 in the file header.\n");fclose(fp);return -1;}if(fwrite(&file.bfOffset,sizeof(DWORD),1,fp)!=1){printf("Can not write bfOffBits in the file header.\n");fclose(fp);return -1;}if(fwrite(&info.biSize,sizeof(DWORD),1,fp)!=1){printf("Can not write biSize in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biWidth,sizeof(LONG),1,fp)!=1){printf("Can not write biWidth in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biHeight,sizeof(LONG),1,fp)!=1){printf("Can not write biHeight in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biPlanes,sizeof(WORD),1,fp)!=1){printf("Can not write biPlanes in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biBitCount,sizeof(WORD),1,fp)!=1){printf("Can not write biBitCount in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biCompression,sizeof(DWORD),1,fp)!=1){printf("Can not write biCompression in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biSizeImage,sizeof(DWORD),1,fp)!=1){printf("Can not write biSizeImage in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biXplosPerMeter,sizeof(LONG),1,fp)!=1){printf("Can not write biXPelsPerMeter in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biYplosPerMeter,sizeof(LONG),1,fp)!=1){printf("Can not write biYPelsPerMeter in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biClrUsed,sizeof(DWORD),1,fp)!=1){printf("Can not write biClrUsed in the info header.\n");fclose(fp);return -1;}if(fwrite(&info.biClrImportant,sizeof(DWORD),1,fp)!=1){printf("Can not write biClrImportant in the info header.\n");fclose(fp);return -1;}BMPRGBQUAD pal[256];for(int i=0;i<256;i++){pal[i].rgbReserve=0;pal[i].rgbBlue=i;pal[i].rgbGreen=i;pal[i].rgbRed=i;}if(info.biBitCount==8){if(fwrite(pal,sizeof(RGBQUAD),256,fp)!=256){printf("Error: can not write the color palette.\n");fclose(fp);return -1;}}int Width = (info.biWidth*info.biBitCount + 31)/8/4*4;int writenum = fwrite(imagedata,sizeof(unsigned char),info.biHeight*Width,fp);if(writenum!=info.biHeight*Width){printf("Error: can not write the pixel data.\n");fclose(fp);return -1;}fclose(fp);//printf("Save As the image successfully.\n");return 0;}


 

4.main.c

#include "cBMPimage.h"int main(){char *fp ="E:\\cudatest\\bmpread\\bmpread\\Debug\\a.bmp";cBMPimage image1,image2;image1.bmpload(fp);image2.bmpcopypara(&image1);image1.bmpsave("E:\\cudatest\\bmpread\\bmpread\\b.bmp");return 0;}


 注:在简略上述程序,只用于8位灰度图时,发现会出现读写错误。逐语句的去找问题,终于找到了。。。。

     在打开bmp文件时,若用fopen函数,mode使用“r+”时,会默认用文本文件方式打开bmp文件,这时,读取颜色表不成功(只读到了0~0x19)。

     所以在打开bmp文件时,一定要用“rb+”,即以二进制方式打开bmp文件。

   为什么在读到0x19 0x19 0x19 0xff 后会结束呢?

  因为0x19后是0x1a,0x1A在ASCII码中代表EOF,在过去,ASCII码EOF曾经在unix/linux中被作为文件结束符使用,微软继承了这个传统,也以EOF作为文件的结束符

  如何解决这个问题?其实标准已经给出了其中一种解决方法,由于二进制方式的输入输出是一一对应的,字符不会产生变化,那么用二进制读取就不会产生这个问题,事实也证明是可以的,只是存在一点麻烦,由于windows下会把/n转换为/r/n,二进制读取时必须对此转换进行堙别和还原,这会增加代码的复杂性,这种麻烦很让人讨厌。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝鼻屎比较深怎么办 来例假痔疮犯了怎么办 微医爽约过一次怎么办 炸完的薯条软了怎么办 学信网号码换了怎么办 学信网注册换手机了怎么办 学信网手机号码已被注册怎么办 学信网手机号码被注册了怎么办 去英国留学不会做饭怎么办 小米陶瓷刀钝了怎么办 橱柜的缝擦不到怎么办 悠悠球上油早了怎么办 买了没有esp的车怎么办 饥荒海难狗来了怎么办 饥荒海难拖网掉水里了怎么办 饥荒遇到了猪人怎么办 饥荒龙蝇赖在家不走怎么办 饥荒海难崩档了怎么办 gta5全是rpf文件怎么办 饥荒没有海象人营地怎么办 饥荒海滩猎犬来了怎么办 宝宝换牙门牙上长颗尖牙怎么办 肉卡在牙缝里怎么办 电脑做系统卡死怎么办 苹果6升级太卡怎么办 电脑玩不了联机饥荒怎么办 饥荒渡渡鸟死了一只怎么办 饥荒电脑联机植物生病怎么办 开车蹭到别人车怎么办 立定跳不会收腹怎么办 1岁宝宝有蛔虫怎么办 手机屏幕总是有网页跳出来怎么办 cs游戏屏幕变成正方形怎么办 大王卡被收回了怎么办 模拟人生4小人生病了怎么办 创造与魔法死后怎么办? 脚不小心扭伤了该怎么办 小鸡脚扭伤了该怎么办 跳高比赛最终成绩相等怎么办 热车1200怠速降不下来怎么办 大腿根骨髓水肿越来越疼怎么办