2012年7月17日 星期二

Read Bitmap by C++

NeoBmp.h
#ifndef Neo_Bmp_H
#define Neo_Bmp_H
class NeoBmp
{
public:
    int width,height;
    unsigned char* rgb;
    NeoBmp();
    ~NeoBmp();
    void load(const char* filename);
    void save(const char* filename);
    void flip_vectical();
private:
    void rb_swap();
};
#endif
NeoBmp.cpp

#include "stdio.h"
#include "stdlib.h"
#include "memory.h"
#include "NeoBmp.H"

#pragma pack( push, 1 )
typedef struct _bmp_header_info
{
  unsigned short bfType;
  unsigned int bfSize;
  unsigned short bfReserved1;
  unsigned short bfReserved2;
  unsigned int bfOffBits;

  // bitmap header
  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;
} bmp_header_info;
#pragma pack( pop, 1 )

NeoBmp::NeoBmp()
{
    memset(this, 0, sizeof(NeoBmp));
}

NeoBmp::~NeoBmp()
{
    if(rgb!=NULL)
        free(rgb);
}

void NeoBmp::load(const char* filename)
{
    bmp_header_info bhi;
    {
          FILE *fp = fopen(filename, "rb" );
          if(fp==NULL )
          {
          printf( "[Error] NeoBmp::load, file '%s' not found.\n", filename);
          exit(-1);
          }
          fread(&bhi,sizeof(bmp_header_info),1,fp);
          fclose(fp);
    }
    if(bhi.bfType != 'MB' )
    {
        printf( "[Error] NeoBmp::load, not bitmap file\n" );
        exit(-1);
    }
    if( bhi.biCompression != 0 )
    {
        printf( "[Error] NeoBmp::load, only uncompressed bitmap is supported\n" );
        exit(-1);
    }
      if( bhi.biBitCount != 24 )
    {
        printf( "[Error] NeoBmp::load, must be 24bit bitmap\n" );
        exit(-1);
    }

    if(rgb) free(rgb);
    width = bhi.biWidth;
    height = bhi.biHeight;
    rgb = (unsigned char*) malloc(width*height*3*sizeof(unsigned char));
    {
        FILE *fp = fopen( filename, "rb" );
        fseek( fp, bhi.bfOffBits, SEEK_SET );
        int i;
        for(i=0; i < height; i++ )
        {
            fread(&rgb[i*width*3], sizeof(unsigned char), width*3, fp );
            fseek(fp, (4-width*3%4)%4, SEEK_CUR );
        }
        fclose(fp);
    }
    rb_swap();
}

void NeoBmp::rb_swap()
{
  unsigned char tmp;
  int i,j;
  for( j=0; j < height; j++ )
    for( i=0; i < width; i++ )
    {
     tmp = rgb[(j*width+i)*3];
     rgb[(j*width+i)*3] = rgb[(j*width+i)*3+2];
     rgb[(j*width+i)*3+2] = tmp;
    }
}

void NeoBmp::save( const char *filename)
{
    bmp_header_info bhi;
    bhi.bfType = 'MB';
    bhi.bfSize = width*height*3*sizeof(unsigned char) + sizeof(bhi);
    bhi.bfReserved1 = 0;
    bhi.bfReserved2 = 0;
    bhi.bfOffBits = sizeof(bhi);

    bhi.biSize = 40;
    bhi.biWidth = width;
    bhi.biHeight = height;
    bhi.biPlanes = 1;
    bhi.biBitCount = 24;
    bhi.biCompression = 0;
    bhi.biSizeImage = 0;
    bhi.biXpelsPerMeter = 0;
    bhi.biYpelsPerMeter = 0;
    bhi.biClrUsed = 0;
    bhi.biClrImportant = 0;
    int j;
    rb_swap();
    unsigned char pad[3] = {0};
    FILE *fp = fopen(filename, "wb" );
    fwrite( &bhi, sizeof(bmp_header_info), 1, fp);
     for( j=0; j < height; j++ )
     {
     fwrite( &rgb[j*width*3], sizeof(unsigned char), width*3, fp);
     fwrite(pad, sizeof(unsigned char), (4-width*3%4)%4, fp);
     }
     fclose(fp);
}
void NeoBmp::flip_vectical()
{
    unsigned char* tmp_rgb = (unsigned char*) malloc(width*height*3*sizeof(unsigned char));
    int j;
    for(j=0; j < height; j++)
    {
        memcpy( &tmp_rgb[j*width*3], &rgb[(height-j-1)*width*3], width*3*sizeof(unsigned char) );
    }
    memcpy( rgb, tmp_rgb, width*height*3*sizeof(unsigned char) );
    free(tmp_rgb);
}

main.cpp

#include "NeoBmp.H"
using namespace std;

int main()
{
    NeoBmp a;
    a.load("test.bmp");
    a.flip_vectical();
    a.save("output.bmp");
    return 0;
}

沒有留言:

張貼留言