(root)/
libpng-1.6.40/
contrib/
visupng/
PngFile.c
       1  /*-------------------------------------
       2   *  PNGFILE.C -- Image File Functions
       3   *-------------------------------------
       4   *
       5   * Copyright 2000,2017 Willem van Schaik.
       6   *
       7   * This code is released under the libpng license.
       8   * For conditions of distribution and use, see the disclaimer
       9   * and license in png.h
      10   */
      11  
      12  #include <windows.h>
      13  #include <commdlg.h>
      14  #include <stdio.h>
      15  #include <stdlib.h>
      16  #include <zlib.h>
      17  
      18  #include "png.h"
      19  #include "pngfile.h"
      20  #include "cexcept.h"
      21  
      22  define_exception_type(const char *);
      23  extern struct exception_context the_exception_context[1];
      24  struct exception_context the_exception_context[1];
      25  png_const_charp msg;
      26  
      27  static OPENFILENAME ofn;
      28  
      29  static png_structp png_ptr = NULL;
      30  static png_infop info_ptr = NULL;
      31  
      32  
      33  /* cexcept interface */
      34  
      35  static void
      36  png_cexcept_error(png_structp png_ptr, png_const_charp msg)
      37  {
      38     if(png_ptr)
      39       ;
      40  #ifdef PNG_CONSOLE_IO_SUPPORTED
      41     fprintf(stderr, "libpng error: %s\n", msg);
      42  #endif
      43     {
      44        Throw msg;
      45     }
      46  }
      47  
      48  /* Windows open-file functions */
      49  
      50  void PngFileInitialize (HWND hwnd)
      51  {
      52      static TCHAR szFilter[] = TEXT ("PNG Files (*.PNG)\0*.png\0")
      53          TEXT ("All Files (*.*)\0*.*\0\0");
      54  
      55      ofn.lStructSize       = sizeof (OPENFILENAME);
      56      ofn.hwndOwner         = hwnd;
      57      ofn.hInstance         = NULL;
      58      ofn.lpstrFilter       = szFilter;
      59      ofn.lpstrCustomFilter = NULL;
      60      ofn.nMaxCustFilter    = 0;
      61      ofn.nFilterIndex      = 0;
      62      ofn.lpstrFile         = NULL;          /* Set in Open and Close functions */
      63      ofn.nMaxFile          = MAX_PATH;
      64      ofn.lpstrFileTitle    = NULL;          /* Set in Open and Close functions */
      65      ofn.nMaxFileTitle     = MAX_PATH;
      66      ofn.lpstrInitialDir   = NULL;
      67      ofn.lpstrTitle        = NULL;
      68      ofn.Flags             = 0;             /* Set in Open and Close functions */
      69      ofn.nFileOffset       = 0;
      70      ofn.nFileExtension    = 0;
      71      ofn.lpstrDefExt       = TEXT ("png");
      72      ofn.lCustData         = 0;
      73      ofn.lpfnHook          = NULL;
      74      ofn.lpTemplateName    = NULL;
      75  }
      76  
      77  BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
      78  {
      79      ofn.hwndOwner         = hwnd;
      80      ofn.lpstrFile         = pstrFileName;
      81      ofn.lpstrFileTitle    = pstrTitleName;
      82      ofn.Flags             = OFN_HIDEREADONLY;
      83  
      84      return GetOpenFileName (&ofn);
      85  }
      86  
      87  BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
      88  {
      89      ofn.hwndOwner         = hwnd;
      90      ofn.lpstrFile         = pstrFileName;
      91      ofn.lpstrFileTitle    = pstrTitleName;
      92      ofn.Flags             = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
      93  
      94      return GetSaveFileName (&ofn);
      95  }
      96  
      97  /* PNG image handler functions */
      98  
      99  BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData,
     100                     int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor)
     101  {
     102      static FILE        *pfFile;
     103      png_byte            pbSig[8];
     104      int                 iBitDepth;
     105      int                 iColorType;
     106      double              dGamma;
     107      png_color_16       *pBackground;
     108      png_uint_32         ulChannels;
     109      png_uint_32         ulRowBytes;
     110      png_byte           *pbImageData = *ppbImageData;
     111      static png_byte   **ppbRowPointers = NULL;
     112      int                 i;
     113  
     114      /* open the PNG input file */
     115  
     116      if (!pstrFileName)
     117      {
     118          *ppbImageData = pbImageData = NULL;
     119          return FALSE;
     120      }
     121  
     122      if (!(pfFile = fopen(pstrFileName, "rb")))
     123      {
     124          *ppbImageData = pbImageData = NULL;
     125          return FALSE;
     126      }
     127  
     128      /* first check the eight byte PNG signature */
     129  
     130      fread(pbSig, 1, 8, pfFile);
     131      if (png_sig_cmp(pbSig, 0, 8))
     132      {
     133          *ppbImageData = pbImageData = NULL;
     134          return FALSE;
     135      }
     136  
     137      /* create the two png(-info) structures */
     138  
     139      png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
     140        (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
     141      if (!png_ptr)
     142      {
     143          *ppbImageData = pbImageData = NULL;
     144          return FALSE;
     145      }
     146  
     147      info_ptr = png_create_info_struct(png_ptr);
     148      if (!info_ptr)
     149      {
     150          png_destroy_read_struct(&png_ptr, NULL, NULL);
     151          *ppbImageData = pbImageData = NULL;
     152          return FALSE;
     153      }
     154  
     155      Try
     156      {
     157  
     158          /* initialize the png structure */
     159  
     160  #ifdef PNG_STDIO_SUPPORTED
     161          png_init_io(png_ptr, pfFile);
     162  #else
     163          png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);
     164  #endif
     165  
     166          png_set_sig_bytes(png_ptr, 8);
     167  
     168          /* read all PNG info up to image data */
     169  
     170          png_read_info(png_ptr, info_ptr);
     171  
     172          /* get width, height, bit-depth and color-type */
     173  
     174          png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
     175              &iColorType, NULL, NULL, NULL);
     176  
     177          /* expand images of all color-type and bit-depth to 3x8-bit RGB */
     178          /* let the library process alpha, transparency, background, etc. */
     179  
     180  #ifdef PNG_READ_16_TO_8_SUPPORTED
     181      if (iBitDepth == 16)
     182  #  ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
     183          png_set_scale_16(png_ptr);
     184  #  else
     185          png_set_strip_16(png_ptr);
     186  #  endif
     187  #endif
     188          if (iColorType == PNG_COLOR_TYPE_PALETTE)
     189              png_set_expand(png_ptr);
     190          if (iBitDepth < 8)
     191              png_set_expand(png_ptr);
     192          if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
     193              png_set_expand(png_ptr);
     194          if (iColorType == PNG_COLOR_TYPE_GRAY ||
     195              iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
     196              png_set_gray_to_rgb(png_ptr);
     197  
     198          /* set the background color to draw transparent and alpha images over */
     199          if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
     200          {
     201              png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
     202              pBkgColor->red   = (byte) pBackground->red;
     203              pBkgColor->green = (byte) pBackground->green;
     204              pBkgColor->blue  = (byte) pBackground->blue;
     205          }
     206          else
     207          {
     208              pBkgColor = NULL;
     209          }
     210  
     211          /* if required set gamma conversion */
     212          if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
     213              png_set_gamma(png_ptr, (double) 2.2, dGamma);
     214  
     215          /* after the transformations are registered, update info_ptr data */
     216  
     217          png_read_update_info(png_ptr, info_ptr);
     218  
     219          /* get again width, height and the new bit-depth and color-type */
     220  
     221          png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
     222              &iColorType, NULL, NULL, NULL);
     223  
     224  
     225          /* row_bytes is the width x number of channels */
     226  
     227          ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
     228          ulChannels = png_get_channels(png_ptr, info_ptr);
     229  
     230          *piChannels = ulChannels;
     231  
     232          /* now we can allocate memory to store the image */
     233  
     234          if (pbImageData)
     235          {
     236              free (pbImageData);
     237              pbImageData = NULL;
     238          }
     239          if ((*piHeight) > ((size_t)(-1))/ulRowBytes) {
     240          {
     241              png_error(png_ptr, "Visual PNG: image is too big");
     242          }
     243          if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight)
     244                              * sizeof(png_byte))) == NULL)
     245          {
     246              png_error(png_ptr, "Visual PNG: out of memory");
     247          }
     248          *ppbImageData = pbImageData;
     249  
     250          /* and allocate memory for an array of row-pointers */
     251  
     252          if ((ppbRowPointers = (png_bytepp) malloc((*piHeight)
     253                              * sizeof(png_bytep))) == NULL)
     254          {
     255              png_error(png_ptr, "Visual PNG: out of memory");
     256          }
     257  
     258          /* set the individual row-pointers to point at the correct offsets */
     259  
     260          for (i = 0; i < (*piHeight); i++)
     261              ppbRowPointers[i] = pbImageData + i * ulRowBytes;
     262  
     263          /* now we can go ahead and just read the whole image */
     264  
     265          png_read_image(png_ptr, ppbRowPointers);
     266  
     267          /* read the additional chunks in the PNG file (not really needed) */
     268  
     269          png_read_end(png_ptr, NULL);
     270  
     271          /* and we're done */
     272  
     273          free (ppbRowPointers);
     274          ppbRowPointers = NULL;
     275  
     276          /* yepp, done */
     277      }
     278  
     279      Catch (msg)
     280      {
     281          png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
     282  
     283          *ppbImageData = pbImageData = NULL;
     284  
     285          if(ppbRowPointers)
     286              free (ppbRowPointers);
     287  
     288          fclose(pfFile);
     289  
     290          return FALSE;
     291      }
     292  
     293      fclose (pfFile);
     294  
     295      return TRUE;
     296  }
     297  
     298  
     299  BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData,
     300                     int iWidth, int iHeight, png_color bkgColor)
     301  {
     302      const int           ciBitDepth = 8;
     303      const int           ciChannels = 3;
     304  
     305      static FILE        *pfFile;
     306      png_uint_32         ulRowBytes;
     307      static png_byte   **ppbRowPointers = NULL;
     308      int                 i;
     309  
     310      /* open the PNG output file */
     311  
     312      if (!pstrFileName)
     313          return FALSE;
     314  
     315      if (!(pfFile = fopen(pstrFileName, "wb")))
     316          return FALSE;
     317  
     318      /* prepare the standard PNG structures */
     319  
     320      png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
     321        (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
     322      if (!png_ptr)
     323      {
     324          fclose(pfFile);
     325          return FALSE;
     326      }
     327  
     328      info_ptr = png_create_info_struct(png_ptr);
     329      if (!info_ptr) {
     330          fclose(pfFile);
     331          png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
     332          return FALSE;
     333      }
     334  
     335      Try
     336      {
     337          /* initialize the png structure */
     338  
     339  #ifdef PNG_STDIO_SUPPORTED
     340          png_init_io(png_ptr, pfFile);
     341  #else
     342          png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush);
     343  #endif
     344  
     345          /* we're going to write a very simple 3x8-bit RGB image */
     346  
     347          png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth,
     348              PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
     349              PNG_FILTER_TYPE_BASE);
     350  
     351          /* write the file header information */
     352  
     353          png_write_info(png_ptr, info_ptr);
     354  
     355          /* swap the BGR pixels in the DiData structure to RGB */
     356  
     357          png_set_bgr(png_ptr);
     358  
     359          /* row_bytes is the width x number of channels */
     360  
     361          ulRowBytes = iWidth * ciChannels;
     362  
     363          /* we can allocate memory for an array of row-pointers */
     364  
     365          if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL)
     366              Throw "Visualpng: Out of memory";
     367  
     368          /* set the individual row-pointers to point at the correct offsets */
     369  
     370          for (i = 0; i < iHeight; i++)
     371              ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2);
     372  
     373          /* write out the entire image data in one call */
     374  
     375          png_write_image (png_ptr, ppbRowPointers);
     376  
     377          /* write the additional chunks to the PNG file (not really needed) */
     378  
     379          png_write_end(png_ptr, info_ptr);
     380  
     381          /* and we're done */
     382  
     383          free (ppbRowPointers);
     384          ppbRowPointers = NULL;
     385  
     386          /* clean up after the write, and free any memory allocated */
     387  
     388          png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
     389  
     390          /* yepp, done */
     391      }
     392  
     393      Catch (msg)
     394      {
     395          png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
     396  
     397          if(ppbRowPointers)
     398              free (ppbRowPointers);
     399  
     400          fclose(pfFile);
     401  
     402          return FALSE;
     403      }
     404  
     405      fclose (pfFile);
     406  
     407      return TRUE;
     408  }
     409  
     410  #ifndef PNG_STDIO_SUPPORTED
     411  
     412  static void
     413  png_read_data(png_structp png_ptr, png_bytep data, size_t length)
     414  {
     415     size_t check;
     416  
     417     /* fread() returns 0 on error, so it is OK to store this in a size_t
     418      * instead of an int, which is what fread() actually returns.
     419      */
     420     check = fread(data, 1, length, (FILE *)png_ptr->io_ptr);
     421  
     422     if (check != length)
     423     {
     424        png_error(png_ptr, "Read Error");
     425     }
     426  }
     427  
     428  static void
     429  png_write_data(png_structp png_ptr, png_bytep data, size_t length)
     430  {
     431     png_uint_32 check;
     432  
     433     check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
     434     if (check != length)
     435     {
     436        png_error(png_ptr, "Write Error");
     437     }
     438  }
     439  
     440  static void
     441  png_flush(png_structp png_ptr)
     442  {
     443     FILE *io_ptr;
     444     io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
     445     if (io_ptr != NULL)
     446        fflush(io_ptr);
     447  }
     448  
     449  #endif
     450  
     451  /*-----------------
     452   *  end of source
     453   *-----------------
     454   */