C++ bmp位图读取

137次阅读
没有评论

共计 5879 个字符,预计需要花费 15 分钟才能阅读完成。

首先   简单解释一下bmp文件格式

bmp 格式文件 分为四个部分

header 文件格式,大小

infoheader 图像的高,宽,位数

optional palette 可选调色板:使用索引来表示图像是的 索引与颜色的映射 并非一定包含

image data 图像像素信息的数据

其中24位bmp文件不使用索引 所以不需要optional palette 部分

所以在读取调色板是进行文件格式的判断,如24位,则不需要读取调色板,直接读取像素信息

FILE *fp=NULL; 
    int ret = fopen_s(&fp,"D:\\11.bmp","rb"); 
    if(fp==0)    
    { 
        return ; 
    } 
    BITMAPFILEHEADER fileheader={0}; 
    fread(&fileheader,sizeof(fileheader),1,fp); 
    if(fileheader.bfType!=0x4D42) 
    { 
        fclose(fp); 
        return ; 
    } 
 
    BITMAPINFOHEADER head; 
    fread(&head,sizeof(BITMAPINFOHEADER),1,fp);  
    long bmpWidth = head.biWidth; 
    long bmpHeight = head.biHeight; 
    WORD biBitCount = head.biBitCount; 
    if(biBitCount != 24) 
    { 
        ::AfxMessageBox(_T("请选择24位位图!")); 
        fclose(fp); 
        return ; 
    } 
 
    int totalSize = (bmpWidth *biBitCount/8+3)/4*4*bmpHeight; 
    BYTE *pBmpBuf = new BYTE[totalSize]; 
    size_t size = 0; 
    while(true) 
    { 
        int iret = fread(&pBmpBuf[size],1,1,fp); 
        if(iret == 0) 
            break; 
        size = size + iret; 
    } 
    fclose(fp); 
 
    int i,j; 
    CClientDC dc(this); 
    int pitch=bmpWidth%4; 
    for(i=0;i<bmpHeight;i++) 
    { 
        int realPitch=i*pitch; 
        for(j=0;j<bmpWidth;j++) 
        { 
            dc.SetPixel(j,i,RGB( 
                pBmpBuf[(i*bmpWidth+j)*3+2+realPitch], 
                pBmpBuf[(i*bmpWidth+j)*3+1+realPitch], 
                pBmpBuf[(i*bmpWidth+j)*3+realPitch])); 
        } 
    } 
delete [] pBmpBuf; pBmpBuf = NULL;
    return ;

完整读取代码,为了兼容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;
  }
 
  fseek(fp, sizeof(FileHeader), SEEK_SET);
  //lseek(fp, sizeof(FileHeader), SEEK_SET);
  InfoHeader head;
  fread(&head, sizeof(InfoHeader), 1, fp);
  //read(fp, &head, sizeof(InfoHeader));
 
  bmpWidth = head.biWidth;
  bmpHeight = head.biHeight;
  biBitCount = head.biBitCount;
 
  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[] = "logo256.bmp";
  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

 

 

正文完
 
admin
版权声明:本站原创文章,由 admin 2022-07-02发表,共计5879字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码