⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dim_bmp_format_io.cpp

📁 Digital Notebook Source Code v1.1.0 [
💻 CPP
字号:
/*****************************************************************************
  BMP IO 
  Copyright (c) 2004 by Dmitry V. Fedorov <www.dimin.net> <dima@dimin.net>

  IMPLEMENTATION
  
  Programmer: Dima V. Fedorov <mailto:dima@dimin.net> <http://www.dimin.net/>

  CURRENT STATE: NO RLE COMPRESSION SUPPORTED RIGHT NOW!!!  

  History:
    03/29/2004 22:23 - First creation
    05/10/2004 14:55 - Big endian support
    08/04/2004 22:25 - Update to FMT_IFS 1.2, support for io protorypes
        
  Ver : 3
*****************************************************************************/

#include <string>

#include "dim_bmp_format.h"

//****************************************************************************
// READ PROC
//****************************************************************************
static int read_bmp_image(TDimFormatHandle *fmtHndl)
{
  if (fmtHndl == NULL) return 1;
  if (fmtHndl->internalParams == NULL) return 1;
  TDimBmpParams *bmpPar = (TDimBmpParams *) fmtHndl->internalParams;
  TDimImageInfo *info = &bmpPar->i;  
  TDimImageBitmap *img = fmtHndl->image;
  
  //-------------------------------------------------
  // init the image
  //-------------------------------------------------
  if ( allocImg( fmtHndl, info, img) != 0 ) return 1;

  //-------------------------------------------------
  // read the image
  //-------------------------------------------------

  // offset can be bogus, verify
  if ( bmpPar->bf.bfOffBits <= 0 ) return FALSE;
  if ( dimSeek( fmtHndl, bmpPar->bf.bfOffBits, SEEK_SET ) != 0 ) return FALSE;
  
  int bpl = getLineSizeInBytes( img );
  unsigned long bplF = (( bmpPar->bi.biWidth * bmpPar->bi.biBitCount + 31)/32)*4;

    
  //-------------------------------------------------
  // 1,4,8 bit uncompressed BMP image
  //-------------------------------------------------
  if ( (bmpPar->bi.biBitCount == 1) || ( (bmpPar->bi.biBitCount <= 8) && (bmpPar->bi.biCompression == DIM_BMP_RGB) ) ) 
  {       
    int h = bmpPar->bi.biHeight;
    unsigned char *buf = new unsigned char [bplF];      
    
    while ( --h >= 0 ) 
    {
      DIM_UCHAR *p = ((unsigned char *) img->bits[0]) + ( h * bpl );
      if ( dimRead( fmtHndl, buf, 1, bplF ) != bplF) return 1;
      memcpy( p, buf, bpl );
    }
    delete [] buf;
  }

  //-------------------------------------------------
  // 4 bit BMP image
  //-------------------------------------------------  
  if ( ( bmpPar->bi.biBitCount == 4 ) && (bmpPar->bi.biCompression == DIM_BMP_RLE4) )
  {      
    /*
    int    buflen = ((w+7)/8)*4;
    uchar *buf    = new uchar[buflen];
    Q_CHECK_PTR( buf );

    int x=0, y=0, b, c, i;
    register uchar *p = line[h-1];
    uchar *endp = line[h-1]+w;
    while ( y < h ) {
      if ( (b=d->getch()) == EOF )
        break;
      if ( b == 0 ) {     // escape code
        switch ( (b=d->getch()) ) {
        case 0:     // end of line
          x = 0;
          y++;
          p = line[h-y-1];
          break;
        case 1:     // end of image
        case EOF:   // end of file
          y = h;    // exit loop
          break;
        case 2:     // delta (jump)
          x += d->getch();
          y += d->getch();
          
          // Protection
          if ( (uint)x >= (uint)w )
            x = w-1;
          if ( (uint)y >= (uint)h )
            y = h-1;
          
          p = line[h-y-1] + x;
          break;
        default:    // absolute mode
          // Protection
          if ( p + b > endp )
            b = endp-p;
          
          i = (c = b)/2;
          while ( i-- ) {
            b = d->getch();
            *p++ = b >> 4;
            *p++ = b & 0x0f;
          }
          if ( c & 1 )
            *p++ = d->getch() >> 4;
          if ( (((c & 3) + 1) & 2) == 2 )
            d->getch(); // align on word boundary
          x += c;
        }
      } else {      // encoded mode
        // Protection
        if ( p + b > endp )
          b = endp-p;
        
        i = (c = b)/2;
        b = d->getch();   // 2 pixels to be repeated
        while ( i-- ) {
          *p++ = b >> 4;
          *p++ = b & 0x0f;
        }
        if ( c & 1 )
          *p++ = b >> 4;
        x += c;
      }
    }
    */
  } // 4 bits

  //-------------------------------------------------
  // 8 bit BMP image RLE
  //-------------------------------------------------  
  if ( ( bmpPar->bi.biBitCount == 8 ) && (bmpPar->bi.biCompression == DIM_BMP_RLE8) )
  {    
    /*
    int x=0, y=0, b;
    register uchar *p = line[h-1];
    while ( y < h ) {
      if ( (b=d->getch()) == EOF )
        break;
      if ( b == 0 ) {     // escape code
        switch ( (b=d->getch()) ) {
        case 0:     // end of line
          x = 0;
          y++;
          p = line[h-y-1];
          break;
        case 1:     // end of image
        case EOF:   // end of file
          y = h;    // exit loop
          break;
        case 2:     // delta (jump)
          x += d->getch();
          y += d->getch();
          p = line[h-y-1] + x;
          break;
        default:    // absolute mode
          if ( d->readBlock( (char *)p, b ) != b )
            return FALSE;
          if ( (b & 1) == 1 )
            d->getch(); // align on word boundary
          x += b;
          p += b;
        }
      } else {      // encoded mode
        memset( p, d->getch(), b ); // repeat pixel
        x += b;
        p += b;
      }
    }
    */
  }
  
  //-------------------------------------------------
  // RGB BMP image
  //-------------------------------------------------  
  if ( bmpPar->bi.biBitCount == 16 || bmpPar->bi.biBitCount == 24 || bmpPar->bi.biBitCount == 32 )
  {  
    int h = bmpPar->bi.biHeight;
    unsigned char *bufF = new unsigned char [bplF];

    while ( --h >= 0 ) 
    {
      if ( dimRead( fmtHndl, bufF, bplF, 1 ) != 1 ) return 1;

      if ( bmpPar->bi.biBitCount == 16 )
      {
        // nothing yet
      }
      
      if ( bmpPar->bi.biBitCount == 24 )
      {
        unsigned long x = 0;
        DIM_UCHAR *p0 = ((unsigned char *) img->bits[0]) + ( h * bpl );
        DIM_UCHAR *p1 = ((unsigned char *) img->bits[1]) + ( h * bpl );
        DIM_UCHAR *p2 = ((unsigned char *) img->bits[2]) + ( h * bpl );
        for ( x=0; x<(unsigned long)bpl*3; x+=3 )
        {
          *p0 = bufF[x+2]; p0++; // R
          *p1 = bufF[x+1]; p1++; // G
          *p2 = bufF[x+0]; p2++; // B
        }
      }

      if ( bmpPar->bi.biBitCount == 32 )
      {
        unsigned long x = 0;
        DIM_UCHAR *p0 = ((unsigned char *) img->bits[0]) + ( h * bpl );
        DIM_UCHAR *p1 = ((unsigned char *) img->bits[1]) + ( h * bpl );
        DIM_UCHAR *p2 = ((unsigned char *) img->bits[2]) + ( h * bpl );
        DIM_UCHAR *p3 = ((unsigned char *) img->bits[3]) + ( h * bpl );
        for ( x=0; x<(unsigned long)bpl*4; x+=4 )
        {
          *p0 = bufF[x+3]; p0++; // R          
          *p1 = bufF[x+2]; p1++; // G
          *p2 = bufF[x+1]; p2++; // B
          *p3 = bufF[x+0]; p3++; // A
        }
      }

    }
    delete[] bufF;
  }

  return 0;}


//****************************************************************************
// WRITE PROC
//****************************************************************************

static int write_bmp_image(TDimFormatHandle *fmtHndl)
{
  if (fmtHndl == NULL) return 1;
  if (fmtHndl->internalParams == NULL) return 1;
  TDimBmpParams *bmpPar = (TDimBmpParams *) fmtHndl->internalParams;
  TDimImageBitmap *img = fmtHndl->image;
  //TDimImageInfo *info = &img->i;   
  
  unsigned long bpl = getLineSizeInBytes( img );
  unsigned long num_cols = getImgNumColors( img );
  unsigned long nbits = img->i.depth * img->i.samples;
  unsigned long bpl_bmp = (( img->i.width * nbits + 31)/32)*4;

  //-------------------------------------------------
  // write BMP header
  //-------------------------------------------------  
  memcpy( &bmpPar->bf.bfType, "BM", 2 );
  bmpPar->bf.bfReserved1 = bmpPar->bf.bfReserved2 = 0;  // reserved, should be zero
  if (nbits <= 8)
    bmpPar->bf.bfOffBits = BMP_FILEHDR_SIZE + DIM_BMP_WIN + num_cols*4;
  else
    bmpPar->bf.bfOffBits = BMP_FILEHDR_SIZE + DIM_BMP_WIN;
  bmpPar->bf.bfSize      = bmpPar->bf.bfOffBits + bpl_bmp * img->i.height;

  // swap structure elements if running on Big endian machine...
  if (dimBigendian) {
    dimSwapLong( (DIM_UINT32*) &bmpPar->bf.bfOffBits );
    dimSwapLong( (DIM_UINT32*) &bmpPar->bf.bfSize );
  }

  if (dimWrite( fmtHndl, &bmpPar->bf, 1, sizeof(bmpPar->bf) ) != sizeof(bmpPar->bf)) return 1;

  //-------------------------------------------------
  // write image header
  //------------------------------------------------- 
  bmpPar->bi.biSize          = DIM_BMP_WIN;   // build info header
  bmpPar->bi.biWidth         = img->i.width;
  bmpPar->bi.biHeight        = img->i.height;
  bmpPar->bi.biPlanes        = 1;
  bmpPar->bi.biBitCount      = (unsigned short) nbits;
  bmpPar->bi.biCompression   = DIM_BMP_RGB;
  bmpPar->bi.biSizeImage     = bpl_bmp * img->i.height;
  bmpPar->bi.biXPelsPerMeter = 2834; // 72 dpi default
  bmpPar->bi.biYPelsPerMeter = 2834;
  if (nbits <= 8) {
    bmpPar->bi.biClrUsed       = num_cols;
    bmpPar->bi.biClrImportant  = num_cols;
  }
  else {
    bmpPar->bi.biClrUsed       = 0;
    bmpPar->bi.biClrImportant  = 0;
  }

  if (dimBigendian) {
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biSize );    
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biWidth );  
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biHeight );  
    dimSwapShort( (DIM_UINT16*) &bmpPar->bi.biPlanes );
    dimSwapShort( (DIM_UINT16*) &bmpPar->bi.biBitCount );
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biCompression );    
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biSizeImage );    
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biXPelsPerMeter );    
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biYPelsPerMeter );    
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biClrUsed );    
    dimSwapLong( (DIM_UINT32*) &bmpPar->bi.biClrImportant );    
  }

  if (dimWrite( fmtHndl, &bmpPar->bi, 1, sizeof(bmpPar->bi) ) != sizeof(bmpPar->bi)) return 1;

  //-------------------------------------------------
  // write image palette if there's any
  //------------------------------------------------- 
  unsigned int i;
  if (nbits <= 8)
  {    
    unsigned char *color_table = new unsigned char [ num_cols*4 ];
    unsigned char *rgb = color_table;

    if (img->i.lut.count > 0)
      for ( i=0; i<num_cols; i++ ) 
      {
        *rgb++ = (unsigned char) dimB ( img->i.lut.rgba[i] );
        *rgb++ = (unsigned char) dimG ( img->i.lut.rgba[i] );
        *rgb++ = (unsigned char) dimR ( img->i.lut.rgba[i] );
        *rgb++ = 0;
      }
    else
      for ( i=0; i<num_cols; i++ ) 
      {
        *rgb++ = iTrimUC(i * (256/num_cols));
        *rgb++ = iTrimUC(i * (256/num_cols));
        *rgb++ = iTrimUC(i * (256/num_cols));
        *rgb++ = 0;
      }

    if ( dimWrite( fmtHndl, color_table, 1, num_cols*4 ) != num_cols*4) return 1;
    delete [] color_table;
  }


  //-------------------------------------------------
  // write image data
  //-------------------------------------------------
  unsigned char *buf = new unsigned char[bpl_bmp];
  memset( buf, 0, bpl_bmp );
  int h = img->i.height;

  while ( --h >= 0 ) 
  {
    
    if (nbits <= 8) 
    {
      DIM_UCHAR *p = ((unsigned char *) img->bits[0]) + ( h * bpl );
      memcpy( buf, p, bpl );
    }
  
    if ( nbits == 16 )
    {
      // nothing yet
    }
    
    if ( ( img->i.depth == 8 ) && ( img->i.samples == 3 ) )
    {
      unsigned long x = 0;
      DIM_UCHAR *p0 = ((unsigned char *) img->bits[0]) + ( h * bpl );
      DIM_UCHAR *p1 = ((unsigned char *) img->bits[1]) + ( h * bpl );
      DIM_UCHAR *p2 = ((unsigned char *) img->bits[2]) + ( h * bpl );
      for ( x=0; x<bpl*3; x+=3 )
      {
        buf[x+2] = *p0++; // R
        buf[x+1] = *p1++; // G
        buf[x+0] = *p2++; // B
      }
    }

    if ( ( img->i.depth == 8 ) && ( img->i.samples == 4 ) )
    {
      unsigned long x = 0;
      DIM_UCHAR *p0 = ((unsigned char *) img->bits[0]) + ( h * bpl );
      DIM_UCHAR *p1 = ((unsigned char *) img->bits[1]) + ( h * bpl );
      DIM_UCHAR *p2 = ((unsigned char *) img->bits[2]) + ( h * bpl );
      DIM_UCHAR *p3 = ((unsigned char *) img->bits[3]) + ( h * bpl );
      for ( x=0; x<bpl*4; x+=4 )
      {
        buf[x+3] = *p0++; // R
        buf[x+2] = *p1++; // G
        buf[x+1] = *p2++; // B
        buf[x+0] = *p3++; // A
      }
    }

    if (dimWrite( fmtHndl, buf, 1, bpl_bmp ) != bpl_bmp) return 1;

  } // while --h
  delete[] buf;

  dimFlush( fmtHndl );
  return 0;

}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -