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

📄 dim_png_format_io.cpp

📁 Digital Notebook Source Code v1.1.0 [
💻 CPP
字号:
/*****************************************************************************
  PNG 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/>

  History:
    07/29/2004 16:31 - First creation
    08/04/2004 22:25 - Update to FMT_IFS 1.2, support for io protorypes
        
  Ver : 2
*****************************************************************************/

#include <string>

// Disables Visual Studio 2005 warnings for deprecated code#ifdef WIN32   #pragma warning(disable:4996)#endif

#include "dim_png_format.h"

//****************************************************************************
// READ PROC
//****************************************************************************

static int read_png_image(TDimFormatHandle *fmtHndl)
{
  if (fmtHndl == NULL) return 1;
  if (fmtHndl->internalParams == NULL) return 1;
  TDimPngParams *pngPar = (TDimPngParams *) fmtHndl->internalParams;
  TDimImageInfo *info = &pngPar->i;  
  TDimImageBitmap *img = fmtHndl->image;
  
  //-------------------------------------------------
  // init the image
  //-------------------------------------------------
  if ( allocImg( fmtHndl, info, img) != 0 ) return 1;

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

  if (setjmp( png_jmpbuf(pngPar->png_ptr) ))
  {
    png_destroy_read_struct( &pngPar->png_ptr, &pngPar->info_ptr, &pngPar->end_info );
    return 1;
  }

  int num_passes = png_set_interlace_handling( pngPar->png_ptr );
  int pass;

  unsigned int bpl = getLineSizeInBytes( img );  
  unsigned long h = info->height;
  unsigned long y = 0;
 
  if (img->i.samples == 1)
  {
    for ( pass=0; pass<num_passes; pass++ )
    {
      while ( y < h ) 
      {
        png_bytep p = ((unsigned char *) img->bits[0]) + ( y * bpl );
        png_read_row( pngPar->png_ptr, p, NULL );
        y++;
      }
      y = 0;
    } // interlace passes
  }
  else
  { // multi samples (channels)
    unsigned char *buf = new unsigned char [ bpl * img->i.samples ];
    
    if (num_passes == 0)
    { // faster code in the case of non interlaced image

      while ( y < h ) 
      {
        png_bytep pbuf = buf;
        png_read_row( pngPar->png_ptr, pbuf, NULL ); 

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

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

        y++;
      } // while
    }
    else
    {  // slower code which handles interlaced images
      memset( img->bits[0], 0, bpl * h );
      memset( img->bits[1], 0, bpl * h );
      memset( img->bits[2], 0, bpl * h );

      for ( pass=0; pass<num_passes; pass++ )
      {    
        while ( y < h ) 
        {
          png_bytep pbuf = buf;
          memset( buf, 0, bpl * img->i.samples );
          png_read_row( pngPar->png_ptr, pbuf, NULL ); 

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

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

          y++;
        } // while
        y = 0;
      } // interlace passes
    } // interlaced code
    delete [] buf;
  }

  png_read_end( pngPar->png_ptr, pngPar->end_info );

  return 0;
}


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

static int write_png_image(TDimFormatHandle *fmtHndl)
{
  if (fmtHndl == NULL) return 1;
  if (fmtHndl->internalParams == NULL) return 1;
  TDimPngParams *pngPar = (TDimPngParams *) fmtHndl->internalParams;
  TDimImageBitmap *img = fmtHndl->image;
  TDimImageInfo *info = &img->i; 

  if (setjmp( png_jmpbuf(pngPar->png_ptr) ))
  {
    png_destroy_read_struct( &pngPar->png_ptr, &pngPar->info_ptr, &pngPar->end_info );
    return 1;
  }
  
  int color_type = PNG_COLOR_TYPE_GRAY;;
  if ( info->samples == 1 ) color_type = PNG_COLOR_TYPE_GRAY;
  if ( info->samples == 2 ) color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  if ( info->samples == 3 ) color_type = PNG_COLOR_TYPE_RGB;
  if ( info->samples == 4 ) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  if ( info->imageMode == DIM_INDEXED ) color_type = PNG_COLOR_TYPE_PALETTE;

  png_set_IHDR( pngPar->png_ptr, pngPar->info_ptr, info->width, info->height, info->depth, color_type, 
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);


  //-------------------------------------------------
  // write palette if any
  //-------------------------------------------------

  if ( ( color_type == PNG_COLOR_TYPE_PALETTE ) && ( info->lut.count > 0 ) )
  {
    int i;
    int num_colors = info->lut.count;
    png_colorp palette = new png_color[ num_colors ];
    png_set_PLTE( pngPar->png_ptr, pngPar->info_ptr, palette, num_colors );

    for ( i=0; i<num_colors; i++ ) 
    {
      pngPar->info_ptr->palette[i].red   = (unsigned char) dimR( info->lut.rgba[i] );
      pngPar->info_ptr->palette[i].green = (unsigned char) dimG( info->lut.rgba[i] );
      pngPar->info_ptr->palette[i].blue  = (unsigned char) dimB( info->lut.rgba[i] );
    }  

  } // if paletted


  //-------------------------------------------------
  // write meta text if any
  //-------------------------------------------------
  if ( ( fmtHndl->metaData.count > 0 ) && ( fmtHndl->metaData.tags != NULL ) )
  {
    TDimTagList *tagList = &fmtHndl->metaData;
    png_textp text_ptr = new png_text[ tagList->count ];    
    std::string str = "", keystr = ""; 
    unsigned int i;

    for (i=0; i<tagList->count; i++)
    {
      TDimTagItem *tagItem = &tagList->tags[i];
      str = "";
      keystr = tagItem->tagId;

      if ( tagItem->tagType == DIM_TAG_ASCII ) 
        str = (char *) tagItem->tagData;
      
      if ( str.size() < 40 )
        text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE;
      else
        text_ptr[i].compression = PNG_TEXT_COMPRESSION_zTXt;

      char *keychar = new char [ keystr.size() ];
      char *strchar = new char [ str.size() ];
      strcpy ( keychar, keystr.c_str() );
      strcpy ( strchar, str.c_str() );

      text_ptr[i].key  = (png_charp) keychar;
      text_ptr[i].text = (png_charp) strchar;

    } // for i

    png_set_text( pngPar->png_ptr, pngPar->info_ptr, text_ptr, tagList->count );
    delete [] text_ptr;
  } // if there are meta tags

  //-------------------------------------------------
  // write image
  //-------------------------------------------------
  png_write_info( pngPar->png_ptr, pngPar->info_ptr );
  if ( (info->depth > 8) && (!dimBigendian) )  png_set_swap( pngPar->png_ptr );

  unsigned int bpl = getLineSizeInBytes( img );  
  unsigned long h = info->height;
  unsigned long y = 0;

  if (img->i.samples == 1)
  {
    while ( y < h ) 
    {
      png_bytep p = ((unsigned char *) img->bits[0]) + ( y * bpl );
      png_write_row( pngPar->png_ptr, p );
      y++;
    }
    y = 0;
  }
  else
  { // multi samples (channels)
    unsigned char *buf = new unsigned char [ bpl * img->i.samples ];

    while ( y < h ) 
    {
      png_bytep pbuf = buf;

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

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

      png_write_row( pngPar->png_ptr, pbuf );

      y++;
    } // while
 
    delete [] buf;
  }

  png_write_end( pngPar->png_ptr, pngPar->info_ptr );

  return 0;
}

//****************************************************************************
// READ METADATA TEXT PROC
//****************************************************************************

static char *png_read_meta_as_text(TDimFormatHandle *fmtHndl)
{
  if (fmtHndl == NULL) return NULL;
  if (fmtHndl->internalParams == NULL) return NULL;
  TDimPngParams *pngPar = (TDimPngParams *) fmtHndl->internalParams;

  char *buf = NULL;
  std::string str = ""; 
  
  if (setjmp( png_jmpbuf(pngPar->png_ptr) ))
  {
    png_destroy_read_struct( &pngPar->png_ptr, &pngPar->info_ptr, &pngPar->end_info );
    return NULL;
  }

  png_textp text_ptr;
  int num_text = 0;
  png_get_text( pngPar->png_ptr, pngPar->info_ptr, &text_ptr, &num_text );

  while (num_text--) 
  {
    str += "[ Key: ";   
    str += text_ptr->key;
    str += " ]\n";
    str += text_ptr->text;
    str += "\n\n";
    text_ptr++;
  }

  buf = new char [str.size()+1];
  buf[str.size()] = '\0';
  memcpy( buf, str.c_str(), str.size() );
  
  return buf;
}

//----------------------------------------------------------------------------
// read meta data tag by tag
//----------------------------------------------------------------------------

static DIM_UINT add_one_png_tag (TDimFormatHandle *fmtHndl, int tag, const char* str)
{
  DIM_UCHAR *buf = NULL;
  DIM_UINT32 buf_size = strlen(str);
  DIM_UINT32 buf_type = DIM_TAG_ASCII;

  if ( (buf_size == 0) || (str == NULL) ) return 1;
  else
  {
    // now add tag into structure
    TDimTagItem item;

    buf = (unsigned char *) dimMalloc(fmtHndl, buf_size + 1);
    strncpy((char *) buf, str, buf_size);
    buf[buf_size] = '\0';

    item.tagGroup  = DIM_META_PNG;
    item.tagId     = tag;
    item.tagType   = buf_type;
    item.tagLength = buf_size;
    item.tagData   = buf;

    addMetaTag( &fmtHndl->metaData, item);
  }

  return 0;
}

static DIM_UINT read_png_metadata (TDimFormatHandle *fmtHndl, int group, int tag, int type)
{
  if (fmtHndl == NULL) return 1;
  if (fmtHndl->internalParams == NULL) return 1;
  TDimPngParams *pngPar = (TDimPngParams *) fmtHndl->internalParams;
  
  if ( (group != DIM_META_PNG) && (group != -1) ) return 1;

  if (setjmp( png_jmpbuf(pngPar->png_ptr) ))
  {
    png_destroy_read_struct( &pngPar->png_ptr, &pngPar->info_ptr, &pngPar->end_info );
    return 1;
  }

  std::string str = ""; 
  png_textp text_ptr;
  int num_text = 0;
  png_get_text( pngPar->png_ptr, pngPar->info_ptr, &text_ptr, &num_text );

  int i = 0;
  while ( i < num_text) 
  {
    str = "";
    str += "[Key: ";   
    str += text_ptr->key;
    str += "]\n";
    str += text_ptr->text;
    
    add_one_png_tag ( fmtHndl, i, str.c_str() );

    text_ptr++;
    i--;
  }

  tag; type;
  return 0;
}















⌨️ 快捷键说明

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