fukasawa e60969
fukasawa e60969
/* png.c - location for general purpose libpng functions
fukasawa e60969
 *
fukasawa e60969
 * Last changed in libpng 1.6.19 [November 12, 2015]
fukasawa e60969
 * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
fukasawa e60969
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
fukasawa e60969
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
fukasawa e60969
 *
fukasawa e60969
 * This code is released under the libpng license.
fukasawa e60969
 * For conditions of distribution and use, see the disclaimer
fukasawa e60969
 * and license in png.h
fukasawa e60969
 */
fukasawa e60969
fukasawa e60969
#include "pngpriv.h"
fukasawa e60969
fukasawa e60969
/* Generate a compiler error if there is an old png.h in the search path. */
fukasawa e60969
typedef png_libpng_version_1_6_21 Your_png_h_is_not_version_1_6_21;
fukasawa e60969
fukasawa e60969
/* Tells libpng that we have already handled the first "num_bytes" bytes
fukasawa e60969
 * of the PNG file signature.  If the PNG data is embedded into another
fukasawa e60969
 * stream we can set num_bytes = 8 so that libpng will not attempt to read
fukasawa e60969
 * or write any of the magic bytes before it starts on the IHDR.
fukasawa e60969
 */
fukasawa e60969
fukasawa e60969
#ifdef PNG_READ_SUPPORTED
fukasawa e60969
void PNGAPI
fukasawa e60969
png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
fukasawa e60969
{
fukasawa e60969
   unsigned int nb = (unsigned int)num_bytes;
fukasawa e60969
fukasawa e60969
   png_debug(1, "in png_set_sig_bytes");
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   if (num_bytes < 0)
fukasawa e60969
      nb = 0;
fukasawa e60969
fukasawa e60969
   if (nb > 8)
fukasawa e60969
      png_error(png_ptr, "Too many bytes for PNG signature");
fukasawa e60969
fukasawa e60969
   png_ptr->sig_bytes = (png_byte)nb;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Checks whether the supplied bytes match the PNG signature.  We allow
fukasawa e60969
 * checking less than the full 8-byte signature so that those apps that
fukasawa e60969
 * already read the first few bytes of a file to determine the file type
fukasawa e60969
 * can simply check the remaining bytes for extra assurance.  Returns
fukasawa e60969
 * an integer less than, equal to, or greater than zero if sig is found,
fukasawa e60969
 * respectively, to be less than, to match, or be greater than the correct
fukasawa e60969
 * PNG signature (this is the same behavior as strcmp, memcmp, etc).
fukasawa e60969
 */
fukasawa e60969
int PNGAPI
fukasawa e60969
png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check)
fukasawa e60969
{
fukasawa e60969
   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
fukasawa e60969
fukasawa e60969
   if (num_to_check > 8)
fukasawa e60969
      num_to_check = 8;
fukasawa e60969
fukasawa e60969
   else if (num_to_check < 1)
fukasawa e60969
      return (-1);
fukasawa e60969
fukasawa e60969
   if (start > 7)
fukasawa e60969
      return (-1);
fukasawa e60969
fukasawa e60969
   if (start + num_to_check > 8)
fukasawa e60969
      num_to_check = 8 - start;
fukasawa e60969
fukasawa e60969
   return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#endif /* READ */
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
fukasawa e60969
/* Function to allocate memory for zlib */
fukasawa e60969
PNG_FUNCTION(voidpf /* PRIVATE */,
fukasawa e60969
png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
fukasawa e60969
{
fukasawa e60969
   png_alloc_size_t num_bytes = size;
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return NULL;
fukasawa e60969
fukasawa e60969
   if (items >= (~(png_alloc_size_t)0)/size)
fukasawa e60969
   {
fukasawa e60969
      png_warning (png_voidcast(png_structrp, png_ptr),
fukasawa e60969
         "Potential overflow in png_zalloc()");
fukasawa e60969
      return NULL;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   num_bytes *= items;
fukasawa e60969
   return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Function to free memory for zlib */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_zfree(voidpf png_ptr, voidpf ptr)
fukasawa e60969
{
fukasawa e60969
   png_free(png_voidcast(png_const_structrp,png_ptr), ptr);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Reset the CRC variable to 32 bits of 1's.  Care must be taken
fukasawa e60969
 * in case CRC is > 32 bits to leave the top bits 0.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_reset_crc(png_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   /* The cast is safe because the crc is a 32-bit value. */
fukasawa e60969
   png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Calculate the CRC over a section of data.  We can only pass as
fukasawa e60969
 * much data to this routine as the largest single buffer size.  We
fukasawa e60969
 * also check that this data will actually be used before going to the
fukasawa e60969
 * trouble of calculating it.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
fukasawa e60969
{
fukasawa e60969
   int need_crc = 1;
fukasawa e60969
fukasawa e60969
   if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
fukasawa e60969
   {
fukasawa e60969
      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
fukasawa e60969
          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
fukasawa e60969
         need_crc = 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else /* critical */
fukasawa e60969
   {
fukasawa e60969
      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
fukasawa e60969
         need_crc = 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* 'uLong' is defined in zlib.h as unsigned long; this means that on some
fukasawa e60969
    * systems it is a 64-bit value.  crc32, however, returns 32 bits so the
fukasawa e60969
    * following cast is safe.  'uInt' may be no more than 16 bits, so it is
fukasawa e60969
    * necessary to perform a loop here.
fukasawa e60969
    */
fukasawa e60969
   if (need_crc != 0 && length > 0)
fukasawa e60969
   {
fukasawa e60969
      uLong crc = png_ptr->crc; /* Should never issue a warning */
fukasawa e60969
fukasawa e60969
      do
fukasawa e60969
      {
fukasawa e60969
         uInt safe_length = (uInt)length;
fukasawa e60969
#ifndef __COVERITY__
fukasawa e60969
         if (safe_length == 0)
fukasawa e60969
            safe_length = (uInt)-1; /* evil, but safe */
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
         crc = crc32(crc, ptr, safe_length);
fukasawa e60969
fukasawa e60969
         /* The following should never issue compiler warnings; if they do the
fukasawa e60969
          * target system has characteristics that will probably violate other
fukasawa e60969
          * assumptions within the libpng code.
fukasawa e60969
          */
fukasawa e60969
         ptr += safe_length;
fukasawa e60969
         length -= safe_length;
fukasawa e60969
      }
fukasawa e60969
      while (length > 0);
fukasawa e60969
fukasawa e60969
      /* And the following is always safe because the crc is only 32 bits. */
fukasawa e60969
      png_ptr->crc = (png_uint_32)crc;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Check a user supplied version number, called from both read and write
fukasawa e60969
 * functions that create a png_struct.
fukasawa e60969
 */
fukasawa e60969
int
fukasawa e60969
png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
fukasawa e60969
{
fukasawa e60969
     /* Libpng versions 1.0.0 and later are binary compatible if the version
fukasawa e60969
      * string matches through the second '.'; we must recompile any
fukasawa e60969
      * applications that use any older library version.
fukasawa e60969
      */
fukasawa e60969
fukasawa e60969
   if (user_png_ver != NULL)
fukasawa e60969
   {
fukasawa e60969
      int i = -1;
fukasawa e60969
      int found_dots = 0;
fukasawa e60969
fukasawa e60969
      do
fukasawa e60969
      {
fukasawa e60969
         i++;
fukasawa e60969
         if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
fukasawa e60969
            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
fukasawa e60969
         if (user_png_ver[i] == '.')
fukasawa e60969
            found_dots++;
fukasawa e60969
      } while (found_dots < 2 && user_png_ver[i] != 0 &&
fukasawa e60969
            PNG_LIBPNG_VER_STRING[i] != 0);
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
fukasawa e60969
fukasawa e60969
   if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
fukasawa e60969
   {
fukasawa e60969
#ifdef PNG_WARNINGS_SUPPORTED
fukasawa e60969
      size_t pos = 0;
fukasawa e60969
      char m[128];
fukasawa e60969
fukasawa e60969
      pos = png_safecat(m, (sizeof m), pos,
fukasawa e60969
          "Application built with libpng-");
fukasawa e60969
      pos = png_safecat(m, (sizeof m), pos, user_png_ver);
fukasawa e60969
      pos = png_safecat(m, (sizeof m), pos, " but running with ");
fukasawa e60969
      pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
fukasawa e60969
      PNG_UNUSED(pos)
fukasawa e60969
fukasawa e60969
      png_warning(png_ptr, m);
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
fukasawa e60969
      png_ptr->flags = 0;
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
      return 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Success return. */
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Generic function to create a png_struct for either read or write - this
fukasawa e60969
 * contains the common initialization.
fukasawa e60969
 */
fukasawa e60969
PNG_FUNCTION(png_structp /* PRIVATE */,
fukasawa e60969
png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
fukasawa e60969
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
fukasawa e60969
    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
fukasawa e60969
{
fukasawa e60969
   png_struct create_struct;
fukasawa e60969
#  ifdef PNG_SETJMP_SUPPORTED
fukasawa e60969
      jmp_buf create_jmp_buf;
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   /* This temporary stack-allocated structure is used to provide a place to
fukasawa e60969
    * build enough context to allow the user provided memory allocator (if any)
fukasawa e60969
    * to be called.
fukasawa e60969
    */
fukasawa e60969
   memset(&create_struct, 0, (sizeof create_struct));
fukasawa e60969
fukasawa e60969
   /* Added at libpng-1.2.6 */
fukasawa e60969
#  ifdef PNG_USER_LIMITS_SUPPORTED
fukasawa e60969
      create_struct.user_width_max = PNG_USER_WIDTH_MAX;
fukasawa e60969
      create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
fukasawa e60969
fukasawa e60969
#     ifdef PNG_USER_CHUNK_CACHE_MAX
fukasawa e60969
      /* Added at libpng-1.2.43 and 1.4.0 */
fukasawa e60969
      create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
fukasawa e60969
#     endif
fukasawa e60969
fukasawa e60969
#     ifdef PNG_USER_CHUNK_MALLOC_MAX
fukasawa e60969
      /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
fukasawa e60969
       * in png_struct regardless.
fukasawa e60969
       */
fukasawa e60969
      create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
fukasawa e60969
#     endif
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   /* The following two API calls simply set fields in png_struct, so it is safe
fukasawa e60969
    * to do them now even though error handling is not yet set up.
fukasawa e60969
    */
fukasawa e60969
#  ifdef PNG_USER_MEM_SUPPORTED
fukasawa e60969
      png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
fukasawa e60969
#  else
fukasawa e60969
      PNG_UNUSED(mem_ptr)
fukasawa e60969
      PNG_UNUSED(malloc_fn)
fukasawa e60969
      PNG_UNUSED(free_fn)
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   /* (*error_fn) can return control to the caller after the error_ptr is set,
fukasawa e60969
    * this will result in a memory leak unless the error_fn does something
fukasawa e60969
    * extremely sophisticated.  The design lacks merit but is implicit in the
fukasawa e60969
    * API.
fukasawa e60969
    */
fukasawa e60969
   png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
fukasawa e60969
fukasawa e60969
#  ifdef PNG_SETJMP_SUPPORTED
fukasawa e60969
      if (!setjmp(create_jmp_buf))
fukasawa e60969
#  endif
fukasawa e60969
      {
fukasawa e60969
#  ifdef PNG_SETJMP_SUPPORTED
fukasawa e60969
         /* Temporarily fake out the longjmp information until we have
fukasawa e60969
          * successfully completed this function.  This only works if we have
fukasawa e60969
          * setjmp() support compiled in, but it is safe - this stuff should
fukasawa e60969
          * never happen.
fukasawa e60969
          */
fukasawa e60969
         create_struct.jmp_buf_ptr = &create_jmp_buf;
fukasawa e60969
         create_struct.jmp_buf_size = 0; /*stack allocation*/
fukasawa e60969
         create_struct.longjmp_fn = longjmp;
fukasawa e60969
#  endif
fukasawa e60969
         /* Call the general version checker (shared with read and write code):
fukasawa e60969
          */
fukasawa e60969
         if (png_user_version_check(&create_struct, user_png_ver) != 0)
fukasawa e60969
         {
fukasawa e60969
            png_structrp png_ptr = png_voidcast(png_structrp,
fukasawa e60969
               png_malloc_warn(&create_struct, (sizeof *png_ptr)));
fukasawa e60969
fukasawa e60969
            if (png_ptr != NULL)
fukasawa e60969
            {
fukasawa e60969
               /* png_ptr->zstream holds a back-pointer to the png_struct, so
fukasawa e60969
                * this can only be done now:
fukasawa e60969
                */
fukasawa e60969
               create_struct.zstream.zalloc = png_zalloc;
fukasawa e60969
               create_struct.zstream.zfree = png_zfree;
fukasawa e60969
               create_struct.zstream.opaque = png_ptr;
fukasawa e60969
fukasawa e60969
#              ifdef PNG_SETJMP_SUPPORTED
fukasawa e60969
               /* Eliminate the local error handling: */
fukasawa e60969
               create_struct.jmp_buf_ptr = NULL;
fukasawa e60969
               create_struct.jmp_buf_size = 0;
fukasawa e60969
               create_struct.longjmp_fn = 0;
fukasawa e60969
#              endif
fukasawa e60969
fukasawa e60969
               *png_ptr = create_struct;
fukasawa e60969
fukasawa e60969
               /* This is the successful return point */
fukasawa e60969
               return png_ptr;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
   /* A longjmp because of a bug in the application storage allocator or a
fukasawa e60969
    * simple failure to allocate the png_struct.
fukasawa e60969
    */
fukasawa e60969
   return NULL;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Allocate the memory for an info_struct for the application. */
fukasawa e60969
PNG_FUNCTION(png_infop,PNGAPI
fukasawa e60969
png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
fukasawa e60969
{
fukasawa e60969
   png_inforp info_ptr;
fukasawa e60969
fukasawa e60969
   png_debug(1, "in png_create_info_struct");
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return NULL;
fukasawa e60969
fukasawa e60969
   /* Use the internal API that does not (or at least should not) error out, so
fukasawa e60969
    * that this call always returns ok.  The application typically sets up the
fukasawa e60969
    * error handling *after* creating the info_struct because this is the way it
fukasawa e60969
    * has always been done in 'example.c'.
fukasawa e60969
    */
fukasawa e60969
   info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
fukasawa e60969
      (sizeof *info_ptr)));
fukasawa e60969
fukasawa e60969
   if (info_ptr != NULL)
fukasawa e60969
      memset(info_ptr, 0, (sizeof *info_ptr));
fukasawa e60969
fukasawa e60969
   return info_ptr;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* This function frees the memory associated with a single info struct.
fukasawa e60969
 * Normally, one would use either png_destroy_read_struct() or
fukasawa e60969
 * png_destroy_write_struct() to free an info struct, but this may be
fukasawa e60969
 * useful for some applications.  From libpng 1.6.0 this function is also used
fukasawa e60969
 * internally to implement the png_info release part of the 'struct' destroy
fukasawa e60969
 * APIs.  This ensures that all possible approaches free the same data (all of
fukasawa e60969
 * it).
fukasawa e60969
 */
fukasawa e60969
void PNGAPI
fukasawa e60969
png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
fukasawa e60969
{
fukasawa e60969
   png_inforp info_ptr = NULL;
fukasawa e60969
fukasawa e60969
   png_debug(1, "in png_destroy_info_struct");
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   if (info_ptr_ptr != NULL)
fukasawa e60969
      info_ptr = *info_ptr_ptr;
fukasawa e60969
fukasawa e60969
   if (info_ptr != NULL)
fukasawa e60969
   {
fukasawa e60969
      /* Do this first in case of an error below; if the app implements its own
fukasawa e60969
       * memory management this can lead to png_free calling png_error, which
fukasawa e60969
       * will abort this routine and return control to the app error handler.
fukasawa e60969
       * An infinite loop may result if it then tries to free the same info
fukasawa e60969
       * ptr.
fukasawa e60969
       */
fukasawa e60969
      *info_ptr_ptr = NULL;
fukasawa e60969
fukasawa e60969
      png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
fukasawa e60969
      memset(info_ptr, 0, (sizeof *info_ptr));
fukasawa e60969
      png_free(png_ptr, info_ptr);
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Initialize the info structure.  This is now an internal function (0.89)
fukasawa e60969
 * and applications using it are urged to use png_create_info_struct()
fukasawa e60969
 * instead.  Use deprecated in 1.6.0, internal use removed (used internally it
fukasawa e60969
 * is just a memset).
fukasawa e60969
 *
fukasawa e60969
 * NOTE: it is almost inconceivable that this API is used because it bypasses
fukasawa e60969
 * the user-memory mechanism and the user error handling/warning mechanisms in
fukasawa e60969
 * those cases where it does anything other than a memset.
fukasawa e60969
 */
fukasawa e60969
PNG_FUNCTION(void,PNGAPI
fukasawa e60969
png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
fukasawa e60969
   PNG_DEPRECATED)
fukasawa e60969
{
fukasawa e60969
   png_inforp info_ptr = *ptr_ptr;
fukasawa e60969
fukasawa e60969
   png_debug(1, "in png_info_init_3");
fukasawa e60969
fukasawa e60969
   if (info_ptr == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   if ((sizeof (png_info)) > png_info_struct_size)
fukasawa e60969
   {
fukasawa e60969
      *ptr_ptr = NULL;
fukasawa e60969
      /* The following line is why this API should not be used: */
fukasawa e60969
      free(info_ptr);
fukasawa e60969
      info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
fukasawa e60969
         (sizeof *info_ptr)));
fukasawa e60969
      if (info_ptr == NULL)
fukasawa e60969
         return;
fukasawa e60969
      *ptr_ptr = info_ptr;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Set everything to 0 */
fukasawa e60969
   memset(info_ptr, 0, (sizeof *info_ptr));
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* The following API is not called internally */
fukasawa e60969
void PNGAPI
fukasawa e60969
png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
fukasawa e60969
   int freer, png_uint_32 mask)
fukasawa e60969
{
fukasawa e60969
   png_debug(1, "in png_data_freer");
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL || info_ptr == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   if (freer == PNG_DESTROY_WILL_FREE_DATA)
fukasawa e60969
      info_ptr->free_me |= mask;
fukasawa e60969
fukasawa e60969
   else if (freer == PNG_USER_WILL_FREE_DATA)
fukasawa e60969
      info_ptr->free_me &= ~mask;
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      png_error(png_ptr, "Unknown freer parameter in png_data_freer");
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
void PNGAPI
fukasawa e60969
png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
fukasawa e60969
   int num)
fukasawa e60969
{
fukasawa e60969
   png_debug(1, "in png_free_data");
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL || info_ptr == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
#ifdef PNG_TEXT_SUPPORTED
fukasawa e60969
   /* Free text item num or (if num == -1) all text items */
fukasawa e60969
   if (info_ptr->text != 0 &&
fukasawa e60969
       ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      if (num != -1)
fukasawa e60969
      {
fukasawa e60969
         png_free(png_ptr, info_ptr->text[num].key);
fukasawa e60969
         info_ptr->text[num].key = NULL;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         int i;
fukasawa e60969
fukasawa e60969
         for (i = 0; i < info_ptr->num_text; i++)
fukasawa e60969
            png_free(png_ptr, info_ptr->text[i].key);
fukasawa e60969
fukasawa e60969
         png_free(png_ptr, info_ptr->text);
fukasawa e60969
         info_ptr->text = NULL;
fukasawa e60969
         info_ptr->num_text = 0;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_tRNS_SUPPORTED
fukasawa e60969
   /* Free any tRNS entry */
fukasawa e60969
   if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_tRNS;
fukasawa e60969
      png_free(png_ptr, info_ptr->trans_alpha);
fukasawa e60969
      info_ptr->trans_alpha = NULL;
fukasawa e60969
      info_ptr->num_trans = 0;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_sCAL_SUPPORTED
fukasawa e60969
   /* Free any sCAL entry */
fukasawa e60969
   if (((mask & PNG_FREE_SCAL) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      png_free(png_ptr, info_ptr->scal_s_width);
fukasawa e60969
      png_free(png_ptr, info_ptr->scal_s_height);
fukasawa e60969
      info_ptr->scal_s_width = NULL;
fukasawa e60969
      info_ptr->scal_s_height = NULL;
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_sCAL;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_pCAL_SUPPORTED
fukasawa e60969
   /* Free any pCAL entry */
fukasawa e60969
   if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      png_free(png_ptr, info_ptr->pcal_purpose);
fukasawa e60969
      png_free(png_ptr, info_ptr->pcal_units);
fukasawa e60969
      info_ptr->pcal_purpose = NULL;
fukasawa e60969
      info_ptr->pcal_units = NULL;
fukasawa e60969
fukasawa e60969
      if (info_ptr->pcal_params != NULL)
fukasawa e60969
         {
fukasawa e60969
            int i;
fukasawa e60969
fukasawa e60969
            for (i = 0; i < info_ptr->pcal_nparams; i++)
fukasawa e60969
               png_free(png_ptr, info_ptr->pcal_params[i]);
fukasawa e60969
fukasawa e60969
            png_free(png_ptr, info_ptr->pcal_params);
fukasawa e60969
            info_ptr->pcal_params = NULL;
fukasawa e60969
         }
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_pCAL;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_iCCP_SUPPORTED
fukasawa e60969
   /* Free any profile entry */
fukasawa e60969
   if (((mask & PNG_FREE_ICCP) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      png_free(png_ptr, info_ptr->iccp_name);
fukasawa e60969
      png_free(png_ptr, info_ptr->iccp_profile);
fukasawa e60969
      info_ptr->iccp_name = NULL;
fukasawa e60969
      info_ptr->iccp_profile = NULL;
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_iCCP;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_sPLT_SUPPORTED
fukasawa e60969
   /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
fukasawa e60969
   if (info_ptr->splt_palettes != 0 &&
fukasawa e60969
       ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      if (num != -1)
fukasawa e60969
      {
fukasawa e60969
         png_free(png_ptr, info_ptr->splt_palettes[num].name);
fukasawa e60969
         png_free(png_ptr, info_ptr->splt_palettes[num].entries);
fukasawa e60969
         info_ptr->splt_palettes[num].name = NULL;
fukasawa e60969
         info_ptr->splt_palettes[num].entries = NULL;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         int i;
fukasawa e60969
fukasawa e60969
         for (i = 0; i < info_ptr->splt_palettes_num; i++)
fukasawa e60969
         {
fukasawa e60969
            png_free(png_ptr, info_ptr->splt_palettes[i].name);
fukasawa e60969
            png_free(png_ptr, info_ptr->splt_palettes[i].entries);
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         png_free(png_ptr, info_ptr->splt_palettes);
fukasawa e60969
         info_ptr->splt_palettes = NULL;
fukasawa e60969
         info_ptr->splt_palettes_num = 0;
fukasawa e60969
         info_ptr->valid &= ~PNG_INFO_sPLT;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
fukasawa e60969
   if (info_ptr->unknown_chunks != 0 &&
fukasawa e60969
       ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      if (num != -1)
fukasawa e60969
      {
fukasawa e60969
          png_free(png_ptr, info_ptr->unknown_chunks[num].data);
fukasawa e60969
          info_ptr->unknown_chunks[num].data = NULL;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         int i;
fukasawa e60969
fukasawa e60969
         for (i = 0; i < info_ptr->unknown_chunks_num; i++)
fukasawa e60969
            png_free(png_ptr, info_ptr->unknown_chunks[i].data);
fukasawa e60969
fukasawa e60969
         png_free(png_ptr, info_ptr->unknown_chunks);
fukasawa e60969
         info_ptr->unknown_chunks = NULL;
fukasawa e60969
         info_ptr->unknown_chunks_num = 0;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_hIST_SUPPORTED
fukasawa e60969
   /* Free any hIST entry */
fukasawa e60969
   if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      png_free(png_ptr, info_ptr->hist);
fukasawa e60969
      info_ptr->hist = NULL;
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_hIST;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   /* Free any PLTE entry that was internally allocated */
fukasawa e60969
   if (((mask & PNG_FREE_PLTE) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      png_free(png_ptr, info_ptr->palette);
fukasawa e60969
      info_ptr->palette = NULL;
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_PLTE;
fukasawa e60969
      info_ptr->num_palette = 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
#ifdef PNG_INFO_IMAGE_SUPPORTED
fukasawa e60969
   /* Free any image bits attached to the info structure */
fukasawa e60969
   if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
fukasawa e60969
   {
fukasawa e60969
      if (info_ptr->row_pointers != 0)
fukasawa e60969
      {
fukasawa e60969
         png_uint_32 row;
fukasawa e60969
         for (row = 0; row < info_ptr->height; row++)
fukasawa e60969
            png_free(png_ptr, info_ptr->row_pointers[row]);
fukasawa e60969
fukasawa e60969
         png_free(png_ptr, info_ptr->row_pointers);
fukasawa e60969
         info_ptr->row_pointers = NULL;
fukasawa e60969
      }
fukasawa e60969
      info_ptr->valid &= ~PNG_INFO_IDAT;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   if (num != -1)
fukasawa e60969
      mask &= ~PNG_FREE_MUL;
fukasawa e60969
fukasawa e60969
   info_ptr->free_me &= ~mask;
fukasawa e60969
}
fukasawa e60969
#endif /* READ || WRITE */
fukasawa e60969
fukasawa e60969
/* This function returns a pointer to the io_ptr associated with the user
fukasawa e60969
 * functions.  The application should free any memory associated with this
fukasawa e60969
 * pointer before png_write_destroy() or png_read_destroy() are called.
fukasawa e60969
 */
fukasawa e60969
png_voidp PNGAPI
fukasawa e60969
png_get_io_ptr(png_const_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return (NULL);
fukasawa e60969
fukasawa e60969
   return (png_ptr->io_ptr);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
fukasawa e60969
#  ifdef PNG_STDIO_SUPPORTED
fukasawa e60969
/* Initialize the default input/output functions for the PNG file.  If you
fukasawa e60969
 * use your own read or write routines, you can call either png_set_read_fn()
fukasawa e60969
 * or png_set_write_fn() instead of png_init_io().  If you have defined
fukasawa e60969
 * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
fukasawa e60969
 * function of your own because "FILE *" isn't necessarily available.
fukasawa e60969
 */
fukasawa e60969
void PNGAPI
fukasawa e60969
png_init_io(png_structrp png_ptr, png_FILE_p fp)
fukasawa e60969
{
fukasawa e60969
   png_debug(1, "in png_init_io");
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   png_ptr->io_ptr = (png_voidp)fp;
fukasawa e60969
}
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
#  ifdef PNG_SAVE_INT_32_SUPPORTED
fukasawa e60969
/* PNG signed integers are saved in 32-bit 2's complement format.  ANSI C-90
fukasawa e60969
 * defines a cast of a signed integer to an unsigned integer either to preserve
fukasawa e60969
 * the value, if it is positive, or to calculate:
fukasawa e60969
 *
fukasawa e60969
 *     (UNSIGNED_MAX+1) + integer
fukasawa e60969
 *
fukasawa e60969
 * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
fukasawa e60969
 * negative integral value is added the result will be an unsigned value
fukasawa e60969
 * correspnding to the 2's complement representation.
fukasawa e60969
 */
fukasawa e60969
void PNGAPI
fukasawa e60969
png_save_int_32(png_bytep buf, png_int_32 i)
fukasawa e60969
{
fukasawa e60969
   png_save_uint_32(buf, i);
fukasawa e60969
}
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
#  ifdef PNG_TIME_RFC1123_SUPPORTED
fukasawa e60969
/* Convert the supplied time into an RFC 1123 string suitable for use in
fukasawa e60969
 * a "Creation Time" or other text-based time string.
fukasawa e60969
 */
fukasawa e60969
int PNGAPI
fukasawa e60969
png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
fukasawa e60969
{
fukasawa e60969
   static PNG_CONST char short_months[12][4] =
fukasawa e60969
        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
fukasawa e60969
         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
fukasawa e60969
fukasawa e60969
   if (out == NULL)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   if (ptime->year > 9999 /* RFC1123 limitation */ ||
fukasawa e60969
       ptime->month == 0    ||  ptime->month > 12  ||
fukasawa e60969
       ptime->day   == 0    ||  ptime->day   > 31  ||
fukasawa e60969
       ptime->hour  > 23    ||  ptime->minute > 59 ||
fukasawa e60969
       ptime->second > 60)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   {
fukasawa e60969
      size_t pos = 0;
fukasawa e60969
      char number_buf[5]; /* enough for a four-digit year */
fukasawa e60969
fukasawa e60969
#     define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
fukasawa e60969
#     define APPEND_NUMBER(format, value)\
fukasawa e60969
         APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
fukasawa e60969
#     define APPEND(ch) if (pos < 28) out[pos++] = (ch)
fukasawa e60969
fukasawa e60969
      APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
fukasawa e60969
      APPEND(' ');
fukasawa e60969
      APPEND_STRING(short_months[(ptime->month - 1)]);
fukasawa e60969
      APPEND(' ');
fukasawa e60969
      APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
fukasawa e60969
      APPEND(' ');
fukasawa e60969
      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
fukasawa e60969
      APPEND(':');
fukasawa e60969
      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
fukasawa e60969
      APPEND(':');
fukasawa e60969
      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
fukasawa e60969
      APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
fukasawa e60969
      PNG_UNUSED (pos)
fukasawa e60969
fukasawa e60969
#     undef APPEND
fukasawa e60969
#     undef APPEND_NUMBER
fukasawa e60969
#     undef APPEND_STRING
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#    if PNG_LIBPNG_VER < 10700
fukasawa e60969
/* To do: remove the following from libpng-1.7 */
fukasawa e60969
/* Original API that uses a private buffer in png_struct.
fukasawa e60969
 * Deprecated because it causes png_struct to carry a spurious temporary
fukasawa e60969
 * buffer (png_struct::time_buffer), better to have the caller pass this in.
fukasawa e60969
 */
fukasawa e60969
png_const_charp PNGAPI
fukasawa e60969
png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
fukasawa e60969
{
fukasawa e60969
   if (png_ptr != NULL)
fukasawa e60969
   {
fukasawa e60969
      /* The only failure above if png_ptr != NULL is from an invalid ptime */
fukasawa e60969
      if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0)
fukasawa e60969
         png_warning(png_ptr, "Ignoring invalid time value");
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
         return png_ptr->time_buffer;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return NULL;
fukasawa e60969
}
fukasawa e60969
#    endif /* LIBPNG_VER < 10700 */
fukasawa e60969
#  endif /* TIME_RFC1123 */
fukasawa e60969
fukasawa e60969
#endif /* READ || WRITE */
fukasawa e60969
fukasawa e60969
png_const_charp PNGAPI
fukasawa e60969
png_get_copyright(png_const_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
fukasawa e60969
#ifdef PNG_STRING_COPYRIGHT
fukasawa e60969
   return PNG_STRING_COPYRIGHT
fukasawa e60969
#else
fukasawa e60969
#  ifdef __STDC__
fukasawa e60969
   return PNG_STRING_NEWLINE \
fukasawa e60969
      "libpng version 1.6.21 - January 15, 2016" PNG_STRING_NEWLINE \
fukasawa e60969
      "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
fukasawa e60969
      PNG_STRING_NEWLINE \
fukasawa e60969
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
fukasawa e60969
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
fukasawa e60969
      PNG_STRING_NEWLINE;
fukasawa e60969
#  else
fukasawa e60969
   return "libpng version 1.6.21 - January 15, 2016\
fukasawa e60969
      Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
fukasawa e60969
      Copyright (c) 1996-1997 Andreas Dilger\
fukasawa e60969
      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
fukasawa e60969
#  endif
fukasawa e60969
#endif
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* The following return the library version as a short string in the
fukasawa e60969
 * format 1.0.0 through 99.99.99zz.  To get the version of *.h files
fukasawa e60969
 * used with your application, print out PNG_LIBPNG_VER_STRING, which
fukasawa e60969
 * is defined in png.h.
fukasawa e60969
 * Note: now there is no difference between png_get_libpng_ver() and
fukasawa e60969
 * png_get_header_ver().  Due to the version_nn_nn_nn typedef guard,
fukasawa e60969
 * it is guaranteed that png.c uses the correct version of png.h.
fukasawa e60969
 */
fukasawa e60969
png_const_charp PNGAPI
fukasawa e60969
png_get_libpng_ver(png_const_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   /* Version of *.c files used when building libpng */
fukasawa e60969
   return png_get_header_ver(png_ptr);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
png_const_charp PNGAPI
fukasawa e60969
png_get_header_ver(png_const_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   /* Version of *.h files used when building libpng */
fukasawa e60969
   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
fukasawa e60969
   return PNG_LIBPNG_VER_STRING;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
png_const_charp PNGAPI
fukasawa e60969
png_get_header_version(png_const_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   /* Returns longer string containing both version and date */
fukasawa e60969
   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
fukasawa e60969
#ifdef __STDC__
fukasawa e60969
   return PNG_HEADER_VERSION_STRING
fukasawa e60969
#  ifndef PNG_READ_SUPPORTED
fukasawa e60969
      " (NO READ SUPPORT)"
fukasawa e60969
#  endif
fukasawa e60969
      PNG_STRING_NEWLINE;
fukasawa e60969
#else
fukasawa e60969
   return PNG_HEADER_VERSION_STRING;
fukasawa e60969
#endif
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
fukasawa e60969
/* NOTE: this routine is not used internally! */
fukasawa e60969
/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
fukasawa e60969
 * large of png_color.  This lets grayscale images be treated as
fukasawa e60969
 * paletted.  Most useful for gamma correction and simplification
fukasawa e60969
 * of code.  This API is not used internally.
fukasawa e60969
 */
fukasawa e60969
void PNGAPI
fukasawa e60969
png_build_grayscale_palette(int bit_depth, png_colorp palette)
fukasawa e60969
{
fukasawa e60969
   int num_palette;
fukasawa e60969
   int color_inc;
fukasawa e60969
   int i;
fukasawa e60969
   int v;
fukasawa e60969
fukasawa e60969
   png_debug(1, "in png_do_build_grayscale_palette");
fukasawa e60969
fukasawa e60969
   if (palette == NULL)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   switch (bit_depth)
fukasawa e60969
   {
fukasawa e60969
      case 1:
fukasawa e60969
         num_palette = 2;
fukasawa e60969
         color_inc = 0xff;
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 2:
fukasawa e60969
         num_palette = 4;
fukasawa e60969
         color_inc = 0x55;
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 4:
fukasawa e60969
         num_palette = 16;
fukasawa e60969
         color_inc = 0x11;
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 8:
fukasawa e60969
         num_palette = 256;
fukasawa e60969
         color_inc = 1;
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         num_palette = 0;
fukasawa e60969
         color_inc = 0;
fukasawa e60969
         break;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
fukasawa e60969
   {
fukasawa e60969
      palette[i].red = (png_byte)(v & 0xff);
fukasawa e60969
      palette[i].green = (png_byte)(v & 0xff);
fukasawa e60969
      palette[i].blue = (png_byte)(v & 0xff);
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
fukasawa e60969
int PNGAPI
fukasawa e60969
png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
fukasawa e60969
{
fukasawa e60969
   /* Check chunk_name and return "keep" value if it's on the list, else 0 */
fukasawa e60969
   png_const_bytep p, p_end;
fukasawa e60969
fukasawa e60969
   if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
fukasawa e60969
      return PNG_HANDLE_CHUNK_AS_DEFAULT;
fukasawa e60969
fukasawa e60969
   p_end = png_ptr->chunk_list;
fukasawa e60969
   p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
fukasawa e60969
fukasawa e60969
   /* The code is the fifth byte after each four byte string.  Historically this
fukasawa e60969
    * code was always searched from the end of the list, this is no longer
fukasawa e60969
    * necessary because the 'set' routine handles duplicate entries correcty.
fukasawa e60969
    */
fukasawa e60969
   do /* num_chunk_list > 0, so at least one */
fukasawa e60969
   {
fukasawa e60969
      p -= 5;
fukasawa e60969
fukasawa e60969
      if (memcmp(chunk_name, p, 4) == 0)
fukasawa e60969
         return p[4];
fukasawa e60969
   }
fukasawa e60969
   while (p > p_end);
fukasawa e60969
fukasawa e60969
   /* This means that known chunks should be processed and unknown chunks should
fukasawa e60969
    * be handled according to the value of png_ptr->unknown_default; this can be
fukasawa e60969
    * confusing because, as a result, there are two levels of defaulting for
fukasawa e60969
    * unknown chunks.
fukasawa e60969
    */
fukasawa e60969
   return PNG_HANDLE_CHUNK_AS_DEFAULT;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
fukasawa e60969
   defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
fukasawa e60969
{
fukasawa e60969
   png_byte chunk_string[5];
fukasawa e60969
fukasawa e60969
   PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
fukasawa e60969
   return png_handle_as_unknown(png_ptr, chunk_string);
fukasawa e60969
}
fukasawa e60969
#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
fukasawa e60969
#endif /* SET_UNKNOWN_CHUNKS */
fukasawa e60969
fukasawa e60969
#ifdef PNG_READ_SUPPORTED
fukasawa e60969
/* This function, added to libpng-1.0.6g, is untested. */
fukasawa e60969
int PNGAPI
fukasawa e60969
png_reset_zstream(png_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   if (png_ptr == NULL)
fukasawa e60969
      return Z_STREAM_ERROR;
fukasawa e60969
fukasawa e60969
   /* WARNING: this resets the window bits to the maximum! */
fukasawa e60969
   return (inflateReset(&png_ptr->zstream));
fukasawa e60969
}
fukasawa e60969
#endif /* READ */
fukasawa e60969
fukasawa e60969
/* This function was added to libpng-1.0.7 */
fukasawa e60969
png_uint_32 PNGAPI
fukasawa e60969
png_access_version_number(void)
fukasawa e60969
{
fukasawa e60969
   /* Version of *.c files used when building libpng */
fukasawa e60969
   return((png_uint_32)PNG_LIBPNG_VER);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
fukasawa e60969
/* Ensure that png_ptr->zstream.msg holds some appropriate error message string.
fukasawa e60969
 * If it doesn't 'ret' is used to set it to something appropriate, even in cases
fukasawa e60969
 * like Z_OK or Z_STREAM_END where the error code is apparently a success code.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_zstream_error(png_structrp png_ptr, int ret)
fukasawa e60969
{
fukasawa e60969
   /* Translate 'ret' into an appropriate error string, priority is given to the
fukasawa e60969
    * one in zstream if set.  This always returns a string, even in cases like
fukasawa e60969
    * Z_OK or Z_STREAM_END where the error code is a success code.
fukasawa e60969
    */
fukasawa e60969
   if (png_ptr->zstream.msg == NULL) switch (ret)
fukasawa e60969
   {
fukasawa e60969
      default:
fukasawa e60969
      case Z_OK:
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_STREAM_END:
fukasawa e60969
         /* Normal exit */
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_NEED_DICT:
fukasawa e60969
         /* This means the deflate stream did not have a dictionary; this
fukasawa e60969
          * indicates a bogus PNG.
fukasawa e60969
          */
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_ERRNO:
fukasawa e60969
         /* gz APIs only: should not happen */
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_STREAM_ERROR:
fukasawa e60969
         /* internal libpng error */
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_DATA_ERROR:
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_MEM_ERROR:
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_BUF_ERROR:
fukasawa e60969
         /* End of input or output; not a problem if the caller is doing
fukasawa e60969
          * incremental read or write.
fukasawa e60969
          */
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case Z_VERSION_ERROR:
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_UNEXPECTED_ZLIB_RETURN:
fukasawa e60969
         /* Compile errors here mean that zlib now uses the value co-opted in
fukasawa e60969
          * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
fukasawa e60969
          * and change pngpriv.h.  Note that this message is "... return",
fukasawa e60969
          * whereas the default/Z_OK one is "... return code".
fukasawa e60969
          */
fukasawa e60969
         png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");
fukasawa e60969
         break;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
fukasawa e60969
 * at libpng 1.5.5!
fukasawa e60969
 */
fukasawa e60969
fukasawa e60969
/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
fukasawa e60969
#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
fukasawa e60969
static int
fukasawa e60969
png_colorspace_check_gamma(png_const_structrp png_ptr,
fukasawa e60969
   png_colorspacerp colorspace, png_fixed_point gAMA, int from)
fukasawa e60969
   /* This is called to check a new gamma value against an existing one.  The
fukasawa e60969
    * routine returns false if the new gamma value should not be written.
fukasawa e60969
    *
fukasawa e60969
    * 'from' says where the new gamma value comes from:
fukasawa e60969
    *
fukasawa e60969
    *    0: the new gamma value is the libpng estimate for an ICC profile
fukasawa e60969
    *    1: the new gamma value comes from a gAMA chunk
fukasawa e60969
    *    2: the new gamma value comes from an sRGB chunk
fukasawa e60969
    */
fukasawa e60969
{
fukasawa e60969
   png_fixed_point gtest;
fukasawa e60969
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
fukasawa e60969
      (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0  ||
fukasawa e60969
      png_gamma_significant(gtest) != 0))
fukasawa e60969
   {
fukasawa e60969
      /* Either this is an sRGB image, in which case the calculated gamma
fukasawa e60969
       * approximation should match, or this is an image with a profile and the
fukasawa e60969
       * value libpng calculates for the gamma of the profile does not match the
fukasawa e60969
       * value recorded in the file.  The former, sRGB, case is an error, the
fukasawa e60969
       * latter is just a warning.
fukasawa e60969
       */
fukasawa e60969
      if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
fukasawa e60969
      {
fukasawa e60969
         png_chunk_report(png_ptr, "gamma value does not match sRGB",
fukasawa e60969
            PNG_CHUNK_ERROR);
fukasawa e60969
         /* Do not overwrite an sRGB value */
fukasawa e60969
         return from == 2;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      else /* sRGB tag not involved */
fukasawa e60969
      {
fukasawa e60969
         png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
fukasawa e60969
            PNG_CHUNK_WARNING);
fukasawa e60969
         return from == 1;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_colorspace_set_gamma(png_const_structrp png_ptr,
fukasawa e60969
   png_colorspacerp colorspace, png_fixed_point gAMA)
fukasawa e60969
{
fukasawa e60969
   /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
fukasawa e60969
    * occur.  Since the fixed point representation is asymetrical it is
fukasawa e60969
    * possible for 1/gamma to overflow the limit of 21474 and this means the
fukasawa e60969
    * gamma value must be at least 5/100000 and hence at most 20000.0.  For
fukasawa e60969
    * safety the limits here are a little narrower.  The values are 0.00016 to
fukasawa e60969
    * 6250.0, which are truly ridiculous gamma values (and will produce
fukasawa e60969
    * displays that are all black or all white.)
fukasawa e60969
    *
fukasawa e60969
    * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
fukasawa e60969
    * handling code, which only required the value to be >0.
fukasawa e60969
    */
fukasawa e60969
   png_const_charp errmsg;
fukasawa e60969
fukasawa e60969
   if (gAMA < 16 || gAMA > 625000000)
fukasawa e60969
      errmsg = "gamma value out of range";
fukasawa e60969
fukasawa e60969
#  ifdef PNG_READ_gAMA_SUPPORTED
fukasawa e60969
   /* Allow the application to set the gamma value more than once */
fukasawa e60969
   else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
fukasawa e60969
      (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
fukasawa e60969
      errmsg = "duplicate";
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   /* Do nothing if the colorspace is already invalid */
fukasawa e60969
   else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
      if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
fukasawa e60969
          1/*from gAMA*/) != 0)
fukasawa e60969
      {
fukasawa e60969
         /* Store this gamma value. */
fukasawa e60969
         colorspace->gamma = gAMA;
fukasawa e60969
         colorspace->flags |=
fukasawa e60969
            (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* At present if the check_gamma test fails the gamma of the colorspace is
fukasawa e60969
       * not updated however the colorspace is not invalidated.  This
fukasawa e60969
       * corresponds to the case where the existing gamma comes from an sRGB
fukasawa e60969
       * chunk or profile.  An error message has already been output.
fukasawa e60969
       */
fukasawa e60969
      return;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Error exit - errmsg has been set. */
fukasawa e60969
   colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
   png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
fukasawa e60969
{
fukasawa e60969
   if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
fukasawa e60969
   {
fukasawa e60969
      /* Everything is invalid */
fukasawa e60969
      info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
fukasawa e60969
         PNG_INFO_iCCP);
fukasawa e60969
fukasawa e60969
#     ifdef PNG_COLORSPACE_SUPPORTED
fukasawa e60969
      /* Clean up the iCCP profile now if it won't be used. */
fukasawa e60969
      png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
fukasawa e60969
#     else
fukasawa e60969
      PNG_UNUSED(png_ptr)
fukasawa e60969
#     endif
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_COLORSPACE_SUPPORTED
fukasawa e60969
      /* Leave the INFO_iCCP flag set if the pngset.c code has already set
fukasawa e60969
       * it; this allows a PNG to contain a profile which matches sRGB and
fukasawa e60969
       * yet still have that profile retrievable by the application.
fukasawa e60969
       */
fukasawa e60969
      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0)
fukasawa e60969
         info_ptr->valid |= PNG_INFO_sRGB;
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
         info_ptr->valid &= ~PNG_INFO_sRGB;
fukasawa e60969
fukasawa e60969
      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
fukasawa e60969
         info_ptr->valid |= PNG_INFO_cHRM;
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
         info_ptr->valid &= ~PNG_INFO_cHRM;
fukasawa e60969
#     endif
fukasawa e60969
fukasawa e60969
      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
fukasawa e60969
         info_ptr->valid |= PNG_INFO_gAMA;
fukasawa e60969
fukasawa e60969
      else
fukasawa e60969
         info_ptr->valid &= ~PNG_INFO_gAMA;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#ifdef PNG_READ_SUPPORTED
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
fukasawa e60969
{
fukasawa e60969
   if (info_ptr == NULL) /* reduce code size; check here not in the caller */
fukasawa e60969
      return;
fukasawa e60969
fukasawa e60969
   info_ptr->colorspace = png_ptr->colorspace;
fukasawa e60969
   png_colorspace_sync_info(png_ptr, info_ptr);
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
#endif /* GAMMA */
fukasawa e60969
fukasawa e60969
#ifdef PNG_COLORSPACE_SUPPORTED
fukasawa e60969
/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
fukasawa e60969
 * cHRM, as opposed to using chromaticities.  These internal APIs return
fukasawa e60969
 * non-zero on a parameter error.  The X, Y and Z values are required to be
fukasawa e60969
 * positive and less than 1.0.
fukasawa e60969
 */
fukasawa e60969
static int
fukasawa e60969
png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
fukasawa e60969
{
fukasawa e60969
   png_int_32 d, dwhite, whiteX, whiteY;
fukasawa e60969
fukasawa e60969
   d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
fukasawa e60969
   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   dwhite = d;
fukasawa e60969
   whiteX = XYZ->red_X;
fukasawa e60969
   whiteY = XYZ->red_Y;
fukasawa e60969
fukasawa e60969
   d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
fukasawa e60969
   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   dwhite += d;
fukasawa e60969
   whiteX += XYZ->green_X;
fukasawa e60969
   whiteY += XYZ->green_Y;
fukasawa e60969
fukasawa e60969
   d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
fukasawa e60969
   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   dwhite += d;
fukasawa e60969
   whiteX += XYZ->blue_X;
fukasawa e60969
   whiteY += XYZ->blue_Y;
fukasawa e60969
fukasawa e60969
   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
fukasawa e60969
    * thus:
fukasawa e60969
    */
fukasawa e60969
   if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
fukasawa e60969
{
fukasawa e60969
   png_fixed_point red_inverse, green_inverse, blue_scale;
fukasawa e60969
   png_fixed_point left, right, denominator;
fukasawa e60969
fukasawa e60969
   /* Check xy and, implicitly, z.  Note that wide gamut color spaces typically
fukasawa e60969
    * have end points with 0 tristimulus values (these are impossible end
fukasawa e60969
    * points, but they are used to cover the possible colors).  We check
fukasawa e60969
    * xy->whitey against 5, not 0, to avoid a possible integer overflow.
fukasawa e60969
    */
fukasawa e60969
   if (xy->redx   < 0 || xy->redx > PNG_FP_1) return 1;
fukasawa e60969
   if (xy->redy   < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
fukasawa e60969
   if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
fukasawa e60969
   if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
fukasawa e60969
   if (xy->bluex  < 0 || xy->bluex > PNG_FP_1) return 1;
fukasawa e60969
   if (xy->bluey  < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
fukasawa e60969
   if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
fukasawa e60969
   if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
fukasawa e60969
fukasawa e60969
   /* The reverse calculation is more difficult because the original tristimulus
fukasawa e60969
    * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
fukasawa e60969
    * derived values were recorded in the cHRM chunk;
fukasawa e60969
    * (red,green,blue,white)x(x,y).  This loses one degree of freedom and
fukasawa e60969
    * therefore an arbitrary ninth value has to be introduced to undo the
fukasawa e60969
    * original transformations.
fukasawa e60969
    *
fukasawa e60969
    * Think of the original end-points as points in (X,Y,Z) space.  The
fukasawa e60969
    * chromaticity values (c) have the property:
fukasawa e60969
    *
fukasawa e60969
    *           C
fukasawa e60969
    *   c = ---------
fukasawa e60969
    *       X + Y + Z
fukasawa e60969
    *
fukasawa e60969
    * For each c (x,y,z) from the corresponding original C (X,Y,Z).  Thus the
fukasawa e60969
    * three chromaticity values (x,y,z) for each end-point obey the
fukasawa e60969
    * relationship:
fukasawa e60969
    *
fukasawa e60969
    *   x + y + z = 1
fukasawa e60969
    *
fukasawa e60969
    * This describes the plane in (X,Y,Z) space that intersects each axis at the
fukasawa e60969
    * value 1.0; call this the chromaticity plane.  Thus the chromaticity
fukasawa e60969
    * calculation has scaled each end-point so that it is on the x+y+z=1 plane
fukasawa e60969
    * and chromaticity is the intersection of the vector from the origin to the
fukasawa e60969
    * (X,Y,Z) value with the chromaticity plane.
fukasawa e60969
    *
fukasawa e60969
    * To fully invert the chromaticity calculation we would need the three
fukasawa e60969
    * end-point scale factors, (red-scale, green-scale, blue-scale), but these
fukasawa e60969
    * were not recorded.  Instead we calculated the reference white (X,Y,Z) and
fukasawa e60969
    * recorded the chromaticity of this.  The reference white (X,Y,Z) would have
fukasawa e60969
    * given all three of the scale factors since:
fukasawa e60969
    *
fukasawa e60969
    *    color-C = color-c * color-scale
fukasawa e60969
    *    white-C = red-C + green-C + blue-C
fukasawa e60969
    *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
fukasawa e60969
    *
fukasawa e60969
    * But cHRM records only white-x and white-y, so we have lost the white scale
fukasawa e60969
    * factor:
fukasawa e60969
    *
fukasawa e60969
    *    white-C = white-c*white-scale
fukasawa e60969
    *
fukasawa e60969
    * To handle this the inverse transformation makes an arbitrary assumption
fukasawa e60969
    * about white-scale:
fukasawa e60969
    *
fukasawa e60969
    *    Assume: white-Y = 1.0
fukasawa e60969
    *    Hence:  white-scale = 1/white-y
fukasawa e60969
    *    Or:     red-Y + green-Y + blue-Y = 1.0
fukasawa e60969
    *
fukasawa e60969
    * Notice the last statement of the assumption gives an equation in three of
fukasawa e60969
    * the nine values we want to calculate.  8 more equations come from the
fukasawa e60969
    * above routine as summarised at the top above (the chromaticity
fukasawa e60969
    * calculation):
fukasawa e60969
    *
fukasawa e60969
    *    Given: color-x = color-X / (color-X + color-Y + color-Z)
fukasawa e60969
    *    Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
fukasawa e60969
    *
fukasawa e60969
    * This is 9 simultaneous equations in the 9 variables "color-C" and can be
fukasawa e60969
    * solved by Cramer's rule.  Cramer's rule requires calculating 10 9x9 matrix
fukasawa e60969
    * determinants, however this is not as bad as it seems because only 28 of
fukasawa e60969
    * the total of 90 terms in the various matrices are non-zero.  Nevertheless
fukasawa e60969
    * Cramer's rule is notoriously numerically unstable because the determinant
fukasawa e60969
    * calculation involves the difference of large, but similar, numbers.  It is
fukasawa e60969
    * difficult to be sure that the calculation is stable for real world values
fukasawa e60969
    * and it is certain that it becomes unstable where the end points are close
fukasawa e60969
    * together.
fukasawa e60969
    *
fukasawa e60969
    * So this code uses the perhaps slightly less optimal but more
fukasawa e60969
    * understandable and totally obvious approach of calculating color-scale.
fukasawa e60969
    *
fukasawa e60969
    * This algorithm depends on the precision in white-scale and that is
fukasawa e60969
    * (1/white-y), so we can immediately see that as white-y approaches 0 the
fukasawa e60969
    * accuracy inherent in the cHRM chunk drops off substantially.
fukasawa e60969
    *
fukasawa e60969
    * libpng arithmetic: a simple inversion of the above equations
fukasawa e60969
    * ------------------------------------------------------------
fukasawa e60969
    *
fukasawa e60969
    *    white_scale = 1/white-y
fukasawa e60969
    *    white-X = white-x * white-scale
fukasawa e60969
    *    white-Y = 1.0
fukasawa e60969
    *    white-Z = (1 - white-x - white-y) * white_scale
fukasawa e60969
    *
fukasawa e60969
    *    white-C = red-C + green-C + blue-C
fukasawa e60969
    *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
fukasawa e60969
    *
fukasawa e60969
    * This gives us three equations in (red-scale,green-scale,blue-scale) where
fukasawa e60969
    * all the coefficients are now known:
fukasawa e60969
    *
fukasawa e60969
    *    red-x*red-scale + green-x*green-scale + blue-x*blue-scale
fukasawa e60969
    *       = white-x/white-y
fukasawa e60969
    *    red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
fukasawa e60969
    *    red-z*red-scale + green-z*green-scale + blue-z*blue-scale
fukasawa e60969
    *       = (1 - white-x - white-y)/white-y
fukasawa e60969
    *
fukasawa e60969
    * In the last equation color-z is (1 - color-x - color-y) so we can add all
fukasawa e60969
    * three equations together to get an alternative third:
fukasawa e60969
    *
fukasawa e60969
    *    red-scale + green-scale + blue-scale = 1/white-y = white-scale
fukasawa e60969
    *
fukasawa e60969
    * So now we have a Cramer's rule solution where the determinants are just
fukasawa e60969
    * 3x3 - far more tractible.  Unfortunately 3x3 determinants still involve
fukasawa e60969
    * multiplication of three coefficients so we can't guarantee to avoid
fukasawa e60969
    * overflow in the libpng fixed point representation.  Using Cramer's rule in
fukasawa e60969
    * floating point is probably a good choice here, but it's not an option for
fukasawa e60969
    * fixed point.  Instead proceed to simplify the first two equations by
fukasawa e60969
    * eliminating what is likely to be the largest value, blue-scale:
fukasawa e60969
    *
fukasawa e60969
    *    blue-scale = white-scale - red-scale - green-scale
fukasawa e60969
    *
fukasawa e60969
    * Hence:
fukasawa e60969
    *
fukasawa e60969
    *    (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
fukasawa e60969
    *                (white-x - blue-x)*white-scale
fukasawa e60969
    *
fukasawa e60969
    *    (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
fukasawa e60969
    *                1 - blue-y*white-scale
fukasawa e60969
    *
fukasawa e60969
    * And now we can trivially solve for (red-scale,green-scale):
fukasawa e60969
    *
fukasawa e60969
    *    green-scale =
fukasawa e60969
    *                (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
fukasawa e60969
    *                -----------------------------------------------------------
fukasawa e60969
    *                                  green-x - blue-x
fukasawa e60969
    *
fukasawa e60969
    *    red-scale =
fukasawa e60969
    *                1 - blue-y*white-scale - (green-y - blue-y) * green-scale
fukasawa e60969
    *                ---------------------------------------------------------
fukasawa e60969
    *                                  red-y - blue-y
fukasawa e60969
    *
fukasawa e60969
    * Hence:
fukasawa e60969
    *
fukasawa e60969
    *    red-scale =
fukasawa e60969
    *          ( (green-x - blue-x) * (white-y - blue-y) -
fukasawa e60969
    *            (green-y - blue-y) * (white-x - blue-x) ) / white-y
fukasawa e60969
    * -------------------------------------------------------------------------
fukasawa e60969
    *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
fukasawa e60969
    *
fukasawa e60969
    *    green-scale =
fukasawa e60969
    *          ( (red-y - blue-y) * (white-x - blue-x) -
fukasawa e60969
    *            (red-x - blue-x) * (white-y - blue-y) ) / white-y
fukasawa e60969
    * -------------------------------------------------------------------------
fukasawa e60969
    *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
fukasawa e60969
    *
fukasawa e60969
    * Accuracy:
fukasawa e60969
    * The input values have 5 decimal digits of accuracy.  The values are all in
fukasawa e60969
    * the range 0 < value < 1, so simple products are in the same range but may
fukasawa e60969
    * need up to 10 decimal digits to preserve the original precision and avoid
fukasawa e60969
    * underflow.  Because we are using a 32-bit signed representation we cannot
fukasawa e60969
    * match this; the best is a little over 9 decimal digits, less than 10.
fukasawa e60969
    *
fukasawa e60969
    * The approach used here is to preserve the maximum precision within the
fukasawa e60969
    * signed representation.  Because the red-scale calculation above uses the
fukasawa e60969
    * difference between two products of values that must be in the range -1..+1
fukasawa e60969
    * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The
fukasawa e60969
    * factor is irrelevant in the calculation because it is applied to both
fukasawa e60969
    * numerator and denominator.
fukasawa e60969
    *
fukasawa e60969
    * Note that the values of the differences of the products of the
fukasawa e60969
    * chromaticities in the above equations tend to be small, for example for
fukasawa e60969
    * the sRGB chromaticities they are:
fukasawa e60969
    *
fukasawa e60969
    * red numerator:    -0.04751
fukasawa e60969
    * green numerator:  -0.08788
fukasawa e60969
    * denominator:      -0.2241 (without white-y multiplication)
fukasawa e60969
    *
fukasawa e60969
    *  The resultant Y coefficients from the chromaticities of some widely used
fukasawa e60969
    *  color space definitions are (to 15 decimal places):
fukasawa e60969
    *
fukasawa e60969
    *  sRGB
fukasawa e60969
    *    0.212639005871510 0.715168678767756 0.072192315360734
fukasawa e60969
    *  Kodak ProPhoto
fukasawa e60969
    *    0.288071128229293 0.711843217810102 0.000085653960605
fukasawa e60969
    *  Adobe RGB
fukasawa e60969
    *    0.297344975250536 0.627363566255466 0.075291458493998
fukasawa e60969
    *  Adobe Wide Gamut RGB
fukasawa e60969
    *    0.258728243040113 0.724682314948566 0.016589442011321
fukasawa e60969
    */
fukasawa e60969
   /* By the argument, above overflow should be impossible here. The return
fukasawa e60969
    * value of 2 indicates an internal error to the caller.
fukasawa e60969
    */
fukasawa e60969
   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
fukasawa e60969
      return 2;
fukasawa e60969
   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
fukasawa e60969
      return 2;
fukasawa e60969
   denominator = left - right;
fukasawa e60969
fukasawa e60969
   /* Now find the red numerator. */
fukasawa e60969
   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
fukasawa e60969
      return 2;
fukasawa e60969
   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
fukasawa e60969
      return 2;
fukasawa e60969
fukasawa e60969
   /* Overflow is possible here and it indicates an extreme set of PNG cHRM
fukasawa e60969
    * chunk values.  This calculation actually returns the reciprocal of the
fukasawa e60969
    * scale value because this allows us to delay the multiplication of white-y
fukasawa e60969
    * into the denominator, which tends to produce a small number.
fukasawa e60969
    */
fukasawa e60969
   if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
fukasawa e60969
       red_inverse <= xy->whitey /* r+g+b scales = white scale */)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   /* Similarly for green_inverse: */
fukasawa e60969
   if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
fukasawa e60969
      return 2;
fukasawa e60969
   if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
fukasawa e60969
      return 2;
fukasawa e60969
   if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
fukasawa e60969
       green_inverse <= xy->whitey)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   /* And the blue scale, the checks above guarantee this can't overflow but it
fukasawa e60969
    * can still produce 0 for extreme cHRM values.
fukasawa e60969
    */
fukasawa e60969
   blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
fukasawa e60969
       png_reciprocal(green_inverse);
fukasawa e60969
   if (blue_scale <= 0)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
fukasawa e60969
   /* And fill in the png_XYZ: */
fukasawa e60969
   if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
fukasawa e60969
       red_inverse) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
fukasawa e60969
       green_inverse) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
   if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
fukasawa e60969
       PNG_FP_1) == 0)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   return 0; /*success*/
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
png_XYZ_normalize(png_XYZ *XYZ)
fukasawa e60969
{
fukasawa e60969
   png_int_32 Y;
fukasawa e60969
fukasawa e60969
   if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
fukasawa e60969
      XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
fukasawa e60969
      XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
fukasawa e60969
      return 1;
fukasawa e60969
fukasawa e60969
   /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
fukasawa e60969
    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
fukasawa e60969
    * relying on addition of two positive values producing a negative one is not
fukasawa e60969
    * safe.
fukasawa e60969
    */
fukasawa e60969
   Y = XYZ->red_Y;
fukasawa e60969
   if (0x7fffffff - Y < XYZ->green_X)
fukasawa e60969
      return 1;
fukasawa e60969
   Y += XYZ->green_Y;
fukasawa e60969
   if (0x7fffffff - Y < XYZ->blue_X)
fukasawa e60969
      return 1;
fukasawa e60969
   Y += XYZ->blue_Y;
fukasawa e60969
fukasawa e60969
   if (Y != PNG_FP_1)
fukasawa e60969
   {
fukasawa e60969
      if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
      if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
      if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
fukasawa e60969
      if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
      if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
      if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
fukasawa e60969
      if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
      if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
      if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
fukasawa e60969
         return 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
fukasawa e60969
{
fukasawa e60969
   /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
fukasawa e60969
   if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->redx,   xy2->redx,  delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->redy,   xy2->redy,  delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->bluex,  xy2->bluex, delta) ||
fukasawa e60969
       PNG_OUT_OF_RANGE(xy1->bluey,  xy2->bluey, delta))
fukasawa e60969
      return 0;
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
fukasawa e60969
 * chunk chromaticities.  Earlier checks used to simply look for the overflow
fukasawa e60969
 * condition (where the determinant of the matrix to solve for XYZ ends up zero
fukasawa e60969
 * because the chromaticity values are not all distinct.)  Despite this it is
fukasawa e60969
 * theoretically possible to produce chromaticities that are apparently valid
fukasawa e60969
 * but that rapidly degrade to invalid, potentially crashing, sets because of
fukasawa e60969
 * arithmetic inaccuracies when calculations are performed on them.  The new
fukasawa e60969
 * check is to round-trip xy -> XYZ -> xy and then check that the result is
fukasawa e60969
 * within a small percentage of the original.
fukasawa e60969
 */
fukasawa e60969
static int
fukasawa e60969
png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
fukasawa e60969
{
fukasawa e60969
   int result;
fukasawa e60969
   png_xy xy_test;
fukasawa e60969
fukasawa e60969
   /* As a side-effect this routine also returns the XYZ endpoints. */
fukasawa e60969
   result = png_XYZ_from_xy(XYZ, xy);
fukasawa e60969
   if (result != 0)
fukasawa e60969
      return result;
fukasawa e60969
fukasawa e60969
   result = png_xy_from_XYZ(&xy_test, XYZ);
fukasawa e60969
   if (result != 0)
fukasawa e60969
      return result;
fukasawa e60969
fukasawa e60969
   if (png_colorspace_endpoints_match(xy, &xy_test,
fukasawa e60969
       5/*actually, the math is pretty accurate*/) != 0)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   /* Too much slip */
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* This is the check going the other way.  The XYZ is modified to normalize it
fukasawa e60969
 * (another side-effect) and the xy chromaticities are returned.
fukasawa e60969
 */
fukasawa e60969
static int
fukasawa e60969
png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
fukasawa e60969
{
fukasawa e60969
   int result;
fukasawa e60969
   png_XYZ XYZtemp;
fukasawa e60969
fukasawa e60969
   result = png_XYZ_normalize(XYZ);
fukasawa e60969
   if (result != 0)
fukasawa e60969
      return result;
fukasawa e60969
fukasawa e60969
   result = png_xy_from_XYZ(xy, XYZ);
fukasawa e60969
   if (result != 0)
fukasawa e60969
      return result;
fukasawa e60969
fukasawa e60969
   XYZtemp = *XYZ;
fukasawa e60969
   return png_colorspace_check_xy(&XYZtemp, xy);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Used to check for an endpoint match against sRGB */
fukasawa e60969
static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
fukasawa e60969
{
fukasawa e60969
   /* color      x       y */
fukasawa e60969
   /* red   */ 64000, 33000,
fukasawa e60969
   /* green */ 30000, 60000,
fukasawa e60969
   /* blue  */ 15000,  6000,
fukasawa e60969
   /* white */ 31270, 32900
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
fukasawa e60969
   png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
fukasawa e60969
   int preferred)
fukasawa e60969
{
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   /* The consistency check is performed on the chromaticities; this factors out
fukasawa e60969
    * variations because of the normalization (or not) of the end point Y
fukasawa e60969
    * values.
fukasawa e60969
    */
fukasawa e60969
   if (preferred < 2 &&
fukasawa e60969
       (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
fukasawa e60969
   {
fukasawa e60969
      /* The end points must be reasonably close to any we already have.  The
fukasawa e60969
       * following allows an error of up to +/-.001
fukasawa e60969
       */
fukasawa e60969
      if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
fukasawa e60969
          100) == 0)
fukasawa e60969
      {
fukasawa e60969
         colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
         png_benign_error(png_ptr, "inconsistent chromaticities");
fukasawa e60969
         return 0; /* failed */
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* Only overwrite with preferred values */
fukasawa e60969
      if (preferred == 0)
fukasawa e60969
         return 1; /* ok, but no change */
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   colorspace->end_points_xy = *xy;
fukasawa e60969
   colorspace->end_points_XYZ = *XYZ;
fukasawa e60969
   colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
fukasawa e60969
fukasawa e60969
   /* The end points are normally quoted to two decimal digits, so allow +/-0.01
fukasawa e60969
    * on this test.
fukasawa e60969
    */
fukasawa e60969
   if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
fukasawa e60969
      colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      colorspace->flags &= PNG_COLORSPACE_CANCEL(
fukasawa e60969
         PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
fukasawa e60969
fukasawa e60969
   return 2; /* ok and changed */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_colorspace_set_chromaticities(png_const_structrp png_ptr,
fukasawa e60969
   png_colorspacerp colorspace, const png_xy *xy, int preferred)
fukasawa e60969
{
fukasawa e60969
   /* We must check the end points to ensure they are reasonable - in the past
fukasawa e60969
    * color management systems have crashed as a result of getting bogus
fukasawa e60969
    * colorant values, while this isn't the fault of libpng it is the
fukasawa e60969
    * responsibility of libpng because PNG carries the bomb and libpng is in a
fukasawa e60969
    * position to protect against it.
fukasawa e60969
    */
fukasawa e60969
   png_XYZ XYZ;
fukasawa e60969
fukasawa e60969
   switch (png_colorspace_check_xy(&XYZ, xy))
fukasawa e60969
   {
fukasawa e60969
      case 0: /* success */
fukasawa e60969
         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
fukasawa e60969
            preferred);
fukasawa e60969
fukasawa e60969
      case 1:
fukasawa e60969
         /* We can't invert the chromaticities so we can't produce value XYZ
fukasawa e60969
          * values.  Likely as not a color management system will fail too.
fukasawa e60969
          */
fukasawa e60969
         colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
         png_benign_error(png_ptr, "invalid chromaticities");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         /* libpng is broken; this should be a warning but if it happens we
fukasawa e60969
          * want error reports so for the moment it is an error.
fukasawa e60969
          */
fukasawa e60969
         colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
         png_error(png_ptr, "internal error checking chromaticities");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 0; /* failed */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_colorspace_set_endpoints(png_const_structrp png_ptr,
fukasawa e60969
   png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
fukasawa e60969
{
fukasawa e60969
   png_XYZ XYZ = *XYZ_in;
fukasawa e60969
   png_xy xy;
fukasawa e60969
fukasawa e60969
   switch (png_colorspace_check_XYZ(&xy, &XYZ))
fukasawa e60969
   {
fukasawa e60969
      case 0:
fukasawa e60969
         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
fukasawa e60969
            preferred);
fukasawa e60969
fukasawa e60969
      case 1:
fukasawa e60969
         /* End points are invalid. */
fukasawa e60969
         colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
         png_benign_error(png_ptr, "invalid end points");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
         png_error(png_ptr, "internal error checking chromaticities");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 0; /* failed */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
fukasawa e60969
/* Error message generation */
fukasawa e60969
static char
fukasawa e60969
png_icc_tag_char(png_uint_32 byte)
fukasawa e60969
{
fukasawa e60969
   byte &= 0xff;
fukasawa e60969
   if (byte >= 32 && byte <= 126)
fukasawa e60969
      return (char)byte;
fukasawa e60969
   else
fukasawa e60969
      return '?';
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static void
fukasawa e60969
png_icc_tag_name(char *name, png_uint_32 tag)
fukasawa e60969
{
fukasawa e60969
   name[0] = '\'';
fukasawa e60969
   name[1] = png_icc_tag_char(tag >> 24);
fukasawa e60969
   name[2] = png_icc_tag_char(tag >> 16);
fukasawa e60969
   name[3] = png_icc_tag_char(tag >>  8);
fukasawa e60969
   name[4] = png_icc_tag_char(tag      );
fukasawa e60969
   name[5] = '\'';
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
is_ICC_signature_char(png_alloc_size_t it)
fukasawa e60969
{
fukasawa e60969
   return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
fukasawa e60969
      (it >= 97 && it <= 122);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
is_ICC_signature(png_alloc_size_t it)
fukasawa e60969
{
fukasawa e60969
   return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
fukasawa e60969
      is_ICC_signature_char((it >> 16) & 0xff) &&
fukasawa e60969
      is_ICC_signature_char((it >> 8) & 0xff) &&
fukasawa e60969
      is_ICC_signature_char(it & 0xff);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
fukasawa e60969
   png_const_charp name, png_alloc_size_t value, png_const_charp reason)
fukasawa e60969
{
fukasawa e60969
   size_t pos;
fukasawa e60969
   char message[196]; /* see below for calculation */
fukasawa e60969
fukasawa e60969
   if (colorspace != NULL)
fukasawa e60969
      colorspace->flags |= PNG_COLORSPACE_INVALID;
fukasawa e60969
fukasawa e60969
   pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
fukasawa e60969
   pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
fukasawa e60969
   pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
fukasawa e60969
   if (is_ICC_signature(value) != 0)
fukasawa e60969
   {
fukasawa e60969
      /* So 'value' is at most 4 bytes and the following cast is safe */
fukasawa e60969
      png_icc_tag_name(message+pos, (png_uint_32)value);
fukasawa e60969
      pos += 6; /* total +8; less than the else clause */
fukasawa e60969
      message[pos++] = ':';
fukasawa e60969
      message[pos++] = ' ';
fukasawa e60969
   }
fukasawa e60969
#  ifdef PNG_WARNINGS_SUPPORTED
fukasawa e60969
   else
fukasawa e60969
      {
fukasawa e60969
         char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
fukasawa e60969
fukasawa e60969
         pos = png_safecat(message, (sizeof message), pos,
fukasawa e60969
            png_format_number(number, number+(sizeof number),
fukasawa e60969
               PNG_NUMBER_FORMAT_x, value));
fukasawa e60969
         pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
fukasawa e60969
      }
fukasawa e60969
#  endif
fukasawa e60969
   /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
fukasawa e60969
   pos = png_safecat(message, (sizeof message), pos, reason);
fukasawa e60969
   PNG_UNUSED(pos)
fukasawa e60969
fukasawa e60969
   /* This is recoverable, but make it unconditionally an app_error on write to
fukasawa e60969
    * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
fukasawa e60969
    * on read, with a warning, but on write unless the app turns off
fukasawa e60969
    * application errors the PNG won't be written.)
fukasawa e60969
    */
fukasawa e60969
   png_chunk_report(png_ptr, message,
fukasawa e60969
      (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
fukasawa e60969
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
#endif /* sRGB || iCCP */
fukasawa e60969
fukasawa e60969
#ifdef PNG_sRGB_SUPPORTED
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
fukasawa e60969
   int intent)
fukasawa e60969
{
fukasawa e60969
   /* sRGB sets known gamma, end points and (from the chunk) intent. */
fukasawa e60969
   /* IMPORTANT: these are not necessarily the values found in an ICC profile
fukasawa e60969
    * because ICC profiles store values adapted to a D50 environment; it is
fukasawa e60969
    * expected that the ICC profile mediaWhitePointTag will be D50; see the
fukasawa e60969
    * checks and code elsewhere to understand this better.
fukasawa e60969
    *
fukasawa e60969
    * These XYZ values, which are accurate to 5dp, produce rgb to gray
fukasawa e60969
    * coefficients of (6968,23435,2366), which are reduced (because they add up
fukasawa e60969
    * to 32769 not 32768) to (6968,23434,2366).  These are the values that
fukasawa e60969
    * libpng has traditionally used (and are the best values given the 15bit
fukasawa e60969
    * algorithm used by the rgb to gray code.)
fukasawa e60969
    */
fukasawa e60969
   static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
fukasawa e60969
   {
fukasawa e60969
      /* color      X      Y      Z */
fukasawa e60969
      /* red   */ 41239, 21264,  1933,
fukasawa e60969
      /* green */ 35758, 71517, 11919,
fukasawa e60969
      /* blue  */ 18048,  7219, 95053
fukasawa e60969
   };
fukasawa e60969
fukasawa e60969
   /* Do nothing if the colorspace is already invalidated. */
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   /* Check the intent, then check for existing settings.  It is valid for the
fukasawa e60969
    * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
fukasawa e60969
    * be consistent with the correct values.  If, however, this function is
fukasawa e60969
    * called below because an iCCP chunk matches sRGB then it is quite
fukasawa e60969
    * conceivable that an older app recorded incorrect gAMA and cHRM because of
fukasawa e60969
    * an incorrect calculation based on the values in the profile - this does
fukasawa e60969
    * *not* invalidate the profile (though it still produces an error, which can
fukasawa e60969
    * be ignored.)
fukasawa e60969
    */
fukasawa e60969
   if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
fukasawa e60969
         (unsigned)intent, "invalid sRGB rendering intent");
fukasawa e60969
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
fukasawa e60969
      colorspace->rendering_intent != intent)
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
fukasawa e60969
         (unsigned)intent, "inconsistent rendering intents");
fukasawa e60969
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
fukasawa e60969
   {
fukasawa e60969
      png_benign_error(png_ptr, "duplicate sRGB information ignored");
fukasawa e60969
      return 0;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* If the standard sRGB cHRM chunk does not match the one from the PNG file
fukasawa e60969
    * warn but overwrite the value with the correct one.
fukasawa e60969
    */
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
fukasawa e60969
      !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
fukasawa e60969
         100))
fukasawa e60969
      png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
fukasawa e60969
         PNG_CHUNK_ERROR);
fukasawa e60969
fukasawa e60969
   /* This check is just done for the error reporting - the routine always
fukasawa e60969
    * returns true when the 'from' argument corresponds to sRGB (2).
fukasawa e60969
    */
fukasawa e60969
   (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
fukasawa e60969
      2/*from sRGB*/);
fukasawa e60969
fukasawa e60969
   /* intent: bugs in GCC force 'int' to be used as the parameter type. */
fukasawa e60969
   colorspace->rendering_intent = (png_uint_16)intent;
fukasawa e60969
   colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
fukasawa e60969
fukasawa e60969
   /* endpoints */
fukasawa e60969
   colorspace->end_points_xy = sRGB_xy;
fukasawa e60969
   colorspace->end_points_XYZ = sRGB_XYZ;
fukasawa e60969
   colorspace->flags |=
fukasawa e60969
      (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
fukasawa e60969
fukasawa e60969
   /* gamma */
fukasawa e60969
   colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
fukasawa e60969
   colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
fukasawa e60969
fukasawa e60969
   /* Finally record that we have an sRGB profile */
fukasawa e60969
   colorspace->flags |=
fukasawa e60969
      (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
fukasawa e60969
fukasawa e60969
   return 1; /* set */
fukasawa e60969
}
fukasawa e60969
#endif /* sRGB */
fukasawa e60969
fukasawa e60969
#ifdef PNG_iCCP_SUPPORTED
fukasawa e60969
/* Encoded value of D50 as an ICC XYZNumber.  From the ICC 2010 spec the value
fukasawa e60969
 * is XYZ(0.9642,1.0,0.8249), which scales to:
fukasawa e60969
 *
fukasawa e60969
 *    (63189.8112, 65536, 54060.6464)
fukasawa e60969
 */
fukasawa e60969
static const png_byte D50_nCIEXYZ[12] =
fukasawa e60969
   { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
fukasawa e60969
   png_const_charp name, png_uint_32 profile_length)
fukasawa e60969
{
fukasawa e60969
   if (profile_length < 132)
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
fukasawa e60969
         "too short");
fukasawa e60969
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
fukasawa e60969
   png_const_charp name, png_uint_32 profile_length,
fukasawa e60969
   png_const_bytep profile/* first 132 bytes only */, int color_type)
fukasawa e60969
{
fukasawa e60969
   png_uint_32 temp;
fukasawa e60969
fukasawa e60969
   /* Length check; this cannot be ignored in this code because profile_length
fukasawa e60969
    * is used later to check the tag table, so even if the profile seems over
fukasawa e60969
    * long profile_length from the caller must be correct.  The caller can fix
fukasawa e60969
    * this up on read or write by just passing in the profile header length.
fukasawa e60969
    */
fukasawa e60969
   temp = png_get_uint_32(profile);
fukasawa e60969
   if (temp != profile_length)
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
         "length does not match profile");
fukasawa e60969
fukasawa e60969
   temp = (png_uint_32) (*(profile+8));
fukasawa e60969
   if (temp > 3 && (profile_length & 3))
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
fukasawa e60969
         "invalid length");
fukasawa e60969
fukasawa e60969
   temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
fukasawa e60969
   if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
fukasawa e60969
      profile_length < 132+12*temp) /* truncated tag table */
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
         "tag count too large");
fukasawa e60969
fukasawa e60969
   /* The 'intent' must be valid or we can't store it, ICC limits the intent to
fukasawa e60969
    * 16 bits.
fukasawa e60969
    */
fukasawa e60969
   temp = png_get_uint_32(profile+64);
fukasawa e60969
   if (temp >= 0xffff) /* The ICC limit */
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
         "invalid rendering intent");
fukasawa e60969
fukasawa e60969
   /* This is just a warning because the profile may be valid in future
fukasawa e60969
    * versions.
fukasawa e60969
    */
fukasawa e60969
   if (temp >= PNG_sRGB_INTENT_LAST)
fukasawa e60969
      (void)png_icc_profile_error(png_ptr, NULL, name, temp,
fukasawa e60969
         "intent outside defined range");
fukasawa e60969
fukasawa e60969
   /* At this point the tag table can't be checked because it hasn't necessarily
fukasawa e60969
    * been loaded; however, various header fields can be checked.  These checks
fukasawa e60969
    * are for values permitted by the PNG spec in an ICC profile; the PNG spec
fukasawa e60969
    * restricts the profiles that can be passed in an iCCP chunk (they must be
fukasawa e60969
    * appropriate to processing PNG data!)
fukasawa e60969
    */
fukasawa e60969
fukasawa e60969
   /* Data checks (could be skipped).  These checks must be independent of the
fukasawa e60969
    * version number; however, the version number doesn't accomodate changes in
fukasawa e60969
    * the header fields (just the known tags and the interpretation of the
fukasawa e60969
    * data.)
fukasawa e60969
    */
fukasawa e60969
   temp = png_get_uint_32(profile+36); /* signature 'ascp' */
fukasawa e60969
   if (temp != 0x61637370)
fukasawa e60969
      return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
         "invalid signature");
fukasawa e60969
fukasawa e60969
   /* Currently the PCS illuminant/adopted white point (the computational
fukasawa e60969
    * white point) are required to be D50,
fukasawa e60969
    * however the profile contains a record of the illuminant so perhaps ICC
fukasawa e60969
    * expects to be able to change this in the future (despite the rationale in
fukasawa e60969
    * the introduction for using a fixed PCS adopted white.)  Consequently the
fukasawa e60969
    * following is just a warning.
fukasawa e60969
    */
fukasawa e60969
   if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
fukasawa e60969
      (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
fukasawa e60969
         "PCS illuminant is not D50");
fukasawa e60969
fukasawa e60969
   /* The PNG spec requires this:
fukasawa e60969
    * "If the iCCP chunk is present, the image samples conform to the colour
fukasawa e60969
    * space represented by the embedded ICC profile as defined by the
fukasawa e60969
    * International Color Consortium [ICC]. The colour space of the ICC profile
fukasawa e60969
    * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
fukasawa e60969
    * 6), or a greyscale colour space for greyscale images (PNG colour types 0
fukasawa e60969
    * and 4)."
fukasawa e60969
    *
fukasawa e60969
    * This checking code ensures the embedded profile (on either read or write)
fukasawa e60969
    * conforms to the specification requirements.  Notice that an ICC 'gray'
fukasawa e60969
    * color-space profile contains the information to transform the monochrome
fukasawa e60969
    * data to XYZ or L*a*b (according to which PCS the profile uses) and this
fukasawa e60969
    * should be used in preference to the standard libpng K channel replication
fukasawa e60969
    * into R, G and B channels.
fukasawa e60969
    *
fukasawa e60969
    * Previously it was suggested that an RGB profile on grayscale data could be
fukasawa e60969
    * handled.  However it it is clear that using an RGB profile in this context
fukasawa e60969
    * must be an error - there is no specification of what it means.  Thus it is
fukasawa e60969
    * almost certainly more correct to ignore the profile.
fukasawa e60969
    */
fukasawa e60969
   temp = png_get_uint_32(profile+16); /* data colour space field */
fukasawa e60969
   switch (temp)
fukasawa e60969
   {
fukasawa e60969
      case 0x52474220: /* 'RGB ' */
fukasawa e60969
         if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
fukasawa e60969
            return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
               "RGB color space not permitted on grayscale PNG");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 0x47524159: /* 'GRAY' */
fukasawa e60969
         if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
fukasawa e60969
            return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
               "Gray color space not permitted on RGB PNG");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
            "invalid ICC profile color space");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* It is up to the application to check that the profile class matches the
fukasawa e60969
    * application requirements; the spec provides no guidance, but it's pretty
fukasawa e60969
    * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
fukasawa e60969
    * ('prtr') or 'spac' (for generic color spaces).  Issue a warning in these
fukasawa e60969
    * cases.  Issue an error for device link or abstract profiles - these don't
fukasawa e60969
    * contain the records necessary to transform the color-space to anything
fukasawa e60969
    * other than the target device (and not even that for an abstract profile).
fukasawa e60969
    * Profiles of these classes may not be embedded in images.
fukasawa e60969
    */
fukasawa e60969
   temp = png_get_uint_32(profile+12); /* profile/device class */
fukasawa e60969
   switch (temp)
fukasawa e60969
   {
fukasawa e60969
      case 0x73636e72: /* 'scnr' */
fukasawa e60969
      case 0x6d6e7472: /* 'mntr' */
fukasawa e60969
      case 0x70727472: /* 'prtr' */
fukasawa e60969
      case 0x73706163: /* 'spac' */
fukasawa e60969
         /* All supported */
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case 0x61627374: /* 'abst' */
fukasawa e60969
         /* May not be embedded in an image */
fukasawa e60969
         return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
            "invalid embedded Abstract ICC profile");
fukasawa e60969
fukasawa e60969
      case 0x6c696e6b: /* 'link' */
fukasawa e60969
         /* DeviceLink profiles cannot be interpreted in a non-device specific
fukasawa e60969
          * fashion, if an app uses the AToB0Tag in the profile the results are
fukasawa e60969
          * undefined unless the result is sent to the intended device,
fukasawa e60969
          * therefore a DeviceLink profile should not be found embedded in a
fukasawa e60969
          * PNG.
fukasawa e60969
          */
fukasawa e60969
         return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
            "unexpected DeviceLink ICC profile class");
fukasawa e60969
fukasawa e60969
      case 0x6e6d636c: /* 'nmcl' */
fukasawa e60969
         /* A NamedColor profile is also device specific, however it doesn't
fukasawa e60969
          * contain an AToB0 tag that is open to misinterpretation.  Almost
fukasawa e60969
          * certainly it will fail the tests below.
fukasawa e60969
          */
fukasawa e60969
         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
fukasawa e60969
            "unexpected NamedColor ICC profile class");
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         /* To allow for future enhancements to the profile accept unrecognized
fukasawa e60969
          * profile classes with a warning, these then hit the test below on the
fukasawa e60969
          * tag content to ensure they are backward compatible with one of the
fukasawa e60969
          * understood profiles.
fukasawa e60969
          */
fukasawa e60969
         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
fukasawa e60969
            "unrecognized ICC profile class");
fukasawa e60969
         break;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* For any profile other than a device link one the PCS must be encoded
fukasawa e60969
    * either in XYZ or Lab.
fukasawa e60969
    */
fukasawa e60969
   temp = png_get_uint_32(profile+20);
fukasawa e60969
   switch (temp)
fukasawa e60969
   {
fukasawa e60969
      case 0x58595a20: /* 'XYZ ' */
fukasawa e60969
      case 0x4c616220: /* 'Lab ' */
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      default:
fukasawa e60969
         return png_icc_profile_error(png_ptr, colorspace, name, temp,
fukasawa e60969
            "unexpected ICC PCS encoding");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
fukasawa e60969
   png_const_charp name, png_uint_32 profile_length,
fukasawa e60969
   png_const_bytep profile /* header plus whole tag table */)
fukasawa e60969
{
fukasawa e60969
   png_uint_32 tag_count = png_get_uint_32(profile+128);
fukasawa e60969
   png_uint_32 itag;
fukasawa e60969
   png_const_bytep tag = profile+132; /* The first tag */
fukasawa e60969
fukasawa e60969
   /* First scan all the tags in the table and add bits to the icc_info value
fukasawa e60969
    * (temporarily in 'tags').
fukasawa e60969
    */
fukasawa e60969
   for (itag=0; itag < tag_count; ++itag, tag += 12)
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 tag_id = png_get_uint_32(tag+0);
fukasawa e60969
      png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
fukasawa e60969
      png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
fukasawa e60969
fukasawa e60969
      /* The ICC specification does not exclude zero length tags, therefore the
fukasawa e60969
       * start might actually be anywhere if there is no data, but this would be
fukasawa e60969
       * a clear abuse of the intent of the standard so the start is checked for
fukasawa e60969
       * being in range.  All defined tag types have an 8 byte header - a 4 byte
fukasawa e60969
       * type signature then 0.
fukasawa e60969
       */
fukasawa e60969
      if ((tag_start & 3) != 0)
fukasawa e60969
      {
fukasawa e60969
         /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
fukasawa e60969
          * only a warning here because libpng does not care about the
fukasawa e60969
          * alignment.
fukasawa e60969
          */
fukasawa e60969
         (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
fukasawa e60969
            "ICC profile tag start not a multiple of 4");
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* This is a hard error; potentially it can cause read outside the
fukasawa e60969
       * profile.
fukasawa e60969
       */
fukasawa e60969
      if (tag_start > profile_length || tag_length > profile_length - tag_start)
fukasawa e60969
         return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
fukasawa e60969
            "ICC profile tag outside profile");
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 1; /* success, maybe with warnings */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#ifdef PNG_sRGB_SUPPORTED
fukasawa e60969
#if PNG_sRGB_PROFILE_CHECKS >= 0
fukasawa e60969
/* Information about the known ICC sRGB profiles */
fukasawa e60969
static const struct
fukasawa e60969
{
fukasawa e60969
   png_uint_32 adler, crc, length;
fukasawa e60969
   png_uint_32 md5[4];
fukasawa e60969
   png_byte    have_md5;
fukasawa e60969
   png_byte    is_broken;
fukasawa e60969
   png_uint_16 intent;
fukasawa e60969
fukasawa e60969
#  define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
fukasawa e60969
#  define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
fukasawa e60969
      { adler, crc, length, md5, broke, intent },
fukasawa e60969
fukasawa e60969
} png_sRGB_checks[] =
fukasawa e60969
{
fukasawa e60969
   /* This data comes from contrib/tools/checksum-icc run on downloads of
fukasawa e60969
    * all four ICC sRGB profiles from www.color.org.
fukasawa e60969
    */
fukasawa e60969
   /* adler32, crc32, MD5[4], intent, date, length, file-name */
fukasawa e60969
   PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
fukasawa e60969
      PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
fukasawa e60969
      "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
fukasawa e60969
fukasawa e60969
   /* ICC sRGB v2 perceptual no black-compensation: */
fukasawa e60969
   PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
fukasawa e60969
      PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
fukasawa e60969
      "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
fukasawa e60969
fukasawa e60969
   PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
fukasawa e60969
      PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
fukasawa e60969
      "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
fukasawa e60969
fukasawa e60969
   /* ICC sRGB v4 perceptual */
fukasawa e60969
   PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
fukasawa e60969
      PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
fukasawa e60969
      "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
fukasawa e60969
fukasawa e60969
   /* The following profiles have no known MD5 checksum. If there is a match
fukasawa e60969
    * on the (empty) MD5 the other fields are used to attempt a match and
fukasawa e60969
    * a warning is produced.  The first two of these profiles have a 'cprt' tag
fukasawa e60969
    * which suggests that they were also made by Hewlett Packard.
fukasawa e60969
    */
fukasawa e60969
   PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
fukasawa e60969
      PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
fukasawa e60969
      "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
fukasawa e60969
fukasawa e60969
   /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
fukasawa e60969
    * match the D50 PCS illuminant in the header (it is in fact the D65 values,
fukasawa e60969
    * so the white point is recorded as the un-adapted value.)  The profiles
fukasawa e60969
    * below only differ in one byte - the intent - and are basically the same as
fukasawa e60969
    * the previous profile except for the mediaWhitePointTag error and a missing
fukasawa e60969
    * chromaticAdaptationTag.
fukasawa e60969
    */
fukasawa e60969
   PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
fukasawa e60969
      PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
fukasawa e60969
      "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
fukasawa e60969
fukasawa e60969
   PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
fukasawa e60969
      PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
fukasawa e60969
      "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static int
fukasawa e60969
png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
fukasawa e60969
   png_const_bytep profile, uLong adler)
fukasawa e60969
{
fukasawa e60969
   /* The quick check is to verify just the MD5 signature and trust the
fukasawa e60969
    * rest of the data.  Because the profile has already been verified for
fukasawa e60969
    * correctness this is safe.  png_colorspace_set_sRGB will check the 'intent'
fukasawa e60969
    * field too, so if the profile has been edited with an intent not defined
fukasawa e60969
    * by sRGB (but maybe defined by a later ICC specification) the read of
fukasawa e60969
    * the profile will fail at that point.
fukasawa e60969
    */
fukasawa e60969
fukasawa e60969
   png_uint_32 length = 0;
fukasawa e60969
   png_uint_32 intent = 0x10000; /* invalid */
fukasawa e60969
#if PNG_sRGB_PROFILE_CHECKS > 1
fukasawa e60969
   uLong crc = 0; /* the value for 0 length data */
fukasawa e60969
#endif
fukasawa e60969
   unsigned int i;
fukasawa e60969
fukasawa e60969
#ifdef PNG_SET_OPTION_SUPPORTED
fukasawa e60969
   /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */
fukasawa e60969
   if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
fukasawa e60969
               PNG_OPTION_ON)
fukasawa e60969
      return 0;
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
fukasawa e60969
   {
fukasawa e60969
      if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
fukasawa e60969
         png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
fukasawa e60969
         png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
fukasawa e60969
         png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
fukasawa e60969
      {
fukasawa e60969
         /* This may be one of the old HP profiles without an MD5, in that
fukasawa e60969
          * case we can only use the length and Adler32 (note that these
fukasawa e60969
          * are not used by default if there is an MD5!)
fukasawa e60969
          */
fukasawa e60969
#        if PNG_sRGB_PROFILE_CHECKS == 0
fukasawa e60969
            if (png_sRGB_checks[i].have_md5 != 0)
fukasawa e60969
               return 1+png_sRGB_checks[i].is_broken;
fukasawa e60969
#        endif
fukasawa e60969
fukasawa e60969
         /* Profile is unsigned or more checks have been configured in. */
fukasawa e60969
         if (length == 0)
fukasawa e60969
         {
fukasawa e60969
            length = png_get_uint_32(profile);
fukasawa e60969
            intent = png_get_uint_32(profile+64);
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         /* Length *and* intent must match */
fukasawa e60969
         if (length == (png_uint_32) png_sRGB_checks[i].length &&
fukasawa e60969
            intent == (png_uint_32) png_sRGB_checks[i].intent)
fukasawa e60969
         {
fukasawa e60969
            /* Now calculate the adler32 if not done already. */
fukasawa e60969
            if (adler == 0)
fukasawa e60969
            {
fukasawa e60969
               adler = adler32(0, NULL, 0);
fukasawa e60969
               adler = adler32(adler, profile, length);
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            if (adler == png_sRGB_checks[i].adler)
fukasawa e60969
            {
fukasawa e60969
               /* These basic checks suggest that the data has not been
fukasawa e60969
                * modified, but if the check level is more than 1 perform
fukasawa e60969
                * our own crc32 checksum on the data.
fukasawa e60969
                */
fukasawa e60969
#              if PNG_sRGB_PROFILE_CHECKS > 1
fukasawa e60969
                  if (crc == 0)
fukasawa e60969
                  {
fukasawa e60969
                     crc = crc32(0, NULL, 0);
fukasawa e60969
                     crc = crc32(crc, profile, length);
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  /* So this check must pass for the 'return' below to happen.
fukasawa e60969
                   */
fukasawa e60969
                  if (crc == png_sRGB_checks[i].crc)
fukasawa e60969
#              endif
fukasawa e60969
               {
fukasawa e60969
                  if (png_sRGB_checks[i].is_broken != 0)
fukasawa e60969
                  {
fukasawa e60969
                     /* These profiles are known to have bad data that may cause
fukasawa e60969
                      * problems if they are used, therefore attempt to
fukasawa e60969
                      * discourage their use, skip the 'have_md5' warning below,
fukasawa e60969
                      * which is made irrelevant by this error.
fukasawa e60969
                      */
fukasawa e60969
                     png_chunk_report(png_ptr, "known incorrect sRGB profile",
fukasawa e60969
                        PNG_CHUNK_ERROR);
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  /* Warn that this being done; this isn't even an error since
fukasawa e60969
                   * the profile is perfectly valid, but it would be nice if
fukasawa e60969
                   * people used the up-to-date ones.
fukasawa e60969
                   */
fukasawa e60969
                  else if (png_sRGB_checks[i].have_md5 == 0)
fukasawa e60969
                  {
fukasawa e60969
                     png_chunk_report(png_ptr,
fukasawa e60969
                        "out-of-date sRGB profile with no signature",
fukasawa e60969
                        PNG_CHUNK_WARNING);
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  return 1+png_sRGB_checks[i].is_broken;
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
# if PNG_sRGB_PROFILE_CHECKS > 0
fukasawa e60969
         /* The signature matched, but the profile had been changed in some
fukasawa e60969
          * way.  This probably indicates a data error or uninformed hacking.
fukasawa e60969
          * Fall through to "no match".
fukasawa e60969
          */
fukasawa e60969
         png_chunk_report(png_ptr,
fukasawa e60969
             "Not recognizing known sRGB profile that has been edited",
fukasawa e60969
             PNG_CHUNK_WARNING);
fukasawa e60969
         break;
fukasawa e60969
# endif
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 0; /* no match */
fukasawa e60969
}
fukasawa e60969
#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
fukasawa e60969
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_icc_set_sRGB(png_const_structrp png_ptr,
fukasawa e60969
   png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
fukasawa e60969
{
fukasawa e60969
   /* Is this profile one of the known ICC sRGB profiles?  If it is, just set
fukasawa e60969
    * the sRGB information.
fukasawa e60969
    */
fukasawa e60969
#if PNG_sRGB_PROFILE_CHECKS >= 0
fukasawa e60969
   if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
fukasawa e60969
#endif
fukasawa e60969
      (void)png_colorspace_set_sRGB(png_ptr, colorspace,
fukasawa e60969
         (int)/*already checked*/png_get_uint_32(profile+64));
fukasawa e60969
}
fukasawa e60969
#endif /* sRGB */
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
fukasawa e60969
   png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
fukasawa e60969
   int color_type)
fukasawa e60969
{
fukasawa e60969
   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
fukasawa e60969
       png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
fukasawa e60969
          color_type) != 0 &&
fukasawa e60969
       png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
fukasawa e60969
          profile) != 0)
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_sRGB_SUPPORTED
fukasawa e60969
         /* If no sRGB support, don't try storing sRGB information */
fukasawa e60969
         png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
fukasawa e60969
#     endif
fukasawa e60969
      return 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Failure case */
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
#endif /* iCCP */
fukasawa e60969
fukasawa e60969
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   /* Set the rgb_to_gray coefficients from the colorspace. */
fukasawa e60969
   if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
fukasawa e60969
      (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
fukasawa e60969
   {
fukasawa e60969
      /* png_set_background has not been called, get the coefficients from the Y
fukasawa e60969
       * values of the colorspace colorants.
fukasawa e60969
       */
fukasawa e60969
      png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
fukasawa e60969
      png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
fukasawa e60969
      png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
fukasawa e60969
      png_fixed_point total = r+g+b;
fukasawa e60969
fukasawa e60969
      if (total > 0 &&
fukasawa e60969
         r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
fukasawa e60969
         g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
fukasawa e60969
         b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
fukasawa e60969
         r+g+b <= 32769)
fukasawa e60969
      {
fukasawa e60969
         /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
fukasawa e60969
          * all of the coefficients were rounded up.  Handle this by
fukasawa e60969
          * reducing the *largest* coefficient by 1; this matches the
fukasawa e60969
          * approach used for the default coefficients in pngrtran.c
fukasawa e60969
          */
fukasawa e60969
         int add = 0;
fukasawa e60969
fukasawa e60969
         if (r+g+b > 32768)
fukasawa e60969
            add = -1;
fukasawa e60969
         else if (r+g+b < 32768)
fukasawa e60969
            add = 1;
fukasawa e60969
fukasawa e60969
         if (add != 0)
fukasawa e60969
         {
fukasawa e60969
            if (g >= r && g >= b)
fukasawa e60969
               g += add;
fukasawa e60969
            else if (r >= g && r >= b)
fukasawa e60969
               r += add;
fukasawa e60969
            else
fukasawa e60969
               b += add;
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         /* Check for an internal error. */
fukasawa e60969
         if (r+g+b != 32768)
fukasawa e60969
            png_error(png_ptr,
fukasawa e60969
               "internal error handling cHRM coefficients");
fukasawa e60969
fukasawa e60969
         else
fukasawa e60969
         {
fukasawa e60969
            png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
fukasawa e60969
            png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* This is a png_error at present even though it could be ignored -
fukasawa e60969
       * it should never happen, but it is important that if it does, the
fukasawa e60969
       * bug is fixed.
fukasawa e60969
       */
fukasawa e60969
      else
fukasawa e60969
         png_error(png_ptr, "internal error handling cHRM->XYZ");
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
#endif /* READ_RGB_TO_GRAY */
fukasawa e60969
fukasawa e60969
#endif /* COLORSPACE */
fukasawa e60969
fukasawa e60969
#ifdef __GNUC__
fukasawa e60969
/* This exists solely to work round a warning from GNU C. */
fukasawa e60969
static int /* PRIVATE */
fukasawa e60969
png_gt(size_t a, size_t b)
fukasawa e60969
{
fukasawa e60969
    return a > b;
fukasawa e60969
}
fukasawa e60969
#else
fukasawa e60969
#   define png_gt(a,b) ((a) > (b))
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_check_IHDR(png_const_structrp png_ptr,
fukasawa e60969
   png_uint_32 width, png_uint_32 height, int bit_depth,
fukasawa e60969
   int color_type, int interlace_type, int compression_type,
fukasawa e60969
   int filter_type)
fukasawa e60969
{
fukasawa e60969
   int error = 0;
fukasawa e60969
fukasawa e60969
   /* Check for width and height valid values */
fukasawa e60969
   if (width == 0)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Image width is zero in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (width > PNG_UINT_31_MAX)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Invalid image width in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (png_gt(((width + 7) & (~7)),
fukasawa e60969
       ((PNG_SIZE_MAX
fukasawa e60969
           - 48        /* big_row_buf hack */
fukasawa e60969
           - 1)        /* filter byte */
fukasawa e60969
           / 8)        /* 8-byte RGBA pixels */
fukasawa e60969
           - 1))       /* extra max_pixel_depth pad */
fukasawa e60969
   {
fukasawa e60969
      /* The size of the row must be within the limits of this architecture.
fukasawa e60969
       * Because the read code can perform arbitrary transformations the
fukasawa e60969
       * maximum size is checked here.  Because the code in png_read_start_row
fukasawa e60969
       * adds extra space "for safety's sake" in several places a conservative
fukasawa e60969
       * limit is used here.
fukasawa e60969
       *
fukasawa e60969
       * NOTE: it would be far better to check the size that is actually used,
fukasawa e60969
       * but the effect in the real world is minor and the changes are more
fukasawa e60969
       * extensive, therefore much more dangerous and much more difficult to
fukasawa e60969
       * write in a way that avoids compiler warnings.
fukasawa e60969
       */
fukasawa e60969
      png_warning(png_ptr, "Image width is too large for this architecture");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
fukasawa e60969
   if (width > png_ptr->user_width_max)
fukasawa e60969
#else
fukasawa e60969
   if (width > PNG_USER_WIDTH_MAX)
fukasawa e60969
#endif
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Image width exceeds user limit in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (height == 0)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Image height is zero in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (height > PNG_UINT_31_MAX)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Invalid image height in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
fukasawa e60969
   if (height > png_ptr->user_height_max)
fukasawa e60969
#else
fukasawa e60969
   if (height > PNG_USER_HEIGHT_MAX)
fukasawa e60969
#endif
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Image height exceeds user limit in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Check other values */
fukasawa e60969
   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
fukasawa e60969
       bit_depth != 8 && bit_depth != 16)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Invalid bit depth in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (color_type < 0 || color_type == 1 ||
fukasawa e60969
       color_type == 5 || color_type > 6)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Invalid color type in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
fukasawa e60969
       ((color_type == PNG_COLOR_TYPE_RGB ||
fukasawa e60969
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
fukasawa e60969
         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (interlace_type >= PNG_INTERLACE_LAST)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Unknown interlace method in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Unknown compression method in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
#ifdef PNG_MNG_FEATURES_SUPPORTED
fukasawa e60969
   /* Accept filter_method 64 (intrapixel differencing) only if
fukasawa e60969
    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
fukasawa e60969
    * 2. Libpng did not read a PNG signature (this filter_method is only
fukasawa e60969
    *    used in PNG datastreams that are embedded in MNG datastreams) and
fukasawa e60969
    * 3. The application called png_permit_mng_features with a mask that
fukasawa e60969
    *    included PNG_FLAG_MNG_FILTER_64 and
fukasawa e60969
    * 4. The filter_method is 64 and
fukasawa e60969
    * 5. The color_type is RGB or RGBA
fukasawa e60969
    */
fukasawa e60969
   if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
fukasawa e60969
       png_ptr->mng_features_permitted != 0)
fukasawa e60969
      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
fukasawa e60969
fukasawa e60969
   if (filter_type != PNG_FILTER_TYPE_BASE)
fukasawa e60969
   {
fukasawa e60969
      if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
fukasawa e60969
          (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
fukasawa e60969
          ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
fukasawa e60969
          (color_type == PNG_COLOR_TYPE_RGB ||
fukasawa e60969
          color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
fukasawa e60969
      {
fukasawa e60969
         png_warning(png_ptr, "Unknown filter method in IHDR");
fukasawa e60969
         error = 1;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0)
fukasawa e60969
      {
fukasawa e60969
         png_warning(png_ptr, "Invalid filter method in IHDR");
fukasawa e60969
         error = 1;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
#else
fukasawa e60969
   if (filter_type != PNG_FILTER_TYPE_BASE)
fukasawa e60969
   {
fukasawa e60969
      png_warning(png_ptr, "Unknown filter method in IHDR");
fukasawa e60969
      error = 1;
fukasawa e60969
   }
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   if (error == 1)
fukasawa e60969
      png_error(png_ptr, "Invalid IHDR data");
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
fukasawa e60969
/* ASCII to fp functions */
fukasawa e60969
/* Check an ASCII formated floating point value, see the more detailed
fukasawa e60969
 * comments in pngpriv.h
fukasawa e60969
 */
fukasawa e60969
/* The following is used internally to preserve the sticky flags */
fukasawa e60969
#define png_fp_add(state, flags) ((state) |= (flags))
fukasawa e60969
#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
fukasawa e60969
   png_size_tp whereami)
fukasawa e60969
{
fukasawa e60969
   int state = *statep;
fukasawa e60969
   png_size_t i = *whereami;
fukasawa e60969
fukasawa e60969
   while (i < size)
fukasawa e60969
   {
fukasawa e60969
      int type;
fukasawa e60969
      /* First find the type of the next character */
fukasawa e60969
      switch (string[i])
fukasawa e60969
      {
fukasawa e60969
      case 43:  type = PNG_FP_SAW_SIGN;                   break;
fukasawa e60969
      case 45:  type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
fukasawa e60969
      case 46:  type = PNG_FP_SAW_DOT;                    break;
fukasawa e60969
      case 48:  type = PNG_FP_SAW_DIGIT;                  break;
fukasawa e60969
      case 49: case 50: case 51: case 52:
fukasawa e60969
      case 53: case 54: case 55: case 56:
fukasawa e60969
      case 57:  type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
fukasawa e60969
      case 69:
fukasawa e60969
      case 101: type = PNG_FP_SAW_E;                      break;
fukasawa e60969
      default:  goto PNG_FP_End;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* Now deal with this type according to the current
fukasawa e60969
       * state, the type is arranged to not overlap the
fukasawa e60969
       * bits of the PNG_FP_STATE.
fukasawa e60969
       */
fukasawa e60969
      switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
fukasawa e60969
      {
fukasawa e60969
      case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
fukasawa e60969
         if ((state & PNG_FP_SAW_ANY) != 0)
fukasawa e60969
            goto PNG_FP_End; /* not a part of the number */
fukasawa e60969
fukasawa e60969
         png_fp_add(state, type);
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
fukasawa e60969
         /* Ok as trailer, ok as lead of fraction. */
fukasawa e60969
         if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */
fukasawa e60969
            goto PNG_FP_End;
fukasawa e60969
fukasawa e60969
         else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */
fukasawa e60969
            png_fp_add(state, type);
fukasawa e60969
fukasawa e60969
         else
fukasawa e60969
            png_fp_set(state, PNG_FP_FRACTION | type);
fukasawa e60969
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
fukasawa e60969
         if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */
fukasawa e60969
            png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
fukasawa e60969
fukasawa e60969
         png_fp_add(state, type | PNG_FP_WAS_VALID);
fukasawa e60969
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_FP_INTEGER + PNG_FP_SAW_E:
fukasawa e60969
         if ((state & PNG_FP_SAW_DIGIT) == 0)
fukasawa e60969
            goto PNG_FP_End;
fukasawa e60969
fukasawa e60969
         png_fp_set(state, PNG_FP_EXPONENT);
fukasawa e60969
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
   /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:
fukasawa e60969
         goto PNG_FP_End; ** no sign in fraction */
fukasawa e60969
fukasawa e60969
   /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:
fukasawa e60969
         goto PNG_FP_End; ** Because SAW_DOT is always set */
fukasawa e60969
fukasawa e60969
      case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
fukasawa e60969
         png_fp_add(state, type | PNG_FP_WAS_VALID);
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_FP_FRACTION + PNG_FP_SAW_E:
fukasawa e60969
         /* This is correct because the trailing '.' on an
fukasawa e60969
          * integer is handled above - so we can only get here
fukasawa e60969
          * with the sequence ".E" (with no preceding digits).
fukasawa e60969
          */
fukasawa e60969
         if ((state & PNG_FP_SAW_DIGIT) == 0)
fukasawa e60969
            goto PNG_FP_End;
fukasawa e60969
fukasawa e60969
         png_fp_set(state, PNG_FP_EXPONENT);
fukasawa e60969
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
      case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
fukasawa e60969
         if ((state & PNG_FP_SAW_ANY) != 0)
fukasawa e60969
            goto PNG_FP_End; /* not a part of the number */
fukasawa e60969
fukasawa e60969
         png_fp_add(state, PNG_FP_SAW_SIGN);
fukasawa e60969
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
   /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:
fukasawa e60969
         goto PNG_FP_End; */
fukasawa e60969
fukasawa e60969
      case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
fukasawa e60969
         png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
fukasawa e60969
fukasawa e60969
         break;
fukasawa e60969
fukasawa e60969
   /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:
fukasawa e60969
         goto PNG_FP_End; */
fukasawa e60969
fukasawa e60969
      default: goto PNG_FP_End; /* I.e. break 2 */
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      /* The character seems ok, continue. */
fukasawa e60969
      ++i;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
PNG_FP_End:
fukasawa e60969
   /* Here at the end, update the state and return the correct
fukasawa e60969
    * return code.
fukasawa e60969
    */
fukasawa e60969
   *statep = state;
fukasawa e60969
   *whereami = i;
fukasawa e60969
fukasawa e60969
   return (state & PNG_FP_SAW_DIGIT) != 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
fukasawa e60969
/* The same but for a complete string. */
fukasawa e60969
int
fukasawa e60969
png_check_fp_string(png_const_charp string, png_size_t size)
fukasawa e60969
{
fukasawa e60969
   int        state=0;
fukasawa e60969
   png_size_t char_index=0;
fukasawa e60969
fukasawa e60969
   if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
fukasawa e60969
      (char_index == size || string[char_index] == 0))
fukasawa e60969
      return state /* must be non-zero - see above */;
fukasawa e60969
fukasawa e60969
   return 0; /* i.e. fail */
fukasawa e60969
}
fukasawa e60969
#endif /* pCAL || sCAL */
fukasawa e60969
fukasawa e60969
#ifdef PNG_sCAL_SUPPORTED
fukasawa e60969
#  ifdef PNG_FLOATING_POINT_SUPPORTED
fukasawa e60969
/* Utility used below - a simple accurate power of ten from an integral
fukasawa e60969
 * exponent.
fukasawa e60969
 */
fukasawa e60969
static double
fukasawa e60969
png_pow10(int power)
fukasawa e60969
{
fukasawa e60969
   int recip = 0;
fukasawa e60969
   double d = 1;
fukasawa e60969
fukasawa e60969
   /* Handle negative exponent with a reciprocal at the end because
fukasawa e60969
    * 10 is exact whereas .1 is inexact in base 2
fukasawa e60969
    */
fukasawa e60969
   if (power < 0)
fukasawa e60969
   {
fukasawa e60969
      if (power < DBL_MIN_10_EXP) return 0;
fukasawa e60969
      recip = 1, power = -power;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   if (power > 0)
fukasawa e60969
   {
fukasawa e60969
      /* Decompose power bitwise. */
fukasawa e60969
      double mult = 10;
fukasawa e60969
      do
fukasawa e60969
      {
fukasawa e60969
         if (power & 1) d *= mult;
fukasawa e60969
         mult *= mult;
fukasawa e60969
         power >>= 1;
fukasawa e60969
      }
fukasawa e60969
      while (power > 0);
fukasawa e60969
fukasawa e60969
      if (recip != 0) d = 1/d;
fukasawa e60969
   }
fukasawa e60969
   /* else power is 0 and d is 1 */
fukasawa e60969
fukasawa e60969
   return d;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Function to format a floating point value in ASCII with a given
fukasawa e60969
 * precision.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
fukasawa e60969
    double fp, unsigned int precision)
fukasawa e60969
{
fukasawa e60969
   /* We use standard functions from math.h, but not printf because
fukasawa e60969
    * that would require stdio.  The caller must supply a buffer of
fukasawa e60969
    * sufficient size or we will png_error.  The tests on size and
fukasawa e60969
    * the space in ascii[] consumed are indicated below.
fukasawa e60969
    */
fukasawa e60969
   if (precision < 1)
fukasawa e60969
      precision = DBL_DIG;
fukasawa e60969
fukasawa e60969
   /* Enforce the limit of the implementation precision too. */
fukasawa e60969
   if (precision > DBL_DIG+1)
fukasawa e60969
      precision = DBL_DIG+1;
fukasawa e60969
fukasawa e60969
   /* Basic sanity checks */
fukasawa e60969
   if (size >= precision+5) /* See the requirements below. */
fukasawa e60969
   {
fukasawa e60969
      if (fp < 0)
fukasawa e60969
      {
fukasawa e60969
         fp = -fp;
fukasawa e60969
         *ascii++ = 45; /* '-'  PLUS 1 TOTAL 1 */
fukasawa e60969
         --size;
fukasawa e60969
      }
fukasawa e60969
fukasawa e60969
      if (fp >= DBL_MIN && fp <= DBL_MAX)
fukasawa e60969
      {
fukasawa e60969
         int exp_b10;   /* A base 10 exponent */
fukasawa e60969
         double base;   /* 10^exp_b10 */
fukasawa e60969
fukasawa e60969
         /* First extract a base 10 exponent of the number,
fukasawa e60969
          * the calculation below rounds down when converting
fukasawa e60969
          * from base 2 to base 10 (multiply by log10(2) -
fukasawa e60969
          * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
fukasawa e60969
          * be increased.  Note that the arithmetic shift
fukasawa e60969
          * performs a floor() unlike C arithmetic - using a
fukasawa e60969
          * C multiply would break the following for negative
fukasawa e60969
          * exponents.
fukasawa e60969
          */
fukasawa e60969
         (void)frexp(fp, &exp_b10); /* exponent to base 2 */
fukasawa e60969
fukasawa e60969
         exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
fukasawa e60969
fukasawa e60969
         /* Avoid underflow here. */
fukasawa e60969
         base = png_pow10(exp_b10); /* May underflow */
fukasawa e60969
fukasawa e60969
         while (base < DBL_MIN || base < fp)
fukasawa e60969
         {
fukasawa e60969
            /* And this may overflow. */
fukasawa e60969
            double test = png_pow10(exp_b10+1);
fukasawa e60969
fukasawa e60969
            if (test <= DBL_MAX)
fukasawa e60969
               ++exp_b10, base = test;
fukasawa e60969
fukasawa e60969
            else
fukasawa e60969
               break;
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         /* Normalize fp and correct exp_b10, after this fp is in the
fukasawa e60969
          * range [.1,1) and exp_b10 is both the exponent and the digit
fukasawa e60969
          * *before* which the decimal point should be inserted
fukasawa e60969
          * (starting with 0 for the first digit).  Note that this
fukasawa e60969
          * works even if 10^exp_b10 is out of range because of the
fukasawa e60969
          * test on DBL_MAX above.
fukasawa e60969
          */
fukasawa e60969
         fp /= base;
fukasawa e60969
         while (fp >= 1) fp /= 10, ++exp_b10;
fukasawa e60969
fukasawa e60969
         /* Because of the code above fp may, at this point, be
fukasawa e60969
          * less than .1, this is ok because the code below can
fukasawa e60969
          * handle the leading zeros this generates, so no attempt
fukasawa e60969
          * is made to correct that here.
fukasawa e60969
          */
fukasawa e60969
fukasawa e60969
         {
fukasawa e60969
            unsigned int czero, clead, cdigits;
fukasawa e60969
            char exponent[10];
fukasawa e60969
fukasawa e60969
            /* Allow up to two leading zeros - this will not lengthen
fukasawa e60969
             * the number compared to using E-n.
fukasawa e60969
             */
fukasawa e60969
            if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
fukasawa e60969
            {
fukasawa e60969
               czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */
fukasawa e60969
               exp_b10 = 0;      /* Dot added below before first output. */
fukasawa e60969
            }
fukasawa e60969
            else
fukasawa e60969
               czero = 0;    /* No zeros to add */
fukasawa e60969
fukasawa e60969
            /* Generate the digit list, stripping trailing zeros and
fukasawa e60969
             * inserting a '.' before a digit if the exponent is 0.
fukasawa e60969
             */
fukasawa e60969
            clead = czero; /* Count of leading zeros */
fukasawa e60969
            cdigits = 0;   /* Count of digits in list. */
fukasawa e60969
fukasawa e60969
            do
fukasawa e60969
            {
fukasawa e60969
               double d;
fukasawa e60969
fukasawa e60969
               fp *= 10;
fukasawa e60969
               /* Use modf here, not floor and subtract, so that
fukasawa e60969
                * the separation is done in one step.  At the end
fukasawa e60969
                * of the loop don't break the number into parts so
fukasawa e60969
                * that the final digit is rounded.
fukasawa e60969
                */
fukasawa e60969
               if (cdigits+czero+1 < precision+clead)
fukasawa e60969
                  fp = modf(fp, &d);
fukasawa e60969
fukasawa e60969
               else
fukasawa e60969
               {
fukasawa e60969
                  d = floor(fp + .5);
fukasawa e60969
fukasawa e60969
                  if (d > 9)
fukasawa e60969
                  {
fukasawa e60969
                     /* Rounding up to 10, handle that here. */
fukasawa e60969
                     if (czero > 0)
fukasawa e60969
                     {
fukasawa e60969
                        --czero, d = 1;
fukasawa e60969
                        if (cdigits == 0) --clead;
fukasawa e60969
                     }
fukasawa e60969
                     else
fukasawa e60969
                     {
fukasawa e60969
                        while (cdigits > 0 && d > 9)
fukasawa e60969
                        {
fukasawa e60969
                           int ch = *--ascii;
fukasawa e60969
fukasawa e60969
                           if (exp_b10 != (-1))
fukasawa e60969
                              ++exp_b10;
fukasawa e60969
fukasawa e60969
                           else if (ch == 46)
fukasawa e60969
                           {
fukasawa e60969
                              ch = *--ascii, ++size;
fukasawa e60969
                              /* Advance exp_b10 to '1', so that the
fukasawa e60969
                               * decimal point happens after the
fukasawa e60969
                               * previous digit.
fukasawa e60969
                               */
fukasawa e60969
                              exp_b10 = 1;
fukasawa e60969
                           }
fukasawa e60969
fukasawa e60969
                           --cdigits;
fukasawa e60969
                           d = ch - 47;  /* I.e. 1+(ch-48) */
fukasawa e60969
                        }
fukasawa e60969
fukasawa e60969
                        /* Did we reach the beginning? If so adjust the
fukasawa e60969
                         * exponent but take into account the leading
fukasawa e60969
                         * decimal point.
fukasawa e60969
                         */
fukasawa e60969
                        if (d > 9)  /* cdigits == 0 */
fukasawa e60969
                        {
fukasawa e60969
                           if (exp_b10 == (-1))
fukasawa e60969
                           {
fukasawa e60969
                              /* Leading decimal point (plus zeros?), if
fukasawa e60969
                               * we lose the decimal point here it must
fukasawa e60969
                               * be reentered below.
fukasawa e60969
                               */
fukasawa e60969
                              int ch = *--ascii;
fukasawa e60969
fukasawa e60969
                              if (ch == 46)
fukasawa e60969
                                 ++size, exp_b10 = 1;
fukasawa e60969
fukasawa e60969
                              /* Else lost a leading zero, so 'exp_b10' is
fukasawa e60969
                               * still ok at (-1)
fukasawa e60969
                               */
fukasawa e60969
                           }
fukasawa e60969
                           else
fukasawa e60969
                              ++exp_b10;
fukasawa e60969
fukasawa e60969
                           /* In all cases we output a '1' */
fukasawa e60969
                           d = 1;
fukasawa e60969
                        }
fukasawa e60969
                     }
fukasawa e60969
                  }
fukasawa e60969
                  fp = 0; /* Guarantees termination below. */
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               if (d == 0)
fukasawa e60969
               {
fukasawa e60969
                  ++czero;
fukasawa e60969
                  if (cdigits == 0) ++clead;
fukasawa e60969
               }
fukasawa e60969
               else
fukasawa e60969
               {
fukasawa e60969
                  /* Included embedded zeros in the digit count. */
fukasawa e60969
                  cdigits += czero - clead;
fukasawa e60969
                  clead = 0;
fukasawa e60969
fukasawa e60969
                  while (czero > 0)
fukasawa e60969
                  {
fukasawa e60969
                     /* exp_b10 == (-1) means we just output the decimal
fukasawa e60969
                      * place - after the DP don't adjust 'exp_b10' any
fukasawa e60969
                      * more!
fukasawa e60969
                      */
fukasawa e60969
                     if (exp_b10 != (-1))
fukasawa e60969
                     {
fukasawa e60969
                        if (exp_b10 == 0) *ascii++ = 46, --size;
fukasawa e60969
                        /* PLUS 1: TOTAL 4 */
fukasawa e60969
                        --exp_b10;
fukasawa e60969
                     }
fukasawa e60969
                     *ascii++ = 48, --czero;
fukasawa e60969
                  }
fukasawa e60969
fukasawa e60969
                  if (exp_b10 != (-1))
fukasawa e60969
                  {
fukasawa e60969
                     if (exp_b10 == 0)
fukasawa e60969
                        *ascii++ = 46, --size; /* counted above */
fukasawa e60969
fukasawa e60969
                     --exp_b10;
fukasawa e60969
                  }
fukasawa e60969
                  *ascii++ = (char)(48 + (int)d), ++cdigits;
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
            while (cdigits+czero < precision+clead && fp > DBL_MIN);
fukasawa e60969
fukasawa e60969
            /* The total output count (max) is now 4+precision */
fukasawa e60969
fukasawa e60969
            /* Check for an exponent, if we don't need one we are
fukasawa e60969
             * done and just need to terminate the string.  At
fukasawa e60969
             * this point exp_b10==(-1) is effectively if flag - it got
fukasawa e60969
             * to '-1' because of the decrement after outputting
fukasawa e60969
             * the decimal point above (the exponent required is
fukasawa e60969
             * *not* -1!)
fukasawa e60969
             */
fukasawa e60969
            if (exp_b10 >= (-1) && exp_b10 <= 2)
fukasawa e60969
            {
fukasawa e60969
               /* The following only happens if we didn't output the
fukasawa e60969
                * leading zeros above for negative exponent, so this
fukasawa e60969
                * doesn't add to the digit requirement.  Note that the
fukasawa e60969
                * two zeros here can only be output if the two leading
fukasawa e60969
                * zeros were *not* output, so this doesn't increase
fukasawa e60969
                * the output count.
fukasawa e60969
                */
fukasawa e60969
               while (--exp_b10 >= 0) *ascii++ = 48;
fukasawa e60969
fukasawa e60969
               *ascii = 0;
fukasawa e60969
fukasawa e60969
               /* Total buffer requirement (including the '\0') is
fukasawa e60969
                * 5+precision - see check at the start.
fukasawa e60969
                */
fukasawa e60969
               return;
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            /* Here if an exponent is required, adjust size for
fukasawa e60969
             * the digits we output but did not count.  The total
fukasawa e60969
             * digit output here so far is at most 1+precision - no
fukasawa e60969
             * decimal point and no leading or trailing zeros have
fukasawa e60969
             * been output.
fukasawa e60969
             */
fukasawa e60969
            size -= cdigits;
fukasawa e60969
fukasawa e60969
            *ascii++ = 69, --size;    /* 'E': PLUS 1 TOTAL 2+precision */
fukasawa e60969
fukasawa e60969
            /* The following use of an unsigned temporary avoids ambiguities in
fukasawa e60969
             * the signed arithmetic on exp_b10 and permits GCC at least to do
fukasawa e60969
             * better optimization.
fukasawa e60969
             */
fukasawa e60969
            {
fukasawa e60969
               unsigned int uexp_b10;
fukasawa e60969
fukasawa e60969
               if (exp_b10 < 0)
fukasawa e60969
               {
fukasawa e60969
                  *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
fukasawa e60969
                  uexp_b10 = -exp_b10;
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               else
fukasawa e60969
                  uexp_b10 = exp_b10;
fukasawa e60969
fukasawa e60969
               cdigits = 0;
fukasawa e60969
fukasawa e60969
               while (uexp_b10 > 0)
fukasawa e60969
               {
fukasawa e60969
                  exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
fukasawa e60969
                  uexp_b10 /= 10;
fukasawa e60969
               }
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            /* Need another size check here for the exponent digits, so
fukasawa e60969
             * this need not be considered above.
fukasawa e60969
             */
fukasawa e60969
            if (size > cdigits)
fukasawa e60969
            {
fukasawa e60969
               while (cdigits > 0) *ascii++ = exponent[--cdigits];
fukasawa e60969
fukasawa e60969
               *ascii = 0;
fukasawa e60969
fukasawa e60969
               return;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
      else if (!(fp >= DBL_MIN))
fukasawa e60969
      {
fukasawa e60969
         *ascii++ = 48; /* '0' */
fukasawa e60969
         *ascii = 0;
fukasawa e60969
         return;
fukasawa e60969
      }
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         *ascii++ = 105; /* 'i' */
fukasawa e60969
         *ascii++ = 110; /* 'n' */
fukasawa e60969
         *ascii++ = 102; /* 'f' */
fukasawa e60969
         *ascii = 0;
fukasawa e60969
         return;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Here on buffer too small. */
fukasawa e60969
   png_error(png_ptr, "ASCII conversion buffer too small");
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#  endif /* FLOATING_POINT */
fukasawa e60969
fukasawa e60969
#  ifdef PNG_FIXED_POINT_SUPPORTED
fukasawa e60969
/* Function to format a fixed point value in ASCII.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
fukasawa e60969
    png_size_t size, png_fixed_point fp)
fukasawa e60969
{
fukasawa e60969
   /* Require space for 10 decimal digits, a decimal point, a minus sign and a
fukasawa e60969
    * trailing \0, 13 characters:
fukasawa e60969
    */
fukasawa e60969
   if (size > 12)
fukasawa e60969
   {
fukasawa e60969
      png_uint_32 num;
fukasawa e60969
fukasawa e60969
      /* Avoid overflow here on the minimum integer. */
fukasawa e60969
      if (fp < 0)
fukasawa e60969
         *ascii++ = 45, num = -fp;
fukasawa e60969
      else
fukasawa e60969
         num = fp;
fukasawa e60969
fukasawa e60969
      if (num <= 0x80000000) /* else overflowed */
fukasawa e60969
      {
fukasawa e60969
         unsigned int ndigits = 0, first = 16 /* flag value */;
fukasawa e60969
         char digits[10];
fukasawa e60969
fukasawa e60969
         while (num)
fukasawa e60969
         {
fukasawa e60969
            /* Split the low digit off num: */
fukasawa e60969
            unsigned int tmp = num/10;
fukasawa e60969
            num -= tmp*10;
fukasawa e60969
            digits[ndigits++] = (char)(48 + num);
fukasawa e60969
            /* Record the first non-zero digit, note that this is a number
fukasawa e60969
             * starting at 1, it's not actually the array index.
fukasawa e60969
             */
fukasawa e60969
            if (first == 16 && num > 0)
fukasawa e60969
               first = ndigits;
fukasawa e60969
            num = tmp;
fukasawa e60969
         }
fukasawa e60969
fukasawa e60969
         if (ndigits > 0)
fukasawa e60969
         {
fukasawa e60969
            while (ndigits > 5) *ascii++ = digits[--ndigits];
fukasawa e60969
            /* The remaining digits are fractional digits, ndigits is '5' or
fukasawa e60969
             * smaller at this point.  It is certainly not zero.  Check for a
fukasawa e60969
             * non-zero fractional digit:
fukasawa e60969
             */
fukasawa e60969
            if (first <= 5)
fukasawa e60969
            {
fukasawa e60969
               unsigned int i;
fukasawa e60969
               *ascii++ = 46; /* decimal point */
fukasawa e60969
               /* ndigits may be <5 for small numbers, output leading zeros
fukasawa e60969
                * then ndigits digits to first:
fukasawa e60969
                */
fukasawa e60969
               i = 5;
fukasawa e60969
               while (ndigits < i) *ascii++ = 48, --i;
fukasawa e60969
               while (ndigits >= first) *ascii++ = digits[--ndigits];
fukasawa e60969
               /* Don't output the trailing zeros! */
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
         else
fukasawa e60969
            *ascii++ = 48;
fukasawa e60969
fukasawa e60969
         /* And null terminate the string: */
fukasawa e60969
         *ascii = 0;
fukasawa e60969
         return;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Here on buffer too small. */
fukasawa e60969
   png_error(png_ptr, "ASCII conversion buffer too small");
fukasawa e60969
}
fukasawa e60969
#   endif /* FIXED_POINT */
fukasawa e60969
#endif /* SCAL */
fukasawa e60969
fukasawa e60969
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
fukasawa e60969
   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
fukasawa e60969
   (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
fukasawa e60969
   defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
fukasawa e60969
   (defined(PNG_sCAL_SUPPORTED) && \
fukasawa e60969
   defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
fukasawa e60969
png_fixed_point
fukasawa e60969
png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
fukasawa e60969
{
fukasawa e60969
   double r = floor(100000 * fp + .5);
fukasawa e60969
fukasawa e60969
   if (r > 2147483647. || r < -2147483648.)
fukasawa e60969
      png_fixed_error(png_ptr, text);
fukasawa e60969
fukasawa e60969
#  ifndef PNG_ERROR_TEXT_SUPPORTED
fukasawa e60969
   PNG_UNUSED(text)
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   return (png_fixed_point)r;
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
fukasawa e60969
    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
fukasawa e60969
/* muldiv functions */
fukasawa e60969
/* This API takes signed arguments and rounds the result to the nearest
fukasawa e60969
 * integer (or, for a fixed point number - the standard argument - to
fukasawa e60969
 * the nearest .00001).  Overflow and divide by zero are signalled in
fukasawa e60969
 * the result, a boolean - true on success, false on overflow.
fukasawa e60969
 */
fukasawa e60969
int
fukasawa e60969
png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
fukasawa e60969
    png_int_32 divisor)
fukasawa e60969
{
fukasawa e60969
   /* Return a * times / divisor, rounded. */
fukasawa e60969
   if (divisor != 0)
fukasawa e60969
   {
fukasawa e60969
      if (a == 0 || times == 0)
fukasawa e60969
      {
fukasawa e60969
         *res = 0;
fukasawa e60969
         return 1;
fukasawa e60969
      }
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
         double r = a;
fukasawa e60969
         r *= times;
fukasawa e60969
         r /= divisor;
fukasawa e60969
         r = floor(r+.5);
fukasawa e60969
fukasawa e60969
         /* A png_fixed_point is a 32-bit integer. */
fukasawa e60969
         if (r <= 2147483647. && r >= -2147483648.)
fukasawa e60969
         {
fukasawa e60969
            *res = (png_fixed_point)r;
fukasawa e60969
            return 1;
fukasawa e60969
         }
fukasawa e60969
#else
fukasawa e60969
         int negative = 0;
fukasawa e60969
         png_uint_32 A, T, D;
fukasawa e60969
         png_uint_32 s16, s32, s00;
fukasawa e60969
fukasawa e60969
         if (a < 0)
fukasawa e60969
            negative = 1, A = -a;
fukasawa e60969
         else
fukasawa e60969
            A = a;
fukasawa e60969
fukasawa e60969
         if (times < 0)
fukasawa e60969
            negative = !negative, T = -times;
fukasawa e60969
         else
fukasawa e60969
            T = times;
fukasawa e60969
fukasawa e60969
         if (divisor < 0)
fukasawa e60969
            negative = !negative, D = -divisor;
fukasawa e60969
         else
fukasawa e60969
            D = divisor;
fukasawa e60969
fukasawa e60969
         /* Following can't overflow because the arguments only
fukasawa e60969
          * have 31 bits each, however the result may be 32 bits.
fukasawa e60969
          */
fukasawa e60969
         s16 = (A >> 16) * (T & 0xffff) +
fukasawa e60969
                           (A & 0xffff) * (T >> 16);
fukasawa e60969
         /* Can't overflow because the a*times bit is only 30
fukasawa e60969
          * bits at most.
fukasawa e60969
          */
fukasawa e60969
         s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
fukasawa e60969
         s00 = (A & 0xffff) * (T & 0xffff);
fukasawa e60969
fukasawa e60969
         s16 = (s16 & 0xffff) << 16;
fukasawa e60969
         s00 += s16;
fukasawa e60969
fukasawa e60969
         if (s00 < s16)
fukasawa e60969
            ++s32; /* carry */
fukasawa e60969
fukasawa e60969
         if (s32 < D) /* else overflow */
fukasawa e60969
         {
fukasawa e60969
            /* s32.s00 is now the 64-bit product, do a standard
fukasawa e60969
             * division, we know that s32 < D, so the maximum
fukasawa e60969
             * required shift is 31.
fukasawa e60969
             */
fukasawa e60969
            int bitshift = 32;
fukasawa e60969
            png_fixed_point result = 0; /* NOTE: signed */
fukasawa e60969
fukasawa e60969
            while (--bitshift >= 0)
fukasawa e60969
            {
fukasawa e60969
               png_uint_32 d32, d00;
fukasawa e60969
fukasawa e60969
               if (bitshift > 0)
fukasawa e60969
                  d32 = D >> (32-bitshift), d00 = D << bitshift;
fukasawa e60969
fukasawa e60969
               else
fukasawa e60969
                  d32 = 0, d00 = D;
fukasawa e60969
fukasawa e60969
               if (s32 > d32)
fukasawa e60969
               {
fukasawa e60969
                  if (s00 < d00) --s32; /* carry */
fukasawa e60969
                  s32 -= d32, s00 -= d00, result += 1<
fukasawa e60969
               }
fukasawa e60969
fukasawa e60969
               else
fukasawa e60969
                  if (s32 == d32 && s00 >= d00)
fukasawa e60969
                     s32 = 0, s00 -= d00, result += 1<
fukasawa e60969
            }
fukasawa e60969
fukasawa e60969
            /* Handle the rounding. */
fukasawa e60969
            if (s00 >= (D >> 1))
fukasawa e60969
               ++result;
fukasawa e60969
fukasawa e60969
            if (negative != 0)
fukasawa e60969
               result = -result;
fukasawa e60969
fukasawa e60969
            /* Check for overflow. */
fukasawa e60969
            if ((negative != 0 && result <= 0) ||
fukasawa e60969
                (negative == 0 && result >= 0))
fukasawa e60969
            {
fukasawa e60969
               *res = result;
fukasawa e60969
               return 1;
fukasawa e60969
            }
fukasawa e60969
         }
fukasawa e60969
#endif
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
#endif /* READ_GAMMA || INCH_CONVERSIONS */
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
fukasawa e60969
/* The following is for when the caller doesn't much care about the
fukasawa e60969
 * result.
fukasawa e60969
 */
fukasawa e60969
png_fixed_point
fukasawa e60969
png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
fukasawa e60969
    png_int_32 divisor)
fukasawa e60969
{
fukasawa e60969
   png_fixed_point result;
fukasawa e60969
fukasawa e60969
   if (png_muldiv(&result, a, times, divisor) != 0)
fukasawa e60969
      return result;
fukasawa e60969
fukasawa e60969
   png_warning(png_ptr, "fixed point overflow ignored");
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
fukasawa e60969
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
fukasawa e60969
png_fixed_point
fukasawa e60969
png_reciprocal(png_fixed_point a)
fukasawa e60969
{
fukasawa e60969
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
   double r = floor(1E10/a+.5);
fukasawa e60969
fukasawa e60969
   if (r <= 2147483647. && r >= -2147483648.)
fukasawa e60969
      return (png_fixed_point)r;
fukasawa e60969
#else
fukasawa e60969
   png_fixed_point res;
fukasawa e60969
fukasawa e60969
   if (png_muldiv(&res, 100000, 100000, a) != 0)
fukasawa e60969
      return res;
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   return 0; /* error/overflow */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* This is the shared test on whether a gamma value is 'significant' - whether
fukasawa e60969
 * it is worth doing gamma correction.
fukasawa e60969
 */
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_gamma_significant(png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
fukasawa e60969
       gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
#ifdef PNG_READ_GAMMA_SUPPORTED
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
/* A local convenience routine. */
fukasawa e60969
static png_fixed_point
fukasawa e60969
png_product2(png_fixed_point a, png_fixed_point b)
fukasawa e60969
{
fukasawa e60969
   /* The required result is 1/a * 1/b; the following preserves accuracy. */
fukasawa e60969
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
   double r = a * 1E-5;
fukasawa e60969
   r *= b;
fukasawa e60969
   r = floor(r+.5);
fukasawa e60969
fukasawa e60969
   if (r <= 2147483647. && r >= -2147483648.)
fukasawa e60969
      return (png_fixed_point)r;
fukasawa e60969
#else
fukasawa e60969
   png_fixed_point res;
fukasawa e60969
fukasawa e60969
   if (png_muldiv(&res, a, b, 100000) != 0)
fukasawa e60969
      return res;
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   return 0; /* overflow */
fukasawa e60969
}
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
fukasawa e60969
/* The inverse of the above. */
fukasawa e60969
png_fixed_point
fukasawa e60969
png_reciprocal2(png_fixed_point a, png_fixed_point b)
fukasawa e60969
{
fukasawa e60969
   /* The required result is 1/a * 1/b; the following preserves accuracy. */
fukasawa e60969
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
   if (a != 0 && b != 0)
fukasawa e60969
   {
fukasawa e60969
      double r = 1E15/a;
fukasawa e60969
      r /= b;
fukasawa e60969
      r = floor(r+.5);
fukasawa e60969
fukasawa e60969
      if (r <= 2147483647. && r >= -2147483648.)
fukasawa e60969
         return (png_fixed_point)r;
fukasawa e60969
   }
fukasawa e60969
#else
fukasawa e60969
   /* This may overflow because the range of png_fixed_point isn't symmetric,
fukasawa e60969
    * but this API is only used for the product of file and screen gamma so it
fukasawa e60969
    * doesn't matter that the smallest number it can produce is 1/21474, not
fukasawa e60969
    * 1/100000
fukasawa e60969
    */
fukasawa e60969
   png_fixed_point res = png_product2(a, b);
fukasawa e60969
fukasawa e60969
   if (res != 0)
fukasawa e60969
      return png_reciprocal(res);
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
   return 0; /* overflow */
fukasawa e60969
}
fukasawa e60969
#endif /* READ_GAMMA */
fukasawa e60969
fukasawa e60969
#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
fukasawa e60969
#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
/* Fixed point gamma.
fukasawa e60969
 *
fukasawa e60969
 * The code to calculate the tables used below can be found in the shell script
fukasawa e60969
 * contrib/tools/intgamma.sh
fukasawa e60969
 *
fukasawa e60969
 * To calculate gamma this code implements fast log() and exp() calls using only
fukasawa e60969
 * fixed point arithmetic.  This code has sufficient precision for either 8-bit
fukasawa e60969
 * or 16-bit sample values.
fukasawa e60969
 *
fukasawa e60969
 * The tables used here were calculated using simple 'bc' programs, but C double
fukasawa e60969
 * precision floating point arithmetic would work fine.
fukasawa e60969
 *
fukasawa e60969
 * 8-bit log table
fukasawa e60969
 *   This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
fukasawa e60969
 *   255, so it's the base 2 logarithm of a normalized 8-bit floating point
fukasawa e60969
 *   mantissa.  The numbers are 32-bit fractions.
fukasawa e60969
 */
fukasawa e60969
static const png_uint_32
fukasawa e60969
png_8bit_l2[128] =
fukasawa e60969
{
fukasawa e60969
   4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
fukasawa e60969
   3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
fukasawa e60969
   3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
fukasawa e60969
   3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
fukasawa e60969
   3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
fukasawa e60969
   2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
fukasawa e60969
   2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
fukasawa e60969
   2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
fukasawa e60969
   2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
fukasawa e60969
   2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
fukasawa e60969
   1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
fukasawa e60969
   1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
fukasawa e60969
   1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
fukasawa e60969
   1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
fukasawa e60969
   1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
fukasawa e60969
   971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
fukasawa e60969
   803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
fukasawa e60969
   639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
fukasawa e60969
   479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
fukasawa e60969
   324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
fukasawa e60969
   172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
fukasawa e60969
   24347096U, 0U
fukasawa e60969
fukasawa e60969
#if 0
fukasawa e60969
   /* The following are the values for 16-bit tables - these work fine for the
fukasawa e60969
    * 8-bit conversions but produce very slightly larger errors in the 16-bit
fukasawa e60969
    * log (about 1.2 as opposed to 0.7 absolute error in the final value).  To
fukasawa e60969
    * use these all the shifts below must be adjusted appropriately.
fukasawa e60969
    */
fukasawa e60969
   65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
fukasawa e60969
   57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
fukasawa e60969
   50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
fukasawa e60969
   43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
fukasawa e60969
   37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
fukasawa e60969
   31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
fukasawa e60969
   25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
fukasawa e60969
   20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
fukasawa e60969
   15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
fukasawa e60969
   10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
fukasawa e60969
   6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
fukasawa e60969
   1119, 744, 372
fukasawa e60969
#endif
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
static png_int_32
fukasawa e60969
png_log8bit(unsigned int x)
fukasawa e60969
{
fukasawa e60969
   unsigned int lg2 = 0;
fukasawa e60969
   /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
fukasawa e60969
    * because the log is actually negate that means adding 1.  The final
fukasawa e60969
    * returned value thus has the range 0 (for 255 input) to 7.994 (for 1
fukasawa e60969
    * input), return -1 for the overflow (log 0) case, - so the result is
fukasawa e60969
    * always at most 19 bits.
fukasawa e60969
    */
fukasawa e60969
   if ((x &= 0xff) == 0)
fukasawa e60969
      return -1;
fukasawa e60969
fukasawa e60969
   if ((x & 0xf0) == 0)
fukasawa e60969
      lg2  = 4, x <<= 4;
fukasawa e60969
fukasawa e60969
   if ((x & 0xc0) == 0)
fukasawa e60969
      lg2 += 2, x <<= 2;
fukasawa e60969
fukasawa e60969
   if ((x & 0x80) == 0)
fukasawa e60969
      lg2 += 1, x <<= 1;
fukasawa e60969
fukasawa e60969
   /* result is at most 19 bits, so this cast is safe: */
fukasawa e60969
   return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
fukasawa e60969
 * for 16-bit images we use the most significant 8 bits of the 16-bit value to
fukasawa e60969
 * get an approximation then multiply the approximation by a correction factor
fukasawa e60969
 * determined by the remaining up to 8 bits.  This requires an additional step
fukasawa e60969
 * in the 16-bit case.
fukasawa e60969
 *
fukasawa e60969
 * We want log2(value/65535), we have log2(v'/255), where:
fukasawa e60969
 *
fukasawa e60969
 *    value = v' * 256 + v''
fukasawa e60969
 *          = v' * f
fukasawa e60969
 *
fukasawa e60969
 * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
fukasawa e60969
 * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
fukasawa e60969
 * than 258.  The final factor also needs to correct for the fact that our 8-bit
fukasawa e60969
 * value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
fukasawa e60969
 *
fukasawa e60969
 * This gives a final formula using a calculated value 'x' which is value/v' and
fukasawa e60969
 * scaling by 65536 to match the above table:
fukasawa e60969
 *
fukasawa e60969
 *   log2(x/257) * 65536
fukasawa e60969
 *
fukasawa e60969
 * Since these numbers are so close to '1' we can use simple linear
fukasawa e60969
 * interpolation between the two end values 256/257 (result -368.61) and 258/257
fukasawa e60969
 * (result 367.179).  The values used below are scaled by a further 64 to give
fukasawa e60969
 * 16-bit precision in the interpolation:
fukasawa e60969
 *
fukasawa e60969
 * Start (256): -23591
fukasawa e60969
 * Zero  (257):      0
fukasawa e60969
 * End   (258):  23499
fukasawa e60969
 */
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
static png_int_32
fukasawa e60969
png_log16bit(png_uint_32 x)
fukasawa e60969
{
fukasawa e60969
   unsigned int lg2 = 0;
fukasawa e60969
fukasawa e60969
   /* As above, but now the input has 16 bits. */
fukasawa e60969
   if ((x &= 0xffff) == 0)
fukasawa e60969
      return -1;
fukasawa e60969
fukasawa e60969
   if ((x & 0xff00) == 0)
fukasawa e60969
      lg2  = 8, x <<= 8;
fukasawa e60969
fukasawa e60969
   if ((x & 0xf000) == 0)
fukasawa e60969
      lg2 += 4, x <<= 4;
fukasawa e60969
fukasawa e60969
   if ((x & 0xc000) == 0)
fukasawa e60969
      lg2 += 2, x <<= 2;
fukasawa e60969
fukasawa e60969
   if ((x & 0x8000) == 0)
fukasawa e60969
      lg2 += 1, x <<= 1;
fukasawa e60969
fukasawa e60969
   /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
fukasawa e60969
    * value.
fukasawa e60969
    */
fukasawa e60969
   lg2 <<= 28;
fukasawa e60969
   lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
fukasawa e60969
fukasawa e60969
   /* Now we need to interpolate the factor, this requires a division by the top
fukasawa e60969
    * 8 bits.  Do this with maximum precision.
fukasawa e60969
    */
fukasawa e60969
   x = ((x << 16) + (x >> 9)) / (x >> 8);
fukasawa e60969
fukasawa e60969
   /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
fukasawa e60969
    * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
fukasawa e60969
    * 16 bits to interpolate to get the low bits of the result.  Round the
fukasawa e60969
    * answer.  Note that the end point values are scaled by 64 to retain overall
fukasawa e60969
    * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
fukasawa e60969
    * the overall scaling by 6-12.  Round at every step.
fukasawa e60969
    */
fukasawa e60969
   x -= 1U << 24;
fukasawa e60969
fukasawa e60969
   if (x <= 65536U) /* <= '257' */
fukasawa e60969
      lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
fukasawa e60969
fukasawa e60969
   /* Safe, because the result can't have more than 20 bits: */
fukasawa e60969
   return (png_int_32)((lg2 + 2048) >> 12);
fukasawa e60969
}
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
fukasawa e60969
/* The 'exp()' case must invert the above, taking a 20-bit fixed point
fukasawa e60969
 * logarithmic value and returning a 16 or 8-bit number as appropriate.  In
fukasawa e60969
 * each case only the low 16 bits are relevant - the fraction - since the
fukasawa e60969
 * integer bits (the top 4) simply determine a shift.
fukasawa e60969
 *
fukasawa e60969
 * The worst case is the 16-bit distinction between 65535 and 65534. This
fukasawa e60969
 * requires perhaps spurious accuracy in the decoding of the logarithm to
fukasawa e60969
 * distinguish log2(65535/65534.5) - 10^-5 or 17 bits.  There is little chance
fukasawa e60969
 * of getting this accuracy in practice.
fukasawa e60969
 *
fukasawa e60969
 * To deal with this the following exp() function works out the exponent of the
fukasawa e60969
 * frational part of the logarithm by using an accurate 32-bit value from the
fukasawa e60969
 * top four fractional bits then multiplying in the remaining bits.
fukasawa e60969
 */
fukasawa e60969
static const png_uint_32
fukasawa e60969
png_32bit_exp[16] =
fukasawa e60969
{
fukasawa e60969
   /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
fukasawa e60969
   4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
fukasawa e60969
   3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
fukasawa e60969
   2553802834U, 2445529972U, 2341847524U, 2242560872U
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
/* Adjustment table; provided to explain the numbers in the code below. */
fukasawa e60969
#if 0
fukasawa e60969
for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
fukasawa e60969
   11 44937.64284865548751208448
fukasawa e60969
   10 45180.98734845585101160448
fukasawa e60969
    9 45303.31936980687359311872
fukasawa e60969
    8 45364.65110595323018870784
fukasawa e60969
    7 45395.35850361789624614912
fukasawa e60969
    6 45410.72259715102037508096
fukasawa e60969
    5 45418.40724413220722311168
fukasawa e60969
    4 45422.25021786898173001728
fukasawa e60969
    3 45424.17186732298419044352
fukasawa e60969
    2 45425.13273269940811464704
fukasawa e60969
    1 45425.61317555035558641664
fukasawa e60969
    0 45425.85339951654943850496
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
static png_uint_32
fukasawa e60969
png_exp(png_fixed_point x)
fukasawa e60969
{
fukasawa e60969
   if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
fukasawa e60969
   {
fukasawa e60969
      /* Obtain a 4-bit approximation */
fukasawa e60969
      png_uint_32 e = png_32bit_exp[(x >> 12) & 0x0f];
fukasawa e60969
fukasawa e60969
      /* Incorporate the low 12 bits - these decrease the returned value by
fukasawa e60969
       * multiplying by a number less than 1 if the bit is set.  The multiplier
fukasawa e60969
       * is determined by the above table and the shift. Notice that the values
fukasawa e60969
       * converge on 45426 and this is used to allow linear interpolation of the
fukasawa e60969
       * low bits.
fukasawa e60969
       */
fukasawa e60969
      if (x & 0x800)
fukasawa e60969
         e -= (((e >> 16) * 44938U) +  16U) >> 5;
fukasawa e60969
fukasawa e60969
      if (x & 0x400)
fukasawa e60969
         e -= (((e >> 16) * 45181U) +  32U) >> 6;
fukasawa e60969
fukasawa e60969
      if (x & 0x200)
fukasawa e60969
         e -= (((e >> 16) * 45303U) +  64U) >> 7;
fukasawa e60969
fukasawa e60969
      if (x & 0x100)
fukasawa e60969
         e -= (((e >> 16) * 45365U) + 128U) >> 8;
fukasawa e60969
fukasawa e60969
      if (x & 0x080)
fukasawa e60969
         e -= (((e >> 16) * 45395U) + 256U) >> 9;
fukasawa e60969
fukasawa e60969
      if (x & 0x040)
fukasawa e60969
         e -= (((e >> 16) * 45410U) + 512U) >> 10;
fukasawa e60969
fukasawa e60969
      /* And handle the low 6 bits in a single block. */
fukasawa e60969
      e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
fukasawa e60969
fukasawa e60969
      /* Handle the upper bits of x. */
fukasawa e60969
      e >>= x >> 16;
fukasawa e60969
      return e;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Check for overflow */
fukasawa e60969
   if (x <= 0)
fukasawa e60969
      return png_32bit_exp[0];
fukasawa e60969
fukasawa e60969
   /* Else underflow */
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
static png_byte
fukasawa e60969
png_exp8bit(png_fixed_point lg2)
fukasawa e60969
{
fukasawa e60969
   /* Get a 32-bit value: */
fukasawa e60969
   png_uint_32 x = png_exp(lg2);
fukasawa e60969
fukasawa e60969
   /* Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the
fukasawa e60969
    * second, rounding, step can't overflow because of the first, subtraction,
fukasawa e60969
    * step.
fukasawa e60969
    */
fukasawa e60969
   x -= x >> 8;
fukasawa e60969
   return (png_byte)(((x + 0x7fffffU) >> 24) & 0xff);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
static png_uint_16
fukasawa e60969
png_exp16bit(png_fixed_point lg2)
fukasawa e60969
{
fukasawa e60969
   /* Get a 32-bit value: */
fukasawa e60969
   png_uint_32 x = png_exp(lg2);
fukasawa e60969
fukasawa e60969
   /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
fukasawa e60969
   x -= x >> 16;
fukasawa e60969
   return (png_uint_16)((x + 32767U) >> 16);
fukasawa e60969
}
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
#endif /* FLOATING_ARITHMETIC */
fukasawa e60969
fukasawa e60969
png_byte
fukasawa e60969
png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   if (value > 0 && value < 255)
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
         /* 'value' is unsigned, ANSI-C90 requires the compiler to correctly
fukasawa e60969
          * convert this to a floating point value.  This includes values that
fukasawa e60969
          * would overflow if 'value' were to be converted to 'int'.
fukasawa e60969
          *
fukasawa e60969
          * Apparently GCC, however, does an intermediate conversion to (int)
fukasawa e60969
          * on some (ARM) but not all (x86) platforms, possibly because of
fukasawa e60969
          * hardware FP limitations.  (E.g. if the hardware conversion always
fukasawa e60969
          * assumes the integer register contains a signed value.)  This results
fukasawa e60969
          * in ANSI-C undefined behavior for large values.
fukasawa e60969
          *
fukasawa e60969
          * Other implementations on the same machine might actually be ANSI-C90
fukasawa e60969
          * conformant and therefore compile spurious extra code for the large
fukasawa e60969
          * values.
fukasawa e60969
          *
fukasawa e60969
          * We can be reasonably sure that an unsigned to float conversion
fukasawa e60969
          * won't be faster than an int to float one.  Therefore this code
fukasawa e60969
          * assumes responsibility for the undefined behavior, which it knows
fukasawa e60969
          * can't happen because of the check above.
fukasawa e60969
          *
fukasawa e60969
          * Note the argument to this routine is an (unsigned int) because, on
fukasawa e60969
          * 16-bit platforms, it is assigned a value which might be out of
fukasawa e60969
          * range for an (int); that would result in undefined behavior in the
fukasawa e60969
          * caller if the *argument* ('value') were to be declared (int).
fukasawa e60969
          */
fukasawa e60969
         double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5);
fukasawa e60969
         return (png_byte)r;
fukasawa e60969
#     else
fukasawa e60969
         png_int_32 lg2 = png_log8bit(value);
fukasawa e60969
         png_fixed_point res;
fukasawa e60969
fukasawa e60969
         if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
fukasawa e60969
            return png_exp8bit(res);
fukasawa e60969
fukasawa e60969
         /* Overflow. */
fukasawa e60969
         value = 0;
fukasawa e60969
#     endif
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return (png_byte)(value & 0xff);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
png_uint_16
fukasawa e60969
png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   if (value > 0 && value < 65535)
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
         /* The same (unsigned int)->(double) constraints apply here as above,
fukasawa e60969
          * however in this case the (unsigned int) to (int) conversion can
fukasawa e60969
          * overflow on an ANSI-C90 compliant system so the cast needs to ensure
fukasawa e60969
          * that this is not possible.
fukasawa e60969
          */
fukasawa e60969
         double r = floor(65535*pow((png_int_32)value/65535.,
fukasawa e60969
                     gamma_val*.00001)+.5);
fukasawa e60969
         return (png_uint_16)r;
fukasawa e60969
#     else
fukasawa e60969
         png_int_32 lg2 = png_log16bit(value);
fukasawa e60969
         png_fixed_point res;
fukasawa e60969
fukasawa e60969
         if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
fukasawa e60969
            return png_exp16bit(res);
fukasawa e60969
fukasawa e60969
         /* Overflow. */
fukasawa e60969
         value = 0;
fukasawa e60969
#     endif
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return (png_uint_16)value;
fukasawa e60969
}
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
fukasawa e60969
/* This does the right thing based on the bit_depth field of the
fukasawa e60969
 * png_struct, interpreting values as 8-bit or 16-bit.  While the result
fukasawa e60969
 * is nominally a 16-bit value if bit depth is 8 then the result is
fukasawa e60969
 * 8-bit (as are the arguments.)
fukasawa e60969
 */
fukasawa e60969
png_uint_16 /* PRIVATE */
fukasawa e60969
png_gamma_correct(png_structrp png_ptr, unsigned int value,
fukasawa e60969
    png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   if (png_ptr->bit_depth == 8)
fukasawa e60969
      return png_gamma_8bit_correct(value, gamma_val);
fukasawa e60969
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
   else
fukasawa e60969
      return png_gamma_16bit_correct(value, gamma_val);
fukasawa e60969
#else
fukasawa e60969
      /* should not reach this */
fukasawa e60969
      return 0;
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
/* Internal function to build a single 16-bit table - the table consists of
fukasawa e60969
 * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
fukasawa e60969
 * to shift the input values right (or 16-number_of_signifiant_bits).
fukasawa e60969
 *
fukasawa e60969
 * The caller is responsible for ensuring that the table gets cleaned up on
fukasawa e60969
 * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
fukasawa e60969
 * should be somewhere that will be cleaned.
fukasawa e60969
 */
fukasawa e60969
static void
fukasawa e60969
png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
fukasawa e60969
   PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   /* Various values derived from 'shift': */
fukasawa e60969
   PNG_CONST unsigned int num = 1U << (8U - shift);
fukasawa e60969
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
   /* CSE the division and work round wacky GCC warnings (see the comments
fukasawa e60969
    * in png_gamma_8bit_correct for where these come from.)
fukasawa e60969
    */
fukasawa e60969
   PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
fukasawa e60969
#endif
fukasawa e60969
   PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
fukasawa e60969
   PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
fukasawa e60969
   unsigned int i;
fukasawa e60969
fukasawa e60969
   png_uint_16pp table = *ptable =
fukasawa e60969
       (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
fukasawa e60969
fukasawa e60969
   for (i = 0; i < num; i++)
fukasawa e60969
   {
fukasawa e60969
      png_uint_16p sub_table = table[i] =
fukasawa e60969
          (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16)));
fukasawa e60969
fukasawa e60969
      /* The 'threshold' test is repeated here because it can arise for one of
fukasawa e60969
       * the 16-bit tables even if the others don't hit it.
fukasawa e60969
       */
fukasawa e60969
      if (png_gamma_significant(gamma_val) != 0)
fukasawa e60969
      {
fukasawa e60969
         /* The old code would overflow at the end and this would cause the
fukasawa e60969
          * 'pow' function to return a result >1, resulting in an
fukasawa e60969
          * arithmetic error.  This code follows the spec exactly; ig is
fukasawa e60969
          * the recovered input sample, it always has 8-16 bits.
fukasawa e60969
          *
fukasawa e60969
          * We want input * 65535/max, rounded, the arithmetic fits in 32
fukasawa e60969
          * bits (unsigned) so long as max <= 32767.
fukasawa e60969
          */
fukasawa e60969
         unsigned int j;
fukasawa e60969
         for (j = 0; j < 256; j++)
fukasawa e60969
         {
fukasawa e60969
            png_uint_32 ig = (j << (8-shift)) + i;
fukasawa e60969
#           ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
fukasawa e60969
               /* Inline the 'max' scaling operation: */
fukasawa e60969
               /* See png_gamma_8bit_correct for why the cast to (int) is
fukasawa e60969
                * required here.
fukasawa e60969
                */
fukasawa e60969
               double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5);
fukasawa e60969
               sub_table[j] = (png_uint_16)d;
fukasawa e60969
#           else
fukasawa e60969
               if (shift != 0)
fukasawa e60969
                  ig = (ig * 65535U + max_by_2)/max;
fukasawa e60969
fukasawa e60969
               sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
fukasawa e60969
#           endif
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
      else
fukasawa e60969
      {
fukasawa e60969
         /* We must still build a table, but do it the fast way. */
fukasawa e60969
         unsigned int j;
fukasawa e60969
fukasawa e60969
         for (j = 0; j < 256; j++)
fukasawa e60969
         {
fukasawa e60969
            png_uint_32 ig = (j << (8-shift)) + i;
fukasawa e60969
fukasawa e60969
            if (shift != 0)
fukasawa e60969
               ig = (ig * 65535U + max_by_2)/max;
fukasawa e60969
fukasawa e60969
            sub_table[j] = (png_uint_16)ig;
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* NOTE: this function expects the *inverse* of the overall gamma transformation
fukasawa e60969
 * required.
fukasawa e60969
 */
fukasawa e60969
static void
fukasawa e60969
png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
fukasawa e60969
   PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   PNG_CONST unsigned int num = 1U << (8U - shift);
fukasawa e60969
   PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
fukasawa e60969
   unsigned int i;
fukasawa e60969
   png_uint_32 last;
fukasawa e60969
fukasawa e60969
   png_uint_16pp table = *ptable =
fukasawa e60969
       (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
fukasawa e60969
fukasawa e60969
   /* 'num' is the number of tables and also the number of low bits of low
fukasawa e60969
    * bits of the input 16-bit value used to select a table.  Each table is
fukasawa e60969
    * itself indexed by the high 8 bits of the value.
fukasawa e60969
    */
fukasawa e60969
   for (i = 0; i < num; i++)
fukasawa e60969
      table[i] = (png_uint_16p)png_malloc(png_ptr,
fukasawa e60969
          256 * (sizeof (png_uint_16)));
fukasawa e60969
fukasawa e60969
   /* 'gamma_val' is set to the reciprocal of the value calculated above, so
fukasawa e60969
    * pow(out,g) is an *input* value.  'last' is the last input value set.
fukasawa e60969
    *
fukasawa e60969
    * In the loop 'i' is used to find output values.  Since the output is
fukasawa e60969
    * 8-bit there are only 256 possible values.  The tables are set up to
fukasawa e60969
    * select the closest possible output value for each input by finding
fukasawa e60969
    * the input value at the boundary between each pair of output values
fukasawa e60969
    * and filling the table up to that boundary with the lower output
fukasawa e60969
    * value.
fukasawa e60969
    *
fukasawa e60969
    * The boundary values are 0.5,1.5..253.5,254.5.  Since these are 9-bit
fukasawa e60969
    * values the code below uses a 16-bit value in i; the values start at
fukasawa e60969
    * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
fukasawa e60969
    * entries are filled with 255).  Start i at 128 and fill all 'last'
fukasawa e60969
    * table entries <= 'max'
fukasawa e60969
    */
fukasawa e60969
   last = 0;
fukasawa e60969
   for (i = 0; i < 255; ++i) /* 8-bit output value */
fukasawa e60969
   {
fukasawa e60969
      /* Find the corresponding maximum input value */
fukasawa e60969
      png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */
fukasawa e60969
fukasawa e60969
      /* Find the boundary value in 16 bits: */
fukasawa e60969
      png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
fukasawa e60969
fukasawa e60969
      /* Adjust (round) to (16-shift) bits: */
fukasawa e60969
      bound = (bound * max + 32768U)/65535U + 1U;
fukasawa e60969
fukasawa e60969
      while (last < bound)
fukasawa e60969
      {
fukasawa e60969
         table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
fukasawa e60969
         last++;
fukasawa e60969
      }
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* And fill in the final entries. */
fukasawa e60969
   while (last < (num << 8))
fukasawa e60969
   {
fukasawa e60969
      table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
fukasawa e60969
      last++;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
fukasawa e60969
/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
fukasawa e60969
 * typically much faster).  Note that libpng currently does no sBIT processing
fukasawa e60969
 * (apparently contrary to the spec) so a 256-entry table is always generated.
fukasawa e60969
 */
fukasawa e60969
static void
fukasawa e60969
png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
fukasawa e60969
   PNG_CONST png_fixed_point gamma_val)
fukasawa e60969
{
fukasawa e60969
   unsigned int i;
fukasawa e60969
   png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
fukasawa e60969
fukasawa e60969
   if (png_gamma_significant(gamma_val) != 0)
fukasawa e60969
      for (i=0; i<256; i++)
fukasawa e60969
         table[i] = png_gamma_8bit_correct(i, gamma_val);
fukasawa e60969
fukasawa e60969
   else
fukasawa e60969
      for (i=0; i<256; ++i)
fukasawa e60969
         table[i] = (png_byte)(i & 0xff);
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* Used from png_read_destroy and below to release the memory used by the gamma
fukasawa e60969
 * tables.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_destroy_gamma_table(png_structrp png_ptr)
fukasawa e60969
{
fukasawa e60969
   png_free(png_ptr, png_ptr->gamma_table);
fukasawa e60969
   png_ptr->gamma_table = NULL;
fukasawa e60969
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
   if (png_ptr->gamma_16_table != NULL)
fukasawa e60969
   {
fukasawa e60969
      int i;
fukasawa e60969
      int istop = (1 << (8 - png_ptr->gamma_shift));
fukasawa e60969
      for (i = 0; i < istop; i++)
fukasawa e60969
      {
fukasawa e60969
         png_free(png_ptr, png_ptr->gamma_16_table[i]);
fukasawa e60969
      }
fukasawa e60969
   png_free(png_ptr, png_ptr->gamma_16_table);
fukasawa e60969
   png_ptr->gamma_16_table = NULL;
fukasawa e60969
   }
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
fukasawa e60969
   png_free(png_ptr, png_ptr->gamma_from_1);
fukasawa e60969
   png_ptr->gamma_from_1 = NULL;
fukasawa e60969
   png_free(png_ptr, png_ptr->gamma_to_1);
fukasawa e60969
   png_ptr->gamma_to_1 = NULL;
fukasawa e60969
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
   if (png_ptr->gamma_16_from_1 != NULL)
fukasawa e60969
   {
fukasawa e60969
      int i;
fukasawa e60969
      int istop = (1 << (8 - png_ptr->gamma_shift));
fukasawa e60969
      for (i = 0; i < istop; i++)
fukasawa e60969
      {
fukasawa e60969
         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
fukasawa e60969
      }
fukasawa e60969
   png_free(png_ptr, png_ptr->gamma_16_from_1);
fukasawa e60969
   png_ptr->gamma_16_from_1 = NULL;
fukasawa e60969
   }
fukasawa e60969
   if (png_ptr->gamma_16_to_1 != NULL)
fukasawa e60969
   {
fukasawa e60969
      int i;
fukasawa e60969
      int istop = (1 << (8 - png_ptr->gamma_shift));
fukasawa e60969
      for (i = 0; i < istop; i++)
fukasawa e60969
      {
fukasawa e60969
         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
fukasawa e60969
      }
fukasawa e60969
   png_free(png_ptr, png_ptr->gamma_16_to_1);
fukasawa e60969
   png_ptr->gamma_16_to_1 = NULL;
fukasawa e60969
   }
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
fukasawa e60969
 * tables, we don't make a full table if we are reducing to 8-bit in
fukasawa e60969
 * the future.  Note also how the gamma_16 tables are segmented so that
fukasawa e60969
 * we don't need to allocate > 64K chunks for a full 16-bit table.
fukasawa e60969
 */
fukasawa e60969
void /* PRIVATE */
fukasawa e60969
png_build_gamma_table(png_structrp png_ptr, int bit_depth)
fukasawa e60969
{
fukasawa e60969
  png_debug(1, "in png_build_gamma_table");
fukasawa e60969
fukasawa e60969
  /* Remove any existing table; this copes with multiple calls to
fukasawa e60969
   * png_read_update_info.  The warning is because building the gamma tables
fukasawa e60969
   * multiple times is a performance hit - it's harmless but the ability to call
fukasawa e60969
   * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible
fukasawa e60969
   * to warn if the app introduces such a hit.
fukasawa e60969
   */
fukasawa e60969
  if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
fukasawa e60969
  {
fukasawa e60969
    png_warning(png_ptr, "gamma table being rebuilt");
fukasawa e60969
    png_destroy_gamma_table(png_ptr);
fukasawa e60969
  }
fukasawa e60969
fukasawa e60969
  if (bit_depth <= 8)
fukasawa e60969
  {
fukasawa e60969
     png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
fukasawa e60969
         png_ptr->screen_gamma > 0 ?  png_reciprocal2(png_ptr->colorspace.gamma,
fukasawa e60969
         png_ptr->screen_gamma) : PNG_FP_1);
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
fukasawa e60969
     if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
fukasawa e60969
     {
fukasawa e60969
        png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
fukasawa e60969
            png_reciprocal(png_ptr->colorspace.gamma));
fukasawa e60969
fukasawa e60969
        png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
fukasawa e60969
            png_ptr->screen_gamma > 0 ?  png_reciprocal(png_ptr->screen_gamma) :
fukasawa e60969
            png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
fukasawa e60969
     }
fukasawa e60969
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
fukasawa e60969
  }
fukasawa e60969
#ifdef PNG_16BIT_SUPPORTED
fukasawa e60969
  else
fukasawa e60969
  {
fukasawa e60969
     png_byte shift, sig_bit;
fukasawa e60969
fukasawa e60969
     if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
fukasawa e60969
     {
fukasawa e60969
        sig_bit = png_ptr->sig_bit.red;
fukasawa e60969
fukasawa e60969
        if (png_ptr->sig_bit.green > sig_bit)
fukasawa e60969
           sig_bit = png_ptr->sig_bit.green;
fukasawa e60969
fukasawa e60969
        if (png_ptr->sig_bit.blue > sig_bit)
fukasawa e60969
           sig_bit = png_ptr->sig_bit.blue;
fukasawa e60969
     }
fukasawa e60969
     else
fukasawa e60969
        sig_bit = png_ptr->sig_bit.gray;
fukasawa e60969
fukasawa e60969
     /* 16-bit gamma code uses this equation:
fukasawa e60969
      *
fukasawa e60969
      *   ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
fukasawa e60969
      *
fukasawa e60969
      * Where 'iv' is the input color value and 'ov' is the output value -
fukasawa e60969
      * pow(iv, gamma).
fukasawa e60969
      *
fukasawa e60969
      * Thus the gamma table consists of up to 256 256-entry tables.  The table
fukasawa e60969
      * is selected by the (8-gamma_shift) most significant of the low 8 bits of
fukasawa e60969
      * the color value then indexed by the upper 8 bits:
fukasawa e60969
      *
fukasawa e60969
      *   table[low bits][high 8 bits]
fukasawa e60969
      *
fukasawa e60969
      * So the table 'n' corresponds to all those 'iv' of:
fukasawa e60969
      *
fukasawa e60969
      *   <all 8-bit="" high="" values=""><n <<="" gamma_shift="">..<(n+1 << gamma_shift)-1></n></all>
fukasawa e60969
      *
fukasawa e60969
      */
fukasawa e60969
     if (sig_bit > 0 && sig_bit < 16U)
fukasawa e60969
        /* shift == insignificant bits */
fukasawa e60969
        shift = (png_byte)((16U - sig_bit) & 0xff);
fukasawa e60969
fukasawa e60969
     else
fukasawa e60969
        shift = 0; /* keep all 16 bits */
fukasawa e60969
fukasawa e60969
     if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
fukasawa e60969
     {
fukasawa e60969
        /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
fukasawa e60969
         * the significant bits in the *input* when the output will
fukasawa e60969
         * eventually be 8 bits.  By default it is 11.
fukasawa e60969
         */
fukasawa e60969
        if (shift < (16U - PNG_MAX_GAMMA_8))
fukasawa e60969
           shift = (16U - PNG_MAX_GAMMA_8);
fukasawa e60969
     }
fukasawa e60969
fukasawa e60969
     if (shift > 8U)
fukasawa e60969
        shift = 8U; /* Guarantees at least one table! */
fukasawa e60969
fukasawa e60969
     png_ptr->gamma_shift = shift;
fukasawa e60969
fukasawa e60969
     /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
fukasawa e60969
      * PNG_COMPOSE).  This effectively smashed the background calculation for
fukasawa e60969
      * 16-bit output because the 8-bit table assumes the result will be reduced
fukasawa e60969
      * to 8 bits.
fukasawa e60969
      */
fukasawa e60969
     if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
fukasawa e60969
         png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
fukasawa e60969
         png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
fukasawa e60969
         png_ptr->screen_gamma) : PNG_FP_1);
fukasawa e60969
fukasawa e60969
     else
fukasawa e60969
         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
fukasawa e60969
         png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
fukasawa e60969
         png_ptr->screen_gamma) : PNG_FP_1);
fukasawa e60969
fukasawa e60969
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
fukasawa e60969
   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
fukasawa e60969
     if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
fukasawa e60969
     {
fukasawa e60969
        png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
fukasawa e60969
            png_reciprocal(png_ptr->colorspace.gamma));
fukasawa e60969
fukasawa e60969
        /* Notice that the '16 from 1' table should be full precision, however
fukasawa e60969
         * the lookup on this table still uses gamma_shift, so it can't be.
fukasawa e60969
         * TODO: fix this.
fukasawa e60969
         */
fukasawa e60969
        png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
fukasawa e60969
            png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
fukasawa e60969
            png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
fukasawa e60969
     }
fukasawa e60969
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
fukasawa e60969
  }
fukasawa e60969
#endif /* 16BIT */
fukasawa e60969
}
fukasawa e60969
#endif /* READ_GAMMA */
fukasawa e60969
fukasawa e60969
/* HARDWARE OR SOFTWARE OPTION SUPPORT */
fukasawa e60969
#ifdef PNG_SET_OPTION_SUPPORTED
fukasawa e60969
int PNGAPI
fukasawa e60969
png_set_option(png_structrp png_ptr, int option, int onoff)
fukasawa e60969
{
fukasawa e60969
   if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
fukasawa e60969
      (option & 1) == 0)
fukasawa e60969
   {
fukasawa e60969
      int mask = 3 << option;
fukasawa e60969
      int setting = (2 + (onoff != 0)) << option;
fukasawa e60969
      int current = png_ptr->options;
fukasawa e60969
fukasawa e60969
      png_ptr->options = (png_byte)(((current & ~mask) | setting) & 0xff);
fukasawa e60969
fukasawa e60969
      return (current & mask) >> option;
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   return PNG_OPTION_INVALID;
fukasawa e60969
}
fukasawa e60969
#endif
fukasawa e60969
fukasawa e60969
/* sRGB support */
fukasawa e60969
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
fukasawa e60969
   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
fukasawa e60969
/* sRGB conversion tables; these are machine generated with the code in
fukasawa e60969
 * contrib/tools/makesRGB.c.  The actual sRGB transfer curve defined in the
fukasawa e60969
 * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
fukasawa e60969
 * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
fukasawa e60969
 * The sRGB to linear table is exact (to the nearest 16-bit linear fraction).
fukasawa e60969
 * The inverse (linear to sRGB) table has accuracies as follows:
fukasawa e60969
 *
fukasawa e60969
 * For all possible (255*65535+1) input values:
fukasawa e60969
 *
fukasawa e60969
 *    error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
fukasawa e60969
 *
fukasawa e60969
 * For the input values corresponding to the 65536 16-bit values:
fukasawa e60969
 *
fukasawa e60969
 *    error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
fukasawa e60969
 *
fukasawa e60969
 * In all cases the inexact readings are only off by one.
fukasawa e60969
 */
fukasawa e60969
fukasawa e60969
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
fukasawa e60969
/* The convert-to-sRGB table is only currently required for read. */
fukasawa e60969
const png_uint_16 png_sRGB_table[256] =
fukasawa e60969
{
fukasawa e60969
   0,20,40,60,80,99,119,139,
fukasawa e60969
   159,179,199,219,241,264,288,313,
fukasawa e60969
   340,367,396,427,458,491,526,562,
fukasawa e60969
   599,637,677,718,761,805,851,898,
fukasawa e60969
   947,997,1048,1101,1156,1212,1270,1330,
fukasawa e60969
   1391,1453,1517,1583,1651,1720,1790,1863,
fukasawa e60969
   1937,2013,2090,2170,2250,2333,2418,2504,
fukasawa e60969
   2592,2681,2773,2866,2961,3058,3157,3258,
fukasawa e60969
   3360,3464,3570,3678,3788,3900,4014,4129,
fukasawa e60969
   4247,4366,4488,4611,4736,4864,4993,5124,
fukasawa e60969
   5257,5392,5530,5669,5810,5953,6099,6246,
fukasawa e60969
   6395,6547,6700,6856,7014,7174,7335,7500,
fukasawa e60969
   7666,7834,8004,8177,8352,8528,8708,8889,
fukasawa e60969
   9072,9258,9445,9635,9828,10022,10219,10417,
fukasawa e60969
   10619,10822,11028,11235,11446,11658,11873,12090,
fukasawa e60969
   12309,12530,12754,12980,13209,13440,13673,13909,
fukasawa e60969
   14146,14387,14629,14874,15122,15371,15623,15878,
fukasawa e60969
   16135,16394,16656,16920,17187,17456,17727,18001,
fukasawa e60969
   18277,18556,18837,19121,19407,19696,19987,20281,
fukasawa e60969
   20577,20876,21177,21481,21787,22096,22407,22721,
fukasawa e60969
   23038,23357,23678,24002,24329,24658,24990,25325,
fukasawa e60969
   25662,26001,26344,26688,27036,27386,27739,28094,
fukasawa e60969
   28452,28813,29176,29542,29911,30282,30656,31033,
fukasawa e60969
   31412,31794,32179,32567,32957,33350,33745,34143,
fukasawa e60969
   34544,34948,35355,35764,36176,36591,37008,37429,
fukasawa e60969
   37852,38278,38706,39138,39572,40009,40449,40891,
fukasawa e60969
   41337,41785,42236,42690,43147,43606,44069,44534,
fukasawa e60969
   45002,45473,45947,46423,46903,47385,47871,48359,
fukasawa e60969
   48850,49344,49841,50341,50844,51349,51858,52369,
fukasawa e60969
   52884,53401,53921,54445,54971,55500,56032,56567,
fukasawa e60969
   57105,57646,58190,58737,59287,59840,60396,60955,
fukasawa e60969
   61517,62082,62650,63221,63795,64372,64952,65535
fukasawa e60969
};
fukasawa e60969
#endif /* SIMPLIFIED_READ */
fukasawa e60969
fukasawa e60969
/* The base/delta tables are required for both read and write (but currently
fukasawa e60969
 * only the simplified versions.)
fukasawa e60969
 */
fukasawa e60969
const png_uint_16 png_sRGB_base[512] =
fukasawa e60969
{
fukasawa e60969
   128,1782,3383,4644,5675,6564,7357,8074,
fukasawa e60969
   8732,9346,9921,10463,10977,11466,11935,12384,
fukasawa e60969
   12816,13233,13634,14024,14402,14769,15125,15473,
fukasawa e60969
   15812,16142,16466,16781,17090,17393,17690,17981,
fukasawa e60969
   18266,18546,18822,19093,19359,19621,19879,20133,
fukasawa e60969
   20383,20630,20873,21113,21349,21583,21813,22041,
fukasawa e60969
   22265,22487,22707,22923,23138,23350,23559,23767,
fukasawa e60969
   23972,24175,24376,24575,24772,24967,25160,25352,
fukasawa e60969
   25542,25730,25916,26101,26284,26465,26645,26823,
fukasawa e60969
   27000,27176,27350,27523,27695,27865,28034,28201,
fukasawa e60969
   28368,28533,28697,28860,29021,29182,29341,29500,
fukasawa e60969
   29657,29813,29969,30123,30276,30429,30580,30730,
fukasawa e60969
   30880,31028,31176,31323,31469,31614,31758,31902,
fukasawa e60969
   32045,32186,32327,32468,32607,32746,32884,33021,
fukasawa e60969
   33158,33294,33429,33564,33697,33831,33963,34095,
fukasawa e60969
   34226,34357,34486,34616,34744,34873,35000,35127,
fukasawa e60969
   35253,35379,35504,35629,35753,35876,35999,36122,
fukasawa e60969
   36244,36365,36486,36606,36726,36845,36964,37083,
fukasawa e60969
   37201,37318,37435,37551,37668,37783,37898,38013,
fukasawa e60969
   38127,38241,38354,38467,38580,38692,38803,38915,
fukasawa e60969
   39026,39136,39246,39356,39465,39574,39682,39790,
fukasawa e60969
   39898,40005,40112,40219,40325,40431,40537,40642,
fukasawa e60969
   40747,40851,40955,41059,41163,41266,41369,41471,
fukasawa e60969
   41573,41675,41777,41878,41979,42079,42179,42279,
fukasawa e60969
   42379,42478,42577,42676,42775,42873,42971,43068,
fukasawa e60969
   43165,43262,43359,43456,43552,43648,43743,43839,
fukasawa e60969
   43934,44028,44123,44217,44311,44405,44499,44592,
fukasawa e60969
   44685,44778,44870,44962,45054,45146,45238,45329,
fukasawa e60969
   45420,45511,45601,45692,45782,45872,45961,46051,
fukasawa e60969
   46140,46229,46318,46406,46494,46583,46670,46758,
fukasawa e60969
   46846,46933,47020,47107,47193,47280,47366,47452,
fukasawa e60969
   47538,47623,47709,47794,47879,47964,48048,48133,
fukasawa e60969
   48217,48301,48385,48468,48552,48635,48718,48801,
fukasawa e60969
   48884,48966,49048,49131,49213,49294,49376,49458,
fukasawa e60969
   49539,49620,49701,49782,49862,49943,50023,50103,
fukasawa e60969
   50183,50263,50342,50422,50501,50580,50659,50738,
fukasawa e60969
   50816,50895,50973,51051,51129,51207,51285,51362,
fukasawa e60969
   51439,51517,51594,51671,51747,51824,51900,51977,
fukasawa e60969
   52053,52129,52205,52280,52356,52432,52507,52582,
fukasawa e60969
   52657,52732,52807,52881,52956,53030,53104,53178,
fukasawa e60969
   53252,53326,53400,53473,53546,53620,53693,53766,
fukasawa e60969
   53839,53911,53984,54056,54129,54201,54273,54345,
fukasawa e60969
   54417,54489,54560,54632,54703,54774,54845,54916,
fukasawa e60969
   54987,55058,55129,55199,55269,55340,55410,55480,
fukasawa e60969
   55550,55620,55689,55759,55828,55898,55967,56036,
fukasawa e60969
   56105,56174,56243,56311,56380,56448,56517,56585,
fukasawa e60969
   56653,56721,56789,56857,56924,56992,57059,57127,
fukasawa e60969
   57194,57261,57328,57395,57462,57529,57595,57662,
fukasawa e60969
   57728,57795,57861,57927,57993,58059,58125,58191,
fukasawa e60969
   58256,58322,58387,58453,58518,58583,58648,58713,
fukasawa e60969
   58778,58843,58908,58972,59037,59101,59165,59230,
fukasawa e60969
   59294,59358,59422,59486,59549,59613,59677,59740,
fukasawa e60969
   59804,59867,59930,59993,60056,60119,60182,60245,
fukasawa e60969
   60308,60370,60433,60495,60558,60620,60682,60744,
fukasawa e60969
   60806,60868,60930,60992,61054,61115,61177,61238,
fukasawa e60969
   61300,61361,61422,61483,61544,61605,61666,61727,
fukasawa e60969
   61788,61848,61909,61969,62030,62090,62150,62211,
fukasawa e60969
   62271,62331,62391,62450,62510,62570,62630,62689,
fukasawa e60969
   62749,62808,62867,62927,62986,63045,63104,63163,
fukasawa e60969
   63222,63281,63340,63398,63457,63515,63574,63632,
fukasawa e60969
   63691,63749,63807,63865,63923,63981,64039,64097,
fukasawa e60969
   64155,64212,64270,64328,64385,64443,64500,64557,
fukasawa e60969
   64614,64672,64729,64786,64843,64900,64956,65013,
fukasawa e60969
   65070,65126,65183,65239,65296,65352,65409,65465
fukasawa e60969
};
fukasawa e60969
fukasawa e60969
const png_byte png_sRGB_delta[512] =
fukasawa e60969
{
fukasawa e60969
   207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
fukasawa e60969
   52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
fukasawa e60969
   35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
fukasawa e60969
   28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
fukasawa e60969
   23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
fukasawa e60969
   21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
fukasawa e60969
   19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
fukasawa e60969
   17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
fukasawa e60969
   16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
fukasawa e60969
   15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
fukasawa e60969
   14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
fukasawa e60969
   13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
fukasawa e60969
   12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
fukasawa e60969
   12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
fukasawa e60969
   11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
fukasawa e60969
   11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
fukasawa e60969
   11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
fukasawa e60969
   10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
fukasawa e60969
   10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
fukasawa e60969
   10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
fukasawa e60969
   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
fukasawa e60969
   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
fukasawa e60969
   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
fukasawa e60969
   9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
fukasawa e60969
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
fukasawa e60969
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
fukasawa e60969
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
fukasawa e60969
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
fukasawa e60969
   8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
fukasawa e60969
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
fukasawa e60969
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
fukasawa e60969
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
fukasawa e60969
};
fukasawa e60969
#endif /* SIMPLIFIED READ/WRITE sRGB support */
fukasawa e60969
fukasawa e60969
/* SIMPLIFIED READ/WRITE SUPPORT */
fukasawa e60969
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
fukasawa e60969
   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
fukasawa e60969
static int
fukasawa e60969
png_image_free_function(png_voidp argument)
fukasawa e60969
{
fukasawa e60969
   png_imagep image = png_voidcast(png_imagep, argument);
fukasawa e60969
   png_controlp cp = image->opaque;
fukasawa e60969
   png_control c;
fukasawa e60969
fukasawa e60969
   /* Double check that we have a png_ptr - it should be impossible to get here
fukasawa e60969
    * without one.
fukasawa e60969
    */
fukasawa e60969
   if (cp->png_ptr == NULL)
fukasawa e60969
      return 0;
fukasawa e60969
fukasawa e60969
   /* First free any data held in the control structure. */
fukasawa e60969
#  ifdef PNG_STDIO_SUPPORTED
fukasawa e60969
      if (cp->owned_file != 0)
fukasawa e60969
      {
fukasawa e60969
         FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
fukasawa e60969
         cp->owned_file = 0;
fukasawa e60969
fukasawa e60969
         /* Ignore errors here. */
fukasawa e60969
         if (fp != NULL)
fukasawa e60969
         {
fukasawa e60969
            cp->png_ptr->io_ptr = NULL;
fukasawa e60969
            (void)fclose(fp);
fukasawa e60969
         }
fukasawa e60969
      }
fukasawa e60969
#  endif
fukasawa e60969
fukasawa e60969
   /* Copy the control structure so that the original, allocated, version can be
fukasawa e60969
    * safely freed.  Notice that a png_error here stops the remainder of the
fukasawa e60969
    * cleanup, but this is probably fine because that would indicate bad memory
fukasawa e60969
    * problems anyway.
fukasawa e60969
    */
fukasawa e60969
   c = *cp;
fukasawa e60969
   image->opaque = &c;
fukasawa e60969
   png_free(c.png_ptr, cp);
fukasawa e60969
fukasawa e60969
   /* Then the structures, calling the correct API. */
fukasawa e60969
   if (c.for_write != 0)
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
fukasawa e60969
         png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
fukasawa e60969
#     else
fukasawa e60969
         png_error(c.png_ptr, "simplified write not supported");
fukasawa e60969
#     endif
fukasawa e60969
   }
fukasawa e60969
   else
fukasawa e60969
   {
fukasawa e60969
#     ifdef PNG_SIMPLIFIED_READ_SUPPORTED
fukasawa e60969
         png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
fukasawa e60969
#     else
fukasawa e60969
         png_error(c.png_ptr, "simplified read not supported");
fukasawa e60969
#     endif
fukasawa e60969
   }
fukasawa e60969
fukasawa e60969
   /* Success. */
fukasawa e60969
   return 1;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
void PNGAPI
fukasawa e60969
png_image_free(png_imagep image)
fukasawa e60969
{
fukasawa e60969
   /* Safely call the real function, but only if doing so is safe at this point
fukasawa e60969
    * (if not inside an error handling context).  Otherwise assume
fukasawa e60969
    * png_safe_execute will call this API after the return.
fukasawa e60969
    */
fukasawa e60969
   if (image != NULL && image->opaque != NULL &&
fukasawa e60969
      image->opaque->error_buf == NULL)
fukasawa e60969
   {
fukasawa e60969
      /* Ignore errors here: */
fukasawa e60969
      (void)png_safe_execute(image, png_image_free_function, image);
fukasawa e60969
      image->opaque = NULL;
fukasawa e60969
   }
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
int /* PRIVATE */
fukasawa e60969
png_image_error(png_imagep image, png_const_charp error_message)
fukasawa e60969
{
fukasawa e60969
   /* Utility to log an error. */
fukasawa e60969
   png_safecat(image->message, (sizeof image->message), 0, error_message);
fukasawa e60969
   image->warning_or_error |= PNG_IMAGE_ERROR;
fukasawa e60969
   png_image_free(image);
fukasawa e60969
   return 0;
fukasawa e60969
}
fukasawa e60969
fukasawa e60969
#endif /* SIMPLIFIED READ/WRITE */
fukasawa e60969
#endif /* READ || WRITE */