<commit_before>/*=========================================================================


  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkPNGImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkPNGImageIO.h"
#include "itkRGBPixel.h"
#include "itkRGBAPixel.h"
#include "png.h"
#include <itksys/SystemTools.hxx>

namespace itk
{

extern "C"
{
  /* The PNG library does not expect the error function to return.
     Therefore we must use this ugly longjmp call.  */
  void itkPNGWriteErrorFunction(png_structp png_ptr,
                                png_const_charp itkNotUsed(error_msg))
  {
    longjmp(png_ptr->jmpbuf, 1);
  }
}


extern "C"
{
  void itkPNGWriteWarningFunction(png_structp itkNotUsed(png_ptr),
                                  png_const_charp itkNotUsed(warning_msg))
  {
  }
}


// simple class to call fopen on construct and
// fclose on destruct
class PNGFileWrapper
{
public:
  PNGFileWrapper(const char * const fname, const char * const openMode):m_FilePointer(NULL)
  {
    m_FilePointer = fopen(fname, openMode);
  }
  virtual ~PNGFileWrapper()
  {
    if(m_FilePointer)
      {
      fclose(m_FilePointer);
      }
  }
  FILE* m_FilePointer;
};

bool PNGImageIO::CanReadFile(const char* file) 
{ 
  // First check the extension
  std::string filename = file;
  if(  filename == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  // Now check the file header
  PNGFileWrapper pngfp(file,"rb");
  if(pngfp.m_FilePointer==NULL)
    {
    return false;
    }
  unsigned char header[8];
  fread(header, 1, 8, pngfp.m_FilePointer);
  bool is_png = !png_sig_cmp(header, 0, 8);
  if(!is_png)
    {
    return false;
    }
  png_structp png_ptr = png_create_read_struct
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
     NULL, NULL);
  if (!png_ptr)
    {
    return false;
    }
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
    png_destroy_read_struct(&png_ptr,
                            (png_infopp)NULL, (png_infopp)NULL);
    return false;
    }
  
  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info)
    {
    png_destroy_read_struct(&png_ptr, &info_ptr,
                            (png_infopp)NULL);
    return false;
    }
  png_destroy_read_struct(&png_ptr, &info_ptr,
                          &end_info);
  
  return true;
}
  
  
void PNGImageIO::ReadVolume(void*)
{
  
}

  
void PNGImageIO::Read(void* buffer)
{
  itkDebugMacro("Read: file dimensions = " << this->GetNumberOfDimensions() );
  // use this class so return will call close
  PNGFileWrapper pngfp(this->GetFileName(),"rb"); 
  FILE* fp = pngfp.m_FilePointer;
  if(!fp)
    {
    itkExceptionMacro("PNGImageIO could not open file: "
                      << this->GetFileName() << " for reading."
                      << std::endl
                      << "Reason: "
                      << itksys::SystemTools::GetLastSystemError());
    return;
    }
  unsigned char header[8];
  fread(header, 1, 8, fp);
  bool is_png = !png_sig_cmp(header, 0, 8);
  if(!is_png)
    {
    itkExceptionMacro("File is not png type: " << this->GetFileName());
    return;
    }
  png_structp png_ptr = png_create_read_struct
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
     NULL, NULL);
  if (!png_ptr)
    {
    itkExceptionMacro("File is not png type" << this->GetFileName());
    return;
    }
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
    png_destroy_read_struct(&png_ptr,
                            (png_infopp)NULL, (png_infopp)NULL);
    itkExceptionMacro("File is not png type " << this->GetFileName());
    return;
    }

  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info)
    {
    png_destroy_read_struct(&png_ptr, &info_ptr,
                            (png_infopp)NULL);
    itkExceptionMacro("File is not png type " << this->GetFileName());
    return;
    }
  
  if( setjmp( png_jmpbuf( png_ptr ) ) )
    {
    png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
    itkExceptionMacro("File is not png type " << this->GetFileName());
    return;    
    }

  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);

  png_read_info(png_ptr, info_ptr);

  png_uint_32 width, height;
  int bitDepth, colorType, interlaceType;
  int compression_type, filter_method;
  png_get_IHDR(png_ptr, info_ptr, 
               &width, &height,
               &bitDepth, &colorType, &interlaceType,
               &compression_type, &filter_method);

  // convert palettes to RGB
  if (colorType == PNG_COLOR_TYPE_PALETTE)
    {
    png_set_palette_to_rgb(png_ptr);
    }

  // minimum of a byte per pixel
  if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) 
    {
    png_set_gray_1_2_4_to_8(png_ptr);
    }

  // add alpha if any alpha found
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
    {
    png_set_tRNS_to_alpha(png_ptr);
    }

  if (bitDepth > 8)
    {
#ifndef ITK_WORDS_BIGENDIAN
    png_set_swap(png_ptr);
#endif
    }

  // have libpng handle interlacing
  //int number_of_passes = png_set_interlace_handling(png_ptr);
  // update the info now that we have defined the filters
  png_read_update_info(png_ptr, info_ptr);

  unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  unsigned char *tempImage = static_cast<unsigned char*>(buffer);
  png_bytep *row_pointers = new png_bytep [height];
  for (unsigned int ui = 0; ui < height; ++ui)
    {
    row_pointers[ui] = tempImage + rowbytes*ui;
    }
  png_read_image(png_ptr, row_pointers);
  delete [] row_pointers;
  // close the file
  png_read_end(png_ptr, NULL);<commit_msg>BUG: reader was not shifting data when it was encoded in the image.<commit_after>/*=========================================================================


  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkPNGImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkPNGImageIO.h"
#include "itkRGBPixel.h"
#include "itkRGBAPixel.h"
#include "png.h"
#include <itksys/SystemTools.hxx>

namespace itk
{

extern "C"
{
  /* The PNG library does not expect the error function to return.
     Therefore we must use this ugly longjmp call.  */
  void itkPNGWriteErrorFunction(png_structp png_ptr,
                                png_const_charp itkNotUsed(error_msg))
  {
    longjmp(png_ptr->jmpbuf, 1);
  }
}


extern "C"
{
  void itkPNGWriteWarningFunction(png_structp itkNotUsed(png_ptr),
                                  png_const_charp itkNotUsed(warning_msg))
  {
  }
}


// simple class to call fopen on construct and
// fclose on destruct
class PNGFileWrapper
{
public:
  PNGFileWrapper(const char * const fname, const char * const openMode):m_FilePointer(NULL)
  {
    m_FilePointer = fopen(fname, openMode);
  }
  virtual ~PNGFileWrapper()
  {
    if(m_FilePointer)
      {
      fclose(m_FilePointer);
      }
  }
  FILE* m_FilePointer;
};

bool PNGImageIO::CanReadFile(const char* file) 
{ 
  // First check the extension
  std::string filename = file;
  if(  filename == "" )
    {
    itkDebugMacro(<<"No filename specified.");
    return false;
    }

  // Now check the file header
  PNGFileWrapper pngfp(file,"rb");
  if(pngfp.m_FilePointer==NULL)
    {
    return false;
    }
  unsigned char header[8];
  fread(header, 1, 8, pngfp.m_FilePointer);
  bool is_png = !png_sig_cmp(header, 0, 8);
  if(!is_png)
    {
    return false;
    }
  png_structp png_ptr = png_create_read_struct
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
     NULL, NULL);
  if (!png_ptr)
    {
    return false;
    }
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
    png_destroy_read_struct(&png_ptr,
                            (png_infopp)NULL, (png_infopp)NULL);
    return false;
    }
  
  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info)
    {
    png_destroy_read_struct(&png_ptr, &info_ptr,
                            (png_infopp)NULL);
    return false;
    }
  png_destroy_read_struct(&png_ptr, &info_ptr,
                          &end_info);
  
  return true;
}
  
  
void PNGImageIO::ReadVolume(void*)
{
  
}

  
void PNGImageIO::Read(void* buffer)
{
  itkDebugMacro("Read: file dimensions = " << this->GetNumberOfDimensions() );
  // use this class so return will call close
  PNGFileWrapper pngfp(this->GetFileName(),"rb"); 
  FILE* fp = pngfp.m_FilePointer;
  if(!fp)
    {
    itkExceptionMacro("PNGImageIO could not open file: "
                      << this->GetFileName() << " for reading."
                      << std::endl
                      << "Reason: "
                      << itksys::SystemTools::GetLastSystemError());
    return;
    }
  unsigned char header[8];
  fread(header, 1, 8, fp);
  bool is_png = !png_sig_cmp(header, 0, 8);
  if(!is_png)
    {
    itkExceptionMacro("File is not png type: " << this->GetFileName());
    return;
    }
  png_structp png_ptr = png_create_read_struct
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
     NULL, NULL);
  if (!png_ptr)
    {
    itkExceptionMacro("File is not png type" << this->GetFileName());
    return;
    }
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
    png_destroy_read_struct(&png_ptr,
                            (png_infopp)NULL, (png_infopp)NULL);
    itkExceptionMacro("File is not png type " << this->GetFileName());
    return;
    }

  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info)
    {
    png_destroy_read_struct(&png_ptr, &info_ptr,
                            (png_infopp)NULL);
    itkExceptionMacro("File is not png type " << this->GetFileName());
    return;
    }
  
  if( setjmp( png_jmpbuf( png_ptr ) ) )
    {
    png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
    itkExceptionMacro("File is not png type " << this->GetFileName());
    return;    
    }

  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);

  png_read_info(png_ptr, info_ptr);

  png_uint_32 width, height;
  int bitDepth, colorType, interlaceType;
  int compression_type, filter_method;
  png_get_IHDR(png_ptr, info_ptr, 
               &width, &height,
               &bitDepth, &colorType, &interlaceType,
               &compression_type, &filter_method);

  // convert palettes to RGB
  if (colorType == PNG_COLOR_TYPE_PALETTE)
    {
    png_set_palette_to_rgb(png_ptr);
    }

  // minimum of a byte per pixel
  if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) 
    {
    png_set_gray_1_2_4_to_8(png_ptr);
    }

  // add alpha if any alpha found
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
    {
    png_set_tRNS_to_alpha(png_ptr);
    }

  if (bitDepth > 8)
    {
#ifndef ITK_WORDS_BIGENDIAN
    png_set_swap(png_ptr);
#endif
    }

  if (info_ptr->valid & PNG_INFO_sBIT)
    {
    png_set_shift(png_ptr, &(info_ptr->sig_bit));
    }
  // have libpng handle interlacing
  //int number_of_passes = png_set_interlace_handling(png_ptr);
  // update the info now that we have defined the filters
  png_read_update_info(png_ptr, info_ptr);

  unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  unsigned char *tempImage = static_cast<unsigned char*>(buffer);
  png_bytep *row_pointers = new png_bytep [height];
  for (unsigned int ui = 0; ui < height; ++ui)
    {
    row_pointers[ui] = tempImage + rowbytes*ui;
    }
  png_read_image(png_ptr, row_pointers);
  delete [] row_pointers;
  // close the file
  png_read_end(png_ptr, NULL);
{'fraction_non_alphanumeric': 0.12864646464646465, 'fraction_numerical': 0.003393939393939394, 'mean_word_length': 2.9871134020618557, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2067063', 'n_tokens_mistral': 4474, 'n_tokens_neox': 4232, 'n_words': 908}