14d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* pngread.c - read a PNG file
34d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
44d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * Last changed in libpng 1.6.17 [March 26, 2015]
54d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
64d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
94d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * This code is released under the libpng license.
104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * For conditions of distribution and use, see the disclaimer
114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * and license in png.h
124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * This file contains routines that an application calls directly to
144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * read a PNG file or stream.
154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "pngpriv.h"
184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  include <errno.h>
204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_SUPPORTED
234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Create a PNG structure for reading, and allocate any memory needed. */
254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannPNG_FUNCTION(png_structp,PNGAPI
264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifndef PNG_USER_MEM_SUPPORTED
304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      error_fn, warn_fn, NULL, NULL, NULL);
324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       warn_fn, NULL, NULL, NULL);
354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Alternate create PNG structure for reading, and allocate any memory
384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * needed.
394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannPNG_FUNCTION(png_structp,PNGAPI
414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* USER_MEM */
484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr != NULL)
504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr->mode = PNG_IS_READ_STRUCT;
524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Added in libpng-1.6.0; this can be used to detect a read structure if
544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * required (it will be zero in a write structure.)
554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* In stable builds only warn if an application error can be completely
644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * handled.
654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        if PNG_RELEASE_BUILD
674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        endif
694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* TODO: delay this, it can be done in png_init_io (if the app doesn't
724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * do it itself) avoiding setting the default function if it is not
734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * required.
744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_read_fn(png_ptr, NULL, NULL);
764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return png_ptr;
794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Read the information before the actual image data.  This has been
844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * changed in v0.90 to allow reading a file that already has the magic
854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * bytes read from the stream.  You can tell libpng how many bytes have
864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * been read from the beginning of the stream (up to the maximum of 8)
874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * via png_set_sig_bytes(), and we will only check the remaining bytes
884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * here.  The application can then have access to the signature bytes we
894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * read if it is determined that this isn't a valid PNG file.
904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_info(png_structrp png_ptr, png_inforp info_ptr)
934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int keep;
964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_read_info");
994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL || info_ptr == NULL)
1014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
1024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Read and check the PNG file signature. */
1044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_sig(png_ptr, info_ptr);
1054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   for (;;)
1074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
1084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 length = png_read_chunk_header(png_ptr);
1094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 chunk_name = png_ptr->chunk_name;
1104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* IDAT logic needs to happen here to simplify getting the two flags
1124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * right.
1134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
1144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (chunk_name == png_IDAT)
1154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
1164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
1174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_chunk_error(png_ptr, "Missing IHDR before IDAT");
1184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             (png_ptr->mode & PNG_HAVE_PLTE) == 0)
1214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_chunk_error(png_ptr, "Missing PLTE before IDAT");
1224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
1244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_chunk_benign_error(png_ptr, "Too many IDATs found");
1254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->mode |= PNG_HAVE_IDAT;
1274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
1284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
1304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
1314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
1324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->mode |= PNG_AFTER_IDAT;
1334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
1344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* This should be a binary subdivision search or a hash for
1364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * matching the chunk name rather than a linear search.
1374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
1384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (chunk_name == png_IHDR)
1394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_IHDR(png_ptr, info_ptr, length);
1404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_IEND)
1424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_IEND(png_ptr, info_ptr, length);
1434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
1464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
1474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_unknown(png_ptr, info_ptr, length, keep);
1484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (chunk_name == png_PLTE)
1504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->mode |= PNG_HAVE_PLTE;
1514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else if (chunk_name == png_IDAT)
1534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
1544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->idat_size = 0; /* It has been consumed */
1554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
1564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
1574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
1584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_PLTE)
1604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_PLTE(png_ptr, info_ptr, length);
1614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_IDAT)
1634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
1644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->idat_size = length;
1654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
1664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
1674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_bKGD_SUPPORTED
1694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_bKGD)
1704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_bKGD(png_ptr, info_ptr, length);
1714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_cHRM_SUPPORTED
1744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_cHRM)
1754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_cHRM(png_ptr, info_ptr, length);
1764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_gAMA_SUPPORTED
1794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_gAMA)
1804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_gAMA(png_ptr, info_ptr, length);
1814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_hIST_SUPPORTED
1844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_hIST)
1854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_hIST(png_ptr, info_ptr, length);
1864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_oFFs_SUPPORTED
1894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_oFFs)
1904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_oFFs(png_ptr, info_ptr, length);
1914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_pCAL_SUPPORTED
1944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_pCAL)
1954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_pCAL(png_ptr, info_ptr, length);
1964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
1974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sCAL_SUPPORTED
1994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sCAL)
2004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sCAL(png_ptr, info_ptr, length);
2014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_pHYs_SUPPORTED
2044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_pHYs)
2054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_pHYs(png_ptr, info_ptr, length);
2064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sBIT_SUPPORTED
2094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sBIT)
2104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sBIT(png_ptr, info_ptr, length);
2114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sRGB_SUPPORTED
2144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sRGB)
2154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sRGB(png_ptr, info_ptr, length);
2164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_iCCP_SUPPORTED
2194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_iCCP)
2204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_iCCP(png_ptr, info_ptr, length);
2214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sPLT_SUPPORTED
2244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sPLT)
2254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sPLT(png_ptr, info_ptr, length);
2264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_tEXt_SUPPORTED
2294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_tEXt)
2304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_tEXt(png_ptr, info_ptr, length);
2314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_tIME_SUPPORTED
2344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_tIME)
2354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_tIME(png_ptr, info_ptr, length);
2364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_tRNS_SUPPORTED
2394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_tRNS)
2404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_tRNS(png_ptr, info_ptr, length);
2414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_zTXt_SUPPORTED
2444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_zTXt)
2454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_zTXt(png_ptr, info_ptr, length);
2464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_iTXt_SUPPORTED
2494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_iTXt)
2504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_iTXt(png_ptr, info_ptr, length);
2514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
2524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
2544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_unknown(png_ptr, info_ptr, length,
2554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            PNG_HANDLE_CHUNK_AS_DEFAULT);
2564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
2574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
2594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Optional call to update the users info_ptr structure */
2614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
2624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
2634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
2644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_read_update_info");
2654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr != NULL)
2674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
2684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
2694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
2704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_start_row(png_ptr);
2714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        ifdef PNG_READ_TRANSFORMS_SUPPORTED
2734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_read_transform_info(png_ptr, info_ptr);
2744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        else
2754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            PNG_UNUSED(info_ptr)
2764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        endif
2774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
2784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* New in 1.6.0 this avoids the bug of doing the initializations twice */
2804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
2814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_app_error(png_ptr,
2824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "png_read_update_info/png_start_read_image: duplicate call");
2834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
2844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
2874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Initialize palette, background, etc, after transformations
2884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * are set, but before any reading takes place.  This allows
2894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * the user to obtain a gamma-corrected palette, for example.
2904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * If the user doesn't call this, we will do it ourselves.
2914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
2924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
2934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_start_read_image(png_structrp png_ptr)
2944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
2954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_start_read_image");
2964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr != NULL)
2984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
2994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
3004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_start_row(png_ptr);
3014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* New in 1.6.0 this avoids the bug of doing the initializations twice */
3034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
3044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_app_error(png_ptr,
3054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "png_start_read_image/png_read_update_info: duplicate call");
3064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
3074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
3094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
3114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_MNG_FEATURES_SUPPORTED
3124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Undoes intrapixel differencing,
3134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * NOTE: this is apparently only supported in the 'sequential' reader.
3144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
3154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void
3164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_do_read_intrapixel(png_row_infop row_info, png_bytep row)
3174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
3184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_do_read_intrapixel");
3194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (
3214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
3224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
3234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int bytes_per_pixel;
3244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 row_width = row_info->width;
3254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row_info->bit_depth == 8)
3274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
3284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep rp;
3294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32 i;
3304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
3324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            bytes_per_pixel = 3;
3334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            bytes_per_pixel = 4;
3364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
3384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            return;
3394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
3414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
3424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
3434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
3444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
3454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
3464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (row_info->bit_depth == 16)
3474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
3484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep rp;
3494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32 i;
3504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
3524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            bytes_per_pixel = 6;
3534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            bytes_per_pixel = 8;
3564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
3584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            return;
3594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
3614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
3624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
3634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
3644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
3654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
3664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
3674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *(rp    ) = (png_byte)((red >> 8) & 0xff);
3684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *(rp + 1) = (png_byte)(red & 0xff);
3694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
3704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *(rp + 5) = (png_byte)(blue & 0xff);
3714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
3724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
3734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
3744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* MNG_FEATURES */
3764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
3784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
3794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
3804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_row_info row_info;
3814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL)
3834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
3844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug2(1, "in png_read_row (row %lu, pass %d)",
3864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       (unsigned long)png_ptr->row_number, png_ptr->pass);
3874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* png_read_start_row sets the information (in particular iwidth) for this
3894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * interlace pass.
3904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
3914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
3924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_read_start_row(png_ptr);
3934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* 1.5.6: row_info moved out of png_struct to a local here. */
3954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
3964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   row_info.color_type = png_ptr->color_type;
3974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   row_info.bit_depth = png_ptr->bit_depth;
3984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   row_info.channels = png_ptr->channels;
3994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   row_info.pixel_depth = png_ptr->pixel_depth;
4004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
4014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_WARNINGS_SUPPORTED
4034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
4044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
4054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Check for transforms that have been set but were defined out */
4064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
4074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
4094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
4124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_FILLER) != 0)
4134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
4144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
4174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    !defined(PNG_READ_PACKSWAP_SUPPORTED)
4184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
4204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
4234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_PACK) != 0)
4244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
4254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
4284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_SHIFT) != 0)
4294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
4304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
4334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_BGR) != 0)
4344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
4354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
4384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
4394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
4404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
4424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* WARNINGS */
4434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_INTERLACING_SUPPORTED
4454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* If interlaced and we do not need a new row, combine row and return.
4464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * Notice that the pixels we have from previous rows have been transformed
4474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * already; we can only combine like with like (transformed or
4484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * untransformed) and, because of the libpng API for interlaced images, this
4494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * means we must transform before de-interlacing.
4504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
4514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->interlaced != 0 &&
4524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       (png_ptr->transformations & PNG_INTERLACE) != 0)
4534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
4544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      switch (png_ptr->pass)
4554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
4564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 0:
4574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_ptr->row_number & 0x07)
4584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
4594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (dsp_row != NULL)
4604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
4614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
4624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
4634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
4644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
4654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 1:
4674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
4684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
4694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (dsp_row != NULL)
4704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
4714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
4734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
4744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
4754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
4764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 2:
4784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->row_number & 0x07) != 4)
4794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
4804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (dsp_row != NULL && (png_ptr->row_number & 4))
4814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
4824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
4844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
4854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
4864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
4874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 3:
4894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
4904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
4914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (dsp_row != NULL)
4924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
4934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
4954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
4964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
4974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
4984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 4:
5004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->row_number & 3) != 2)
5014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
5024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (dsp_row != NULL && (png_ptr->row_number & 2))
5034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
5044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
5064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
5074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
5084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
5094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 5:
5114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
5124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
5134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (dsp_row != NULL)
5144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
5154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
5174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
5184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
5194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
5204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         default:
5224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case 6:
5234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->row_number & 1) == 0)
5244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
5254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_read_finish_row(png_ptr);
5264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
5274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
5284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
5294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
5304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
5314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
5324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
5344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "Invalid attempt to read row data");
5354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Fill the row with IDAT data: */
5374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
5384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
5404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
5414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
5424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
5434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
5444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
5454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "bad adaptive filter value");
5464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
5474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
5494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * 1.5.6, while the buffer really is this big in current versions of libpng
5504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * it may not be in the future, so this was changed just to copy the
5514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * interlaced count:
5524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
5534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
5544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_MNG_FEATURES_SUPPORTED
5564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
5574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
5584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
5594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Intrapixel differencing */
5604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
5614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
5624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
5634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_TRANSFORMS_SUPPORTED
5654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->transformations)
5664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_do_read_transformations(png_ptr, &row_info);
5674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
5684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* The transformed pixel depth should match the depth now in row_info. */
5704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->transformed_pixel_depth == 0)
5714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
5724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
5734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
5744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "sequential row overflow");
5754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
5764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
5784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "internal sequential row size calculation error");
5794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_INTERLACING_SUPPORTED
5814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Expand interlaced rows to full size */
5824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->interlaced != 0 &&
5834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (png_ptr->transformations & PNG_INTERLACE) != 0)
5844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
5854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (png_ptr->pass < 6)
5864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
5874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->transformations);
5884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (dsp_row != NULL)
5904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_combine_row(png_ptr, dsp_row, 1/*display*/);
5914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row != NULL)
5934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_combine_row(png_ptr, row, 0/*row*/);
5944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
5954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else
5974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
5984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
5994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row != NULL)
6004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_combine_row(png_ptr, row, -1/*ignored*/);
6014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (dsp_row != NULL)
6034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_combine_row(png_ptr, dsp_row, -1/*ignored*/);
6044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
6054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_finish_row(png_ptr);
6064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->read_row_fn != NULL)
6084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
6094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
6114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
6124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
6144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Read one or more rows of image data.  If the image is interlaced,
6154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * and png_set_interlace_handling() has been called, the rows need to
6164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * contain the contents of the rows from the previous pass.  If the
6174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * image has alpha or transparency, and png_handle_alpha()[*] has been
6184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * called, the rows contents must be initialized to the contents of the
6194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * screen.
6204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
6214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * "row" holds the actual image, and pixels are placed in it
6224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * as they arrive.  If the image is displayed after each pass, it will
6234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * appear to "sparkle" in.  "display_row" can be used to display a
6244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * "chunky" progressive image, with finer detail added as it becomes
6254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * available.  If you do not want this "chunky" display, you may pass
6264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * NULL for display_row.  If you do not want the sparkle display, and
6274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * you have not called png_handle_alpha(), you may pass NULL for rows.
6284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * If you have called png_handle_alpha(), and the image has either an
6294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * alpha channel or a transparency chunk, you must provide a buffer for
6304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * rows.  In this case, you do not have to provide a display_row buffer
6314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * also, but you may.  If the image is not interlaced, or if you have
6324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * not called png_set_interlace_handling(), the display_row buffer will
6334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * be ignored, so pass NULL to it.
6344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
6354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * [*] png_handle_alpha() does not exist yet, as of this version of libpng
6364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
6374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
6394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_rows(png_structrp png_ptr, png_bytepp row,
6404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    png_bytepp display_row, png_uint_32 num_rows)
6414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
6424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 i;
6434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_bytepp rp;
6444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_bytepp dp;
6454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_read_rows");
6474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL)
6494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
6504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   rp = row;
6524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   dp = display_row;
6534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (rp != NULL && dp != NULL)
6544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (i = 0; i < num_rows; i++)
6554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
6564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep rptr = *rp++;
6574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep dptr = *dp++;
6584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_row(png_ptr, rptr, dptr);
6604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
6614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (rp != NULL)
6634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (i = 0; i < num_rows; i++)
6644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
6654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep rptr = *rp;
6664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_row(png_ptr, rptr, NULL);
6674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         rp++;
6684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
6694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (dp != NULL)
6714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (i = 0; i < num_rows; i++)
6724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
6734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep dptr = *dp;
6744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_row(png_ptr, NULL, dptr);
6754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         dp++;
6764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
6774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
6784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
6794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
6814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Read the entire image.  If the image has an alpha channel or a tRNS
6824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * chunk, and you have called png_handle_alpha()[*], you will need to
6834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * initialize the image to the current image that PNG will be overlaying.
6844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * We set the num_rows again here, in case it was incorrectly set in
6854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * png_read_start_row() by a call to png_read_update_info() or
6864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * png_start_read_image() if png_set_interlace_handling() wasn't called
6874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * prior to either of these functions like it should have been.  You can
6884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * only call this function once.  If you desire to have an image for
6894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * each pass of a interlaced image, use png_read_rows() instead.
6904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
6914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * [*] png_handle_alpha() does not exist yet, as of this version of libpng
6924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
6934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
6944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_image(png_structrp png_ptr, png_bytepp image)
6954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
6964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 i, image_height;
6974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int pass, j;
6984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_bytepp rp;
6994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_read_image");
7014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL)
7034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
7044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_INTERLACING_SUPPORTED
7064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
7074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
7084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      pass = png_set_interlace_handling(png_ptr);
7094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* And make sure transforms are initialized. */
7104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_start_read_image(png_ptr);
7114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
7124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else
7134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
7144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (png_ptr->interlaced != 0 &&
7154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          (png_ptr->transformations & PNG_INTERLACE) == 0)
7164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
7174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Caller called png_start_read_image or png_read_update_info without
7184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * first turning on the PNG_INTERLACE transform.  We can fix this here,
7194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * but the caller should do it!
7204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
7214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_warning(png_ptr, "Interlace handling should be turned on when "
7224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "using png_read_image");
7234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Make sure this is set correctly */
7244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->num_rows = png_ptr->height;
7254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
7264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
7284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * the above error case.
7294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
7304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      pass = png_set_interlace_handling(png_ptr);
7314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
7324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
7334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->interlaced)
7344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr,
7354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          "Cannot read interlaced image -- interlace handler disabled");
7364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   pass = 1;
7384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
7394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   image_height=png_ptr->height;
7414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   for (j = 0; j < pass; j++)
7434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
7444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      rp = image;
7454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (i = 0; i < image_height; i++)
7464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
7474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_read_row(png_ptr, *rp, NULL);
7484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         rp++;
7494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
7504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
7514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
7524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
7534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
7554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Read the end of the PNG file.  Will not read past the end of the
7564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * file, will verify the end is accurate, and will read any comments
7574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * or time information at the end of the file, if info is not NULL.
7584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
7594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
7604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_end(png_structrp png_ptr, png_inforp info_ptr)
7614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
7624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
7634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int keep;
7644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
7654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_read_end");
7674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL)
7694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
7704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* If png_read_end is called in the middle of reading the rows there may
7724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * still be pending IDAT data and an owned zstream.  Deal with this here.
7734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
7744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
7754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0)
7764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
7774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_read_finish_IDAT(png_ptr);
7784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
7804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Report invalid palette index; added at libng-1.5.10 */
7814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
7824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr->num_palette_max > png_ptr->num_palette)
7834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann     png_benign_error(png_ptr, "Read palette index exceeding num_palette");
7844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
7854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   do
7874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
7884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 length = png_read_chunk_header(png_ptr);
7894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 chunk_name = png_ptr->chunk_name;
7904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (chunk_name != png_IDAT)
7924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
7934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (chunk_name == png_IEND)
7954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_IEND(png_ptr, info_ptr, length);
7964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_IHDR)
7984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_IHDR(png_ptr, info_ptr, length);
7994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (info_ptr == NULL)
8014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_crc_finish(png_ptr, length);
8024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
8044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
8054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
8064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (chunk_name == png_IDAT)
8074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
8084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
8094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
8104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_benign_error(png_ptr, ".Too many IDATs found");
8114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
8124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_unknown(png_ptr, info_ptr, length, keep);
8134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (chunk_name == png_PLTE)
8144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->mode |= PNG_HAVE_PLTE;
8154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
8164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_IDAT)
8194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
8204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Zero length IDATs are legal after the last IDAT has been
8214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * read, but not after other chunks have been read.  1.6 does not
8224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * always read all the deflate data; specifically it cannot be relied
8234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * upon to read the Adler32 at the end.  If it doesn't ignore IDAT
8244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * chunks which are longer than zero as well:
8254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
8264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
8274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
8284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_benign_error(png_ptr, "..Too many IDATs found");
8294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_crc_finish(png_ptr, length);
8314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
8324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_PLTE)
8334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_PLTE(png_ptr, info_ptr, length);
8344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_bKGD_SUPPORTED
8364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_bKGD)
8374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_bKGD(png_ptr, info_ptr, length);
8384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_cHRM_SUPPORTED
8414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_cHRM)
8424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_cHRM(png_ptr, info_ptr, length);
8434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_gAMA_SUPPORTED
8464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_gAMA)
8474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_gAMA(png_ptr, info_ptr, length);
8484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_hIST_SUPPORTED
8514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_hIST)
8524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_hIST(png_ptr, info_ptr, length);
8534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_oFFs_SUPPORTED
8564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_oFFs)
8574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_oFFs(png_ptr, info_ptr, length);
8584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_pCAL_SUPPORTED
8614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_pCAL)
8624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_pCAL(png_ptr, info_ptr, length);
8634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sCAL_SUPPORTED
8664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sCAL)
8674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sCAL(png_ptr, info_ptr, length);
8684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_pHYs_SUPPORTED
8714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_pHYs)
8724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_pHYs(png_ptr, info_ptr, length);
8734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sBIT_SUPPORTED
8764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sBIT)
8774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sBIT(png_ptr, info_ptr, length);
8784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sRGB_SUPPORTED
8814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sRGB)
8824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sRGB(png_ptr, info_ptr, length);
8834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_iCCP_SUPPORTED
8864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_iCCP)
8874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_iCCP(png_ptr, info_ptr, length);
8884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_sPLT_SUPPORTED
8914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_sPLT)
8924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_sPLT(png_ptr, info_ptr, length);
8934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
8954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_tEXt_SUPPORTED
8964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_tEXt)
8974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_tEXt(png_ptr, info_ptr, length);
8984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
8994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_tIME_SUPPORTED
9014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_tIME)
9024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_tIME(png_ptr, info_ptr, length);
9034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_tRNS_SUPPORTED
9064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_tRNS)
9074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_tRNS(png_ptr, info_ptr, length);
9084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_zTXt_SUPPORTED
9114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_zTXt)
9124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_zTXt(png_ptr, info_ptr, length);
9134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_iTXt_SUPPORTED
9164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (chunk_name == png_iTXt)
9174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_iTXt(png_ptr, info_ptr, length);
9184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
9214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_handle_unknown(png_ptr, info_ptr, length,
9224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            PNG_HANDLE_CHUNK_AS_DEFAULT);
9234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   } while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
9244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
9254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
9264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Free all memory used in the read struct */
9284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void
9294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_destroy(png_structrp png_ptr)
9304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
9314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_read_destroy");
9324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_GAMMA_SUPPORTED
9344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_destroy_gamma_table(png_ptr);
9354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->big_row_buf);
9384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->big_row_buf = NULL;
9394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->big_prev_row);
9404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->big_prev_row = NULL;
9414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->read_buffer);
9424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->read_buffer = NULL;
9434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_QUANTIZE_SUPPORTED
9454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->palette_lookup);
9464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->palette_lookup = NULL;
9474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->quantize_index);
9484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->quantize_index = NULL;
9494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)
9524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
9534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_zfree(png_ptr, png_ptr->palette);
9544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr->palette = NULL;
9554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
9564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->free_me &= ~PNG_FREE_PLTE;
9574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_tRNS_SUPPORTED) || \
9594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
9604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)
9614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
9624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_free(png_ptr, png_ptr->trans_alpha);
9634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr->trans_alpha = NULL;
9644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
9654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->free_me &= ~PNG_FREE_TRNS;
9664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   inflateEnd(&png_ptr->zstream);
9694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
9714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->save_buffer);
9724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->save_buffer = NULL;
9734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \
9764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
9774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->unknown_chunk.data);
9784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->unknown_chunk.data = NULL;
9794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
9824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free(png_ptr, png_ptr->chunk_list);
9834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->chunk_list = NULL;
9844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
9854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
9874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * callbacks are still set at this point.  They are required to complete the
9884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * destruction of the png_struct itself.
9894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
9904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
9914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Free all memory used by the read */
9934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
9944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
9954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    png_infopp end_info_ptr_ptr)
9964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
9974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = NULL;
9984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_debug(1, "in png_destroy_read_struct");
10004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr_ptr != NULL)
10024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr = *png_ptr_ptr;
10034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL)
10054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
10064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* libpng 1.6.0: use the API to destroy info structs to ensure consistent
10084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * behavior.  Prior to 1.6.0 libpng did extra 'info' destruction in this API.
10094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * The extra was, apparently, unnecessary yet this hides memory leak bugs.
10104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
10124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_destroy_info_struct(png_ptr, info_ptr_ptr);
10134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   *png_ptr_ptr = NULL;
10154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_destroy(png_ptr);
10164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_destroy_png_struct(png_ptr);
10174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
10184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
10204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
10214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
10224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL)
10234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
10244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_ptr->read_row_fn = read_row_fn;
10264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
10274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
10304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_INFO_IMAGE_SUPPORTED
10314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid PNGAPI
10324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_read_png(png_structrp png_ptr, png_inforp info_ptr,
10334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           int transforms,
10344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           voidp params)
10354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
10364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr == NULL || info_ptr == NULL)
10374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
10384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* png_read_info() gives us all of the information from the
10404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * PNG file before the first IDAT (image data chunk).
10414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_info(png_ptr, info_ptr);
10434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
10444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "Image is too high to process with png_read_png()");
10454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* -------------- image transformations start here ------------------- */
10474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
10484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * is not implemented.  This will only happen in de-configured (non-default)
10494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * libpng builds.  The results can be unexpected - png_read_png may return
10504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * short or mal-formed rows because the transform is skipped.
10514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
10544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_SCALE_16) != 0)
10564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Added at libpng-1.5.4. "strip_16" produces the same result that it
10574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * did in earlier versions, while "scale_16" is now more accurate.
10584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
10594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
10604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_scale_16(png_ptr);
10614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
10624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
10634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
10644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* If both SCALE and STRIP are required pngrtran will effectively cancel the
10664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * latter by doing SCALE first.  This is ok and allows apps not to check for
10674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * which is supported to get the right answer.
10684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_STRIP_16) != 0)
10704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
10714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_strip_16(png_ptr);
10724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
10734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
10744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
10754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Strip alpha bytes from the input data without combining with
10774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * the background (not recommended).
10784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0)
10804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
10814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_strip_alpha(png_ptr);
10824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
10834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
10844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
10854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
10874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * byte into separate bytes (useful for paletted and grayscale images).
10884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_PACKING) != 0)
10904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_PACK_SUPPORTED
10914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_packing(png_ptr);
10924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
10934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
10944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
10954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
10964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Change the order of packed pixels to least significant bit first
10974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * (not useful if you are using png_set_packing).
10984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
10994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
11004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_PACKSWAP_SUPPORTED
11014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_packswap(png_ptr);
11024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
11044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Expand paletted colors into true RGB triplets
11074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
11084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * Expand paletted or RGB images with transparency to full alpha
11094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * channels so the data will be available as RGBA quartets.
11104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
11114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_EXPAND) != 0)
11124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_EXPAND_SUPPORTED
11134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_expand(png_ptr);
11144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
11164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* We don't handle background color or gamma transformation or quantizing.
11194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
11204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Invert monochrome files to have 0 as white and 1 as black
11224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
11234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
11244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_INVERT_SUPPORTED
11254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_invert_mono(png_ptr);
11264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
11284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* If you want to shift the pixel values from the range [0,255] or
11314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * [0,65535] to the original [0,7] or [0,31], or whatever range the
11324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * colors were originally in:
11334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
11344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
11354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_SHIFT_SUPPORTED
11364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
11374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_set_shift(png_ptr, &info_ptr->sig_bit);
11384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
11404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
11434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_BGR) != 0)
11444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_BGR_SUPPORTED
11454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_bgr(png_ptr);
11464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
11484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
11514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
11524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
11534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_swap_alpha(png_ptr);
11544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
11564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Swap bytes of 16-bit files to least significant byte first */
11594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
11604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_SWAP_SUPPORTED
11614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_swap(png_ptr);
11624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
11644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Added at libpng-1.2.41 */
11674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Invert the alpha channel from opacity to transparency */
11684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
11694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
11704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_invert_alpha(png_ptr);
11714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
11734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Added at libpng-1.2.41 */
11764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Expand grayscale image to RGB */
11774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0)
11784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
11794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_gray_to_rgb(png_ptr);
11804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
11824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Added at libpng-1.5.4 */
11854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0)
11864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_READ_EXPAND_16_SUPPORTED
11874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_expand_16(png_ptr);
11884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
11894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
11904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
11914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* We don't handle adding filler bytes */
11934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* We use png_read_image and rely on that for interlace handling, but we also
11954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * call png_read_update_info therefore must turn on interlace handling now:
11964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
11974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   (void)png_set_interlace_handling(png_ptr);
11984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Optional call to gamma correct and add the background to the palette
12004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * and update info structure.  REQUIRED if you are expecting libpng to
12014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * update the palette for you (i.e., you selected such a transform above).
12024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
12034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_update_info(png_ptr, info_ptr);
12044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* -------------- image transformations end here ------------------- */
12064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
12084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (info_ptr->row_pointers == NULL)
12094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
12104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 iptr;
12114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
12134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          info_ptr->height * (sizeof (png_bytep))));
12144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (iptr=0; iptr<info_ptr->height; iptr++)
12164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         info_ptr->row_pointers[iptr] = NULL;
12174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      info_ptr->free_me |= PNG_FREE_ROWS;
12194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (iptr = 0; iptr < info_ptr->height; iptr++)
12214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
12224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             png_malloc(png_ptr, info_ptr->rowbytes));
12234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
12244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_image(png_ptr, info_ptr->row_pointers);
12264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   info_ptr->valid |= PNG_INFO_IDAT;
12274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
12294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_end(png_ptr, info_ptr);
12304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   PNG_UNUSED(params)
12324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
12334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* INFO_IMAGE */
12344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SEQUENTIAL_READ */
12354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
12374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* SIMPLIFIED READ
12384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
12394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * This code currently relies on the sequential reader, though it could easily
12404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * be made to work with the progressive one.
12414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
12424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Arguments to png_image_finish_read: */
12434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Encoding of PNG data (used by the color-map code) */
12454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define P_NOTSET  0 /* File encoding not yet known */
12464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define P_sRGB    1 /* 8-bit encoded to sRGB gamma */
12474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define P_LINEAR  2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
12484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define P_FILE    3 /* 8-bit encoded to file gamma, not sRGB or linear */
12494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define P_LINEAR8 4 /* 8-bit linear: only from a file value */
12504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Color-map processing: after libpng has run on the PNG image further
12524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * processing may be needed to convert the data to color-map indices.
12534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
12544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_NONE      0
12554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_GA        1 /* Process GA data to a color-map with alpha */
12564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_TRANS     2 /* Process GA data to a background index */
12574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_RGB       3 /* Process RGB data */
12584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */
12594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* The following document where the background is for each processing case. */
12614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_NONE_BACKGROUND      256
12624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_GA_BACKGROUND        231
12634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_TRANS_BACKGROUND     254
12644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_RGB_BACKGROUND       256
12654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
12664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmanntypedef struct
12684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
12694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Arguments: */
12704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image;
12714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_voidp  buffer;
12724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_int_32 row_stride;
12734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_voidp  colormap;
12744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_const_colorp background;
12754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Local variables: */
12764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_voidp       local_row;
12774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_voidp       first_row;
12784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   ptrdiff_t       row_bytes;           /* step between rows */
12794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int             file_encoding;       /* E_ values above */
12804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_fixed_point gamma_to_linear;     /* For P_FILE, reciprocal of gamma */
12814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int             colormap_processing; /* PNG_CMAP_ values above */
12824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} png_image_read_control;
12834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Do all the *safe* initialization - 'safe' means that png_error won't be
12854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * called, so setting up the jmp_buf is not required.  This means that anything
12864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * called from here must *not* call png_malloc - it has to call png_malloc_warn
12874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * instead so that control is returned safely back to this routine.
12884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
12894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
12904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_init(png_imagep image)
12914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
12924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (image->opaque == NULL)
12934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
12944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
12954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          png_safe_error, png_safe_warning);
12964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* And set the rest of the structure to NULL to ensure that the various
12984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * fields are consistent.
12994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
13004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      memset(image, 0, (sizeof *image));
13014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      image->version = PNG_IMAGE_VERSION;
13024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (png_ptr != NULL)
13044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
13054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_infop info_ptr = png_create_info_struct(png_ptr);
13064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (info_ptr != NULL)
13084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
13094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_controlp control = png_voidcast(png_controlp,
13104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_malloc_warn(png_ptr, (sizeof *control)));
13114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (control != NULL)
13134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
13144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               memset(control, 0, (sizeof *control));
13154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               control->png_ptr = png_ptr;
13174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               control->info_ptr = info_ptr;
13184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               control->for_write = 0;
13194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               image->opaque = control;
13214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return 1;
13224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
13234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Error clean up */
13254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_destroy_info_struct(png_ptr, &info_ptr);
13264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
13274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_destroy_read_struct(&png_ptr, NULL, NULL);
13294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
13304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return png_image_error(image, "png_image_read: out of memory");
13324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
13334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return png_image_error(image, "png_image_read: opaque pointer not NULL");
13354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
13364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Utility to find the base format of a PNG file from a png_struct. */
13384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic png_uint_32
13394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_format(png_structrp png_ptr)
13404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
13414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 format = 0;
13424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
13444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      format |= PNG_FORMAT_FLAG_COLOR;
13454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
13474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      format |= PNG_FORMAT_FLAG_ALPHA;
13484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS
13504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * sets the png_struct fields; that's all we are interested in here.  The
13514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * precise interaction with an app call to png_set_tRNS and PNG file reading
13524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * is unclear.
13534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
13544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (png_ptr->num_trans > 0)
13554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      format |= PNG_FORMAT_FLAG_ALPHA;
13564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr->bit_depth == 16)
13584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      format |= PNG_FORMAT_FLAG_LINEAR;
13594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0)
13614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      format |= PNG_FORMAT_FLAG_COLORMAP;
13624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return format;
13644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
13654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Is the given gamma significantly different from sRGB?  The test is the same
13674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * one used in pngrtran.c when deciding whether to do gamma correction.  The
13684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * arithmetic optimizes the division by using the fact that the inverse of the
13694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * file sRGB gamma is 2.2
13704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
13714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
13724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_gamma_not_sRGB(png_fixed_point g)
13734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
13744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (g < PNG_FP_1)
13754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
13764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
13774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (g == 0)
13784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         return 0;
13794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
13814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
13824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 1;
13844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
13854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Do the main body of a 'png_image_begin_read' function; read the PNG file
13874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * header and fill in all the information.  This is executed in a safe context,
13884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * unlike the init routine above.
13894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
13904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
13914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_header(png_voidp argument)
13924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
13934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = png_voidcast(png_imagep, argument);
13944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = image->opaque->png_ptr;
13954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_inforp info_ptr = image->opaque->info_ptr;
13964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
13974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_set_benign_errors(png_ptr, 1/*warn*/);
13984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_info(png_ptr, info_ptr);
13994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Do this the fast way; just read directly out of png_struct. */
14014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   image->width = png_ptr->width;
14024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   image->height = png_ptr->height;
14034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
14054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 format = png_image_format(png_ptr);
14064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      image->format = format;
14084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_COLORSPACE_SUPPORTED
14104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Does the colorspace match sRGB?  If there is no color endpoint
14114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * (colorant) information assume yes, otherwise require the
14124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set.  If the
14134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * colorspace has been determined to be invalid ignore it.
14144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
14154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
14164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
14174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
14184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
14194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
14204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
14214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* We need the maximum number of entries regardless of the format the
14234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * application sets here.
14244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
14254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
14264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 cmap_entries;
14274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      switch (png_ptr->color_type)
14294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
14304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case PNG_COLOR_TYPE_GRAY:
14314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = 1U << png_ptr->bit_depth;
14324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
14334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         case PNG_COLOR_TYPE_PALETTE:
14354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = png_ptr->num_palette;
14364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
14374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         default:
14394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = 256;
14404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
14414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
14424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (cmap_entries > 256)
14444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         cmap_entries = 256;
14454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      image->colormap_entries = cmap_entries;
14474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
14484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 1;
14504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
14514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_STDIO_SUPPORTED
14534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannint PNGAPI
14544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_begin_read_from_stdio(png_imagep image, FILE* file)
14554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
14564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (image != NULL && image->version == PNG_IMAGE_VERSION)
14574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
14584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (file != NULL)
14594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
14604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_image_read_init(image) != 0)
14614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
14624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* This is slightly evil, but png_init_io doesn't do anything other
14634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * than this and we haven't changed the standard IO functions so
14644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * this saves a 'safe' function.
14654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
14664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->opaque->png_ptr->io_ptr = file;
14674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            return png_safe_execute(image, png_image_read_header, image);
14684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
14694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
14704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
14724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         return png_image_error(image,
14734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "png_image_begin_read_from_stdio: invalid argument");
14744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
14754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (image != NULL)
14774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return png_image_error(image,
14784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
14794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 0;
14814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
14824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannint PNGAPI
14844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_begin_read_from_file(png_imagep image, const char *file_name)
14854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
14864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (image != NULL && image->version == PNG_IMAGE_VERSION)
14874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
14884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (file_name != NULL)
14894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
14904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         FILE *fp = fopen(file_name, "rb");
14914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
14924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (fp != NULL)
14934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
14944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_image_read_init(image) != 0)
14954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
14964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               image->opaque->png_ptr->io_ptr = fp;
14974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               image->opaque->owned_file = 1;
14984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return png_safe_execute(image, png_image_read_header, image);
14994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
15004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Clean up: just the opened file. */
15024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            (void)fclose(fp);
15034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
15044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
15064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            return png_image_error(image, strerror(errno));
15074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
15084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
15104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         return png_image_error(image,
15114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "png_image_begin_read_from_file: invalid argument");
15124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
15134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (image != NULL)
15154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return png_image_error(image,
15164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
15174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 0;
15194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
15204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* STDIO */
15214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void PNGCBAPI
15234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
15244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
15254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_ptr != NULL)
15264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
15274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
15284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (image != NULL)
15294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
15304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_controlp cp = image->opaque;
15314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (cp != NULL)
15324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
15334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_const_bytep memory = cp->memory;
15344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_size_t size = cp->size;
15354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (memory != NULL && size >= need)
15374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
15384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               memcpy(out, memory, need);
15394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cp->memory = memory + need;
15404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cp->size = size - need;
15414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return;
15424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
15434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_error(png_ptr, "read beyond end of data");
15454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
15464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
15474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "invalid memory read");
15494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
15504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
15514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannint PNGAPI png_image_begin_read_from_memory(png_imagep image,
15534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_const_voidp memory, png_size_t size)
15544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
15554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (image != NULL && image->version == PNG_IMAGE_VERSION)
15564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
15574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (memory != NULL && size > 0)
15584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
15594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_image_read_init(image) != 0)
15604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
15614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Now set the IO functions to read from the memory buffer and
15624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * store it into io_ptr.  Again do this in-place to avoid calling a
15634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * libpng function that requires error handling.
15644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
15654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->opaque->memory = png_voidcast(png_const_bytep, memory);
15664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->opaque->size = size;
15674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->opaque->png_ptr->io_ptr = image;
15684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->opaque->png_ptr->read_data_fn = png_image_memory_read;
15694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            return png_safe_execute(image, png_image_read_header, image);
15714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
15724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
15734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
15754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         return png_image_error(image,
15764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "png_image_begin_read_from_memory: invalid argument");
15774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
15784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (image != NULL)
15804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return png_image_error(image,
15814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
15824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 0;
15844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
15854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
15864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Utility function to skip chunks that are not used by the simplified image
15874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * read functions and an appropriate macro to call it.
15884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
15894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
15904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void
15914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_skip_unused_chunks(png_structrp png_ptr)
15924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
15934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Prepare the reader to ignore all recognized chunks whose data will not
15944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * be used, i.e., all chunks recognized by libpng except for those
15954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * involved in basic image reading:
15964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
15974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    IHDR, PLTE, IDAT, IEND
15984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
15994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * Or image data handling:
16004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
16014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
16024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
16034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * This provides a small performance improvement and eliminates any
16044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * potential vulnerability to security problems in the unused chunks.
16054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
16064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
16074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * too.  This allows the simplified API to be compiled without iCCP support,
16084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * however if the support is there the chunk is still checked to detect
16094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * errors (which are unfortunately quite common.)
16104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
16114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
16124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         static PNG_CONST png_byte chunks_to_process[] = {
16134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            98,  75,  71,  68, '\0',  /* bKGD */
16144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            99,  72,  82,  77, '\0',  /* cHRM */
16154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann           103,  65,  77,  65, '\0',  /* gAMA */
16164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        ifdef PNG_READ_iCCP_SUPPORTED
16174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann           105,  67,  67,  80, '\0',  /* iCCP */
16184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        endif
16194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann           115,  66,  73,  84, '\0',  /* sBIT */
16204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann           115,  82,  71,  66, '\0',  /* sRGB */
16214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann           };
16224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       /* Ignore unknown chunks and all other chunks except for the
16244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
16254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        */
16264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
16274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         NULL, -1);
16284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       /* But do not ignore image data handling chunks */
16304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
16314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);
16324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
16334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
16344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
16364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
16374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#  define PNG_SKIP_CHUNKS(p) ((void)0)
16384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* HANDLE_AS_UNKNOWN */
16394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* The following macro gives the exact rounded answer for all values in the
16414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * range 0..255 (it actually divides by 51.2, but the rounding still generates
16424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * the correct numbers 0..5
16434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
16444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
16454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Utility functions to make particular color-maps */
16474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void
16484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannset_file_encoding(png_image_read_control *display)
16494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
16504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
16514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_gamma_significant(g) != 0)
16524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
16534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (png_gamma_not_sRGB(g) != 0)
16544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
16554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         display->file_encoding = P_FILE;
16564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         display->gamma_to_linear = png_reciprocal(g);
16574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
16584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
16604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         display->file_encoding = P_sRGB;
16614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
16624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else
16644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->file_encoding = P_LINEAR8;
16654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
16664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic unsigned int
16684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmanndecode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
16694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
16704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding == P_FILE) /* double check */
16714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      encoding = display->file_encoding;
16724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding == P_NOTSET) /* must be the file encoding */
16744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
16754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      set_file_encoding(display);
16764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      encoding = display->file_encoding;
16774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
16784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (encoding)
16804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
16814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case P_FILE:
16824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
16834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
16844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case P_sRGB:
16864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         value = png_sRGB_table[value];
16874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
16884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case P_LINEAR:
16904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
16914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case P_LINEAR8:
16934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         value *= 257;
16944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
16954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
16964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef __GNUC__
16974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
16984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(display->image->opaque->png_ptr,
16994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "unexpected encoding (internal error)");
17004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
17014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
17024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return value;
17044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
17054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic png_uint_32
17074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_colormap_compose(png_image_read_control *display,
17084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
17094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 background, int encoding)
17104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
17114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* The file value is composed on the background, the background has the given
17124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * encoding and so does the result, the file is encoded with P_FILE and the
17134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * file and alpha are 8-bit values.  The (output) encoding will always be
17144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * P_LINEAR or P_sRGB.
17154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
17164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
17174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 b = decode_gamma(display, background, encoding);
17184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* The alpha is always an 8-bit value (it comes from the palette), the value
17204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.
17214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
17224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   f = f * alpha + b * (255-alpha);
17234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding == P_LINEAR)
17254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
17264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Scale to 65535; divide by 255, approximately (in fact this is extremely
17274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * accurate, it divides by 255.00000005937181414556, with no overflow.)
17284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
17294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      f *= 257; /* Now scaled by 65535 */
17304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      f += f >> 16;
17314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      f = (f+32768) >> 16;
17324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
17334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else /* P_sRGB */
17354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      f = PNG_sRGB_FROM_LINEAR(f);
17364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return f;
17384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
17394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
17414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * be 8-bit.
17424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
17434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void
17444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_create_colormap_entry(png_image_read_control *display,
17454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
17464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 alpha, int encoding)
17474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
17484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = display->image;
17494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
17504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      P_LINEAR : P_sRGB;
17514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
17524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (red != green || green != blue);
17534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (ip > 255)
17554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(image->opaque->png_ptr, "color-map index out of range");
17564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Update the cache with whether the file gamma is significantly different
17584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * from sRGB.
17594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
17604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding == P_FILE)
17614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
17624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (display->file_encoding == P_NOTSET)
17634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         set_file_encoding(display);
17644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Note that the cached value may be P_FILE too, but if it is then the
17664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * gamma_to_linear member has been set.
17674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
17684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      encoding = display->file_encoding;
17694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
17704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding == P_FILE)
17724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
17734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_fixed_point g = display->gamma_to_linear;
17744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      red = png_gamma_16bit_correct(red*257, g);
17764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      green = png_gamma_16bit_correct(green*257, g);
17774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      blue = png_gamma_16bit_correct(blue*257, g);
17784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (convert_to_Y != 0 || output_encoding == P_LINEAR)
17804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
17814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         alpha *= 257;
17824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         encoding = P_LINEAR;
17834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
17844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
17864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
17874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         red = PNG_sRGB_FROM_LINEAR(red * 255);
17884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         green = PNG_sRGB_FROM_LINEAR(green * 255);
17894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         blue = PNG_sRGB_FROM_LINEAR(blue * 255);
17904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         encoding = P_sRGB;
17914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
17924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
17934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
17944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (encoding == P_LINEAR8)
17954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
17964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* This encoding occurs quite frequently in test cases because PngSuite
17974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * includes a gAMA 1.0 chunk with most images.
17984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
17994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      red *= 257;
18004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      green *= 257;
18014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      blue *= 257;
18024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      alpha *= 257;
18034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      encoding = P_LINEAR;
18044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
18054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (encoding == P_sRGB &&
18074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       (convert_to_Y  != 0 || output_encoding == P_LINEAR))
18084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
18094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* The values are 8-bit sRGB values, but must be converted to 16-bit
18104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * linear.
18114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
18124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      red = png_sRGB_table[red];
18134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      green = png_sRGB_table[green];
18144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      blue = png_sRGB_table[blue];
18154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      alpha *= 257;
18164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      encoding = P_LINEAR;
18174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
18184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* This is set if the color isn't gray but the output is. */
18204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding == P_LINEAR)
18214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
18224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (convert_to_Y != 0)
18234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
18244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* NOTE: these values are copied from png_do_rgb_to_gray */
18254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32 y = (png_uint_32)6968 * red  + (png_uint_32)23434 * green +
18264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            (png_uint_32)2366 * blue;
18274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (output_encoding == P_LINEAR)
18294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = (y + 16384) >> 15;
18304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
18324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
18334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* y is scaled by 32768, we need it scaled by 255: */
18344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = (y + 128) >> 8;
18354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y *= 255;
18364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
18374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            alpha = PNG_DIV257(alpha);
18384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            encoding = P_sRGB;
18394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
18404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         blue = red = green = y;
18424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
18434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (output_encoding == P_sRGB)
18454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
18464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         red = PNG_sRGB_FROM_LINEAR(red * 255);
18474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         green = PNG_sRGB_FROM_LINEAR(green * 255);
18484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         blue = PNG_sRGB_FROM_LINEAR(blue * 255);
18494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         alpha = PNG_DIV257(alpha);
18504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         encoding = P_sRGB;
18514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
18524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
18534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (encoding != output_encoding)
18554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(image->opaque->png_ptr, "bad encoding (internal error)");
18564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Store the value. */
18584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
18594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
18604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
18614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
18624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     else
18634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        define afirst 0
18644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
18654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef PNG_FORMAT_BGR_SUPPORTED
18664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
18674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     else
18684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        define bgr 0
18694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
18704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (output_encoding == P_LINEAR)
18724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
18734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
18744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
18764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* The linear 16-bit values must be pre-multiplied by the alpha channel
18784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * value, if less than 65535 (this is, effectively, composite on black
18794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * if the alpha channel is removed.)
18804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
18814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
18824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
18834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 4:
18844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst ? 0 : 3] = (png_uint_16)alpha;
18854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* FALL THROUGH */
18864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 3:
18884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (alpha < 65535)
18894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
18904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (alpha > 0)
18914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
18924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     blue = (blue * alpha + 32767U)/65535U;
18934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     green = (green * alpha + 32767U)/65535U;
18944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     red = (red * alpha + 32767U)/65535U;
18954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
18964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
18974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else
18984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     red = green = blue = 0;
18994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
19004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
19014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst + 1] = (png_uint_16)green;
19024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst + bgr] = (png_uint_16)red;
19034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               break;
19044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 2:
19064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[1 ^ afirst] = (png_uint_16)alpha;
19074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* FALL THROUGH */
19084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 1:
19104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (alpha < 65535)
19114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
19124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (alpha > 0)
19134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     green = (green * alpha + 32767U)/65535U;
19144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else
19164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     green = 0;
19174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
19184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst] = (png_uint_16)green;
19194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               break;
19204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            default:
19224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               break;
19234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
19244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
19254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else /* output encoding is P_sRGB */
19274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
19284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep entry = png_voidcast(png_bytep, display->colormap);
19294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
19314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
19334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
19344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 4:
19354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst ? 0 : 3] = (png_byte)alpha;
19364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 3:
19374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst + (2 ^ bgr)] = (png_byte)blue;
19384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst + 1] = (png_byte)green;
19394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst + bgr] = (png_byte)red;
19404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               break;
19414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 2:
19434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[1 ^ afirst] = (png_byte)alpha;
19444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            case 1:
19454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               entry[afirst] = (png_byte)green;
19464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               break;
19474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            default:
19494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               break;
19504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
19514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
19524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef afirst
19544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        undef afirst
19554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
19564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef bgr
19574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#        undef bgr
19584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
19594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
19604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
19614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
19634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannmake_gray_file_colormap(png_image_read_control *display)
19644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
19654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int i;
19664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   for (i=0; i<256; ++i)
19684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
19694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return i;
19714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
19724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
19744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannmake_gray_colormap(png_image_read_control *display)
19754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
19764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int i;
19774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   for (i=0; i<256; ++i)
19794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
19804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return i;
19824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
19834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_GRAY_COLORMAP_ENTRIES 256
19844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
19864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannmake_ga_colormap(png_image_read_control *display)
19874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
19884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int i, a;
19894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
19904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Alpha is retained, the output will be a color-map with entries
19914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * selected by six levels of alpha.  One transparent entry, 6 gray
19924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * levels for all the intermediate alpha values, leaving 230 entries
19934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * for the opaque grays.  The color-map entries are the six values
19944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the
19954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * relevant entry.
19964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
19974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * if (alpha > 229) // opaque
19984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * {
19994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    // The 231 entries are selected to make the math below work:
20004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    base = 0;
20014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    entry = (231 * gray + 128) >> 8;
20024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * }
20034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * else if (alpha < 26) // transparent
20044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * {
20054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    base = 231;
20064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    entry = 0;
20074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * }
20084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * else // partially opaque
20094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * {
20104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    base = 226 + 6 * PNG_DIV51(alpha);
20114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *    entry = PNG_DIV51(gray);
20124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * }
20134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
20144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   i = 0;
20154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   while (i < 231)
20164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
20174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      unsigned int gray = (i * 256 + 115) / 231;
20184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
20194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
20204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* 255 is used here for the component values for consistency with the code
20224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * that undoes premultiplication in pngwrite.c.
20234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
20244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
20254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   for (a=1; a<5; ++a)
20274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
20284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      unsigned int g;
20294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (g=0; g<6; ++g)
20314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
20324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            P_sRGB);
20334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
20344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return i;
20364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
20374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_GA_COLORMAP_ENTRIES 256
20394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
20414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannmake_rgb_colormap(png_image_read_control *display)
20424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
20434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int i, r;
20444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Build a 6x6x6 opaque RGB cube */
20464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   for (i=r=0; r<6; ++r)
20474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
20484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      unsigned int g;
20494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (g=0; g<6; ++g)
20514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
20524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         unsigned int b;
20534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         for (b=0; b<6; ++b)
20554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
20564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               P_sRGB);
20574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
20584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
20594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return i;
20614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
20624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_RGB_COLORMAP_ENTRIES 216
20644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Return a palette index to the above palette given three 8-bit sRGB values. */
20664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define PNG_RGB_INDEX(r,g,b) \
20674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
20684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
20704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_colormap(png_voidp argument)
20714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
20724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_image_read_control *display =
20734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_voidcast(png_image_read_control*, argument);
20744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   const png_imagep image = display->image;
20754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   const png_structrp png_ptr = image->opaque->png_ptr;
20774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   const png_uint_32 output_format = image->format;
20784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
20794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      P_LINEAR : P_sRGB;
20804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int cmap_entries;
20824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int output_processing;        /* Output processing option */
20834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
20844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Background information; the background color and the index of this color
20864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * in the color-map if it exists (else 256).
20874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
20884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   unsigned int background_index = 256;
20894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 back_r, back_g, back_b;
20904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Flags to accumulate things that need to be done to the input. */
20924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int expand_tRNS = 0;
20934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is
20954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * very difficult to do, the results look awful, and it is difficult to see
20964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * what possible use it is because the application can't control the
20974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * color-map.
20984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
20994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
21004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->num_trans > 0) /* alpha in input */ &&
21014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
21024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
21034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (output_encoding == P_LINEAR) /* compose on black */
21044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         back_b = back_g = back_r = 0;
21054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (display->background == NULL /* no way to remove it */)
21074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr,
21084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "a background color must be supplied to remove alpha/transparency");
21094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Get a copy of the background color (this avoids repeating the checks
21114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * below.)  The encoding is 8-bit sRGB or 16-bit linear, depending on the
21124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * output format.
21134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
21144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
21154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
21164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         back_g = display->background->green;
21174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0)
21184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
21194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            back_r = display->background->red;
21204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            back_b = display->background->blue;
21214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
21224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
21234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            back_b = back_r = back_g;
21244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
21254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
21264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (output_encoding == P_LINEAR)
21284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      back_b = back_r = back_g = 65535;
21294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else
21314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      back_b = back_r = back_g = 255;
21324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Default the input file gamma if required - this is necessary because
21344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * libpng assumes that if no gamma information is present the data is in the
21354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * output format, but the simplified API deduces the gamma from the input
21364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * format.
21374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
21384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
21394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
21404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Do this directly, not using the png_colorspace functions, to ensure
21414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * that it happens even if the colorspace is invalid (though probably if
21424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * it is the setting will be ignored)  Note that the same thing can be
21434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * achieved at the application interface with png_set_gAMA.
21444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
21454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (png_ptr->bit_depth == 16 &&
21464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
21474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
21484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
21504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
21514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
21534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
21544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Decide what to do based on the PNG color type of the input data.  The
21564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * utility function png_create_colormap_entry deals with most aspects of the
21574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * output transformations; this code works out how to produce bytes of
21584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * color-map entries from the original format.
21594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
21604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (png_ptr->color_type)
21614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
21624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_COLOR_TYPE_GRAY:
21634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_ptr->bit_depth <= 8)
21644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
21654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* There at most 256 colors in the output, regardless of
21664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * transparency.
21674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
21684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;
21694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = 1U << png_ptr->bit_depth;
21714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (cmap_entries > image->colormap_entries)
21724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_error(png_ptr, "gray[8] color-map: too few entries");
21734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            step = 255 / (cmap_entries - 1);
21754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            output_processing = PNG_CMAP_NONE;
21764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* If there is a tRNS chunk then this either selects a transparent
21784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * value or, if the output has no alpha, the background color.
21794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
21804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_ptr->num_trans > 0)
21814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
21824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               trans = png_ptr->trans_color.gray;
21834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
21854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
21864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
21874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
21884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* png_create_colormap_entry just takes an RGBA and writes the
21894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * corresponding color-map entry using the format from 'image',
21904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * including the required conversion to sRGB or linear as
21914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * appropriate.  The input values are always either sRGB (if the
21924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * gamma correction flag is 0) or 0..255 scaled file encoded values
21934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * (if the function must gamma correct them).
21944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
21954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            for (i=val=0; i<cmap_entries; ++i, val += step)
21964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
21974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* 'i' is a file value.  While this will result in duplicated
21984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * entries for 8-bit non-sRGB encoded files it is necessary to
21994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * have non-gamma corrected values to do tRNS handling.
22004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
22014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (i != trans)
22024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, i, val, val, val, 255,
22034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     P_FILE/*8-bit with file gamma*/);
22044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Else this entry is transparent.  The colors don't matter if
22064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * there is an alpha channel (back_alpha == 0), but it does no
22074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * harm to pass them in; the values are not set above so this
22084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * passes in white.
22094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                *
22104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * NOTE: this preserves the full precision of the application
22114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * supplied background color when it is used.
22124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
22134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
22144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, i, back_r, back_g, back_b,
22154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     back_alpha, output_encoding);
22164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
22174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* We need libpng to preserve the original encoding. */
22194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            data_encoding = P_FILE;
22204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The rows from libpng, while technically gray values, are now also
22224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * color-map indices; however, they may need to be expanded to 1
22234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * byte per pixel.  This is what png_set_packing does (i.e., it
22244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * unpacks the bit values into bytes.)
22254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
22264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_ptr->bit_depth < 8)
22274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_set_packing(png_ptr);
22284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
22294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else /* bit depth is 16 */
22314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
22324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The 16-bit input values can be converted directly to 8-bit gamma
22334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * encoded values; however, if a tRNS chunk is present 257 color-map
22344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * entries are required.  This means that the extra entry requires
22354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * special processing; add an alpha channel, sacrifice gray level
22364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * 254 and convert transparent (alpha==0) entries to that.
22374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
22384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * Use libpng to chop the data to 8 bits.  Convert it to sRGB at the
22394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * same time to minimize quality loss.  If a tRNS chunk is present
22404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * this means libpng must handle it too; otherwise it is impossible
22414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * to do the exact match on the 16-bit value.
22424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
22434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * If the output has no alpha channel *and* the background color is
22444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * gray then it is possible to let libpng handle the substitution by
22454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * ensuring that the corresponding gray level matches the background
22464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * color exactly.
22474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
22484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            data_encoding = P_sRGB;
22494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
22514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_error(png_ptr, "gray[16] color-map: too few entries");
22524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = make_gray_colormap(display);
22544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_ptr->num_trans > 0)
22564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
22574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               unsigned int back_alpha;
22584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
22604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_alpha = 0;
22614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
22634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
22644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (back_r == back_g && back_g == back_b)
22654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
22664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Background is gray; no special processing will be
22674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * required.
22684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
22694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_color_16 c;
22704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_uint_32 gray = back_g;
22714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (output_encoding == P_LINEAR)
22734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
22744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        gray = PNG_sRGB_FROM_LINEAR(gray * 255);
22754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        /* And make sure the corresponding palette entry
22774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * matches.
22784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         */
22794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_create_colormap_entry(display, gray, back_g, back_g,
22804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           back_g, 65535, P_LINEAR);
22814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
22824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* The background passed to libpng, however, must be the
22844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * sRGB value.
22854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
22864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     c.index = 0; /*unused*/
22874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
22884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* NOTE: does this work without expanding tRNS to alpha?
22904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * It should be the color->gray case below apparently
22914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * doesn't.
22924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
22934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_set_background_fixed(png_ptr, &c,
22944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
22954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        0/*gamma: not used*/);
22964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
22974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     output_processing = PNG_CMAP_NONE;
22984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     break;
22994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
23004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef __COVERITY__
23014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
23024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  * here.
23034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  */
23044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_alpha = 255;
23054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
23064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
23074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
23084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
23094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* output_processing means that the libpng-processed row will be
23114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * 8-bit GA and it has to be processing to single byte color-map
23124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * values.  Entry 254 is replaced by either a completely
23134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * transparent entry or by the background color at full
23144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * precision (and the background color is not a simple gray
23154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * level in this case.)
23164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
23174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               expand_tRNS = 1;
23184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_TRANS;
23194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               background_index = 254;
23204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* And set (overwrite) color-map entry 254 to the actual
23224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * background color at full precision.
23234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
23244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_create_colormap_entry(display, 254, back_r, back_g, back_b,
23254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_alpha, output_encoding);
23264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
23274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
23294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_NONE;
23304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
23314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
23324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_COLOR_TYPE_GRAY_ALPHA:
23344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* 8-bit or 16-bit PNG with two channels - gray and alpha.  A minimum
23354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * of 65536 combinations.  If, however, the alpha channel is to be
23364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * removed there are only 256 possibilities if the background is gray.
23374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * (Otherwise there is a subset of the 65536 possibilities defined by
23384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * the triangle between black, white and the background color.)
23394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          *
23404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * Reduce 16-bit files to 8-bit and sRGB encode the result.  No need to
23414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * worry about tRNS matching - tRNS is ignored if there is an alpha
23424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * channel.
23434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
23444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         data_encoding = P_sRGB;
23454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
23474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
23484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
23494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_error(png_ptr, "gray+alpha color-map: too few entries");
23504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = make_ga_colormap(display);
23524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            background_index = PNG_CMAP_GA_BACKGROUND;
23544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            output_processing = PNG_CMAP_GA;
23554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
23564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else /* alpha is removed */
23584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
23594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Alpha must be removed as the PNG data is processed when the
23604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * background is a color because the G and A channels are
23614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * independent and the vector addition (non-parallel vectors) is a
23624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * 2-D problem.
23634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
23644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * This can be reduced to the same algorithm as above by making a
23654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * colormap containing gray levels (for the opaque grays), a
23664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * background entry (for a transparent pixel) and a set of four six
23674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * level color values, one set for each intermediate alpha value.
23684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * See the comments in make_ga_colormap for how this works in the
23694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * per-pixel processing.
23704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
23714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * If the background is gray, however, we only need a 256 entry gray
23724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * level color map.  It is sufficient to make the entry generated
23734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * for the background color be exactly the color specified.
23744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
23754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
23764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               (back_r == back_g && back_g == back_b))
23774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
23784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Background is gray; no special processing will be required. */
23794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_color_16 c;
23804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_uint_32 gray = back_g;
23814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
23834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_error(png_ptr, "gray-alpha color-map: too few entries");
23844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cmap_entries = make_gray_colormap(display);
23864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (output_encoding == P_LINEAR)
23884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
23894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  gray = PNG_sRGB_FROM_LINEAR(gray * 255);
23904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* And make sure the corresponding palette entry matches. */
23924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, gray, back_g, back_g,
23934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     back_g, 65535, P_LINEAR);
23944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
23954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
23964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* The background passed to libpng, however, must be the sRGB
23974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * value.
23984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
23994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.index = 0; /*unused*/
24004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
24014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_set_background_fixed(png_ptr, &c,
24034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
24044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  0/*gamma: not used*/);
24054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_NONE;
24074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
24084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
24104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
24114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_uint_32 i, a;
24124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* This is the same as png_make_ga_colormap, above, except that
24144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * the entries are all opaque.
24154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
24164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
24174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_error(png_ptr, "ga-alpha color-map: too few entries");
24184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               i = 0;
24204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               while (i < 231)
24214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
24224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 gray = (i * 256 + 115) / 231;
24234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, i++, gray, gray, gray,
24244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     255, P_sRGB);
24254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
24264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* NOTE: this preserves the full precision of the application
24284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * background color.
24294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
24304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               background_index = i;
24314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_create_colormap_entry(display, i++, back_r, back_g, back_b,
24324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef __COVERITY__
24334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
24344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  * here.
24354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  */ 255U,
24364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
24374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  output_encoding == P_LINEAR ? 65535U : 255U,
24384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
24394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  output_encoding);
24404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* For non-opaque input composite on the sRGB background - this
24424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * requires inverting the encoding for each component.  The input
24434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * is still converted to the sRGB encoding because this is a
24444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * reasonable approximate to the logarithmic curve of human
24454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * visual sensitivity, at least over the narrow range which PNG
24464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * represents.  Consequently 'G' is always sRGB encoded, while
24474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * 'A' is linear.  We need the linear background colors.
24484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
24494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (output_encoding == P_sRGB) /* else already linear */
24504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
24514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* This may produce a value not exactly matching the
24524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * background, but that's ok because these numbers are only
24534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * used when alpha != 0
24544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
24554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_r = png_sRGB_table[back_r];
24564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_g = png_sRGB_table[back_g];
24574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  back_b = png_sRGB_table[back_b];
24584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
24594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               for (a=1; a<5; ++a)
24614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
24624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  unsigned int g;
24634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled
24654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * by an 8-bit alpha value (0..255).
24664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
24674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 alpha = 51 * a;
24684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 back_rx = (255-alpha) * back_r;
24694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 back_gx = (255-alpha) * back_g;
24704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 back_bx = (255-alpha) * back_b;
24714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (g=0; g<6; ++g)
24734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
24744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_uint_32 gray = png_sRGB_table[g*51] * alpha;
24754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_create_colormap_entry(display, i++,
24774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        PNG_sRGB_FROM_LINEAR(gray + back_rx),
24784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        PNG_sRGB_FROM_LINEAR(gray + back_gx),
24794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
24804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
24814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
24824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cmap_entries = i;
24844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_GA;
24854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
24864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
24874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
24884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
24894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_COLOR_TYPE_RGB:
24904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_COLOR_TYPE_RGB_ALPHA:
24914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Exclude the case where the output is gray; we can always handle this
24924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * with the cases above.
24934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
24944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
24954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
24964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The color-map will be grayscale, so we may as well convert the
24974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * input RGB values to a simple grayscale and use the grayscale
24984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * code above.
24994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
25004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * NOTE: calling this apparently damages the recognition of the
25014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * transparent color in background color handling; call
25024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * png_set_tRNS_to_alpha before png_set_background_fixed.
25034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
25044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
25054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               -1);
25064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            data_encoding = P_sRGB;
25074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The output will now be one or two 8-bit gray or gray+alpha
25094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * channels.  The more complex case arises when the input has alpha.
25104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
25114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
25124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_ptr->num_trans > 0) &&
25134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
25144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
25154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Both input and output have an alpha channel, so no background
25164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * processing is required; just map the GA bytes to the right
25174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * color-map entry.
25184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
25194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               expand_tRNS = 1;
25204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
25224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_error(png_ptr, "rgb[ga] color-map: too few entries");
25234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cmap_entries = make_ga_colormap(display);
25254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               background_index = PNG_CMAP_GA_BACKGROUND;
25264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_GA;
25274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
25284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
25304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
25314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Either the input or the output has no alpha channel, so there
25324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * will be no non-opaque pixels in the color-map; it will just be
25334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * grayscale.
25344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
25354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
25364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_error(png_ptr, "rgb[gray] color-map: too few entries");
25374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Ideally this code would use libpng to do the gamma correction,
25394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * but if an input alpha channel is to be removed we will hit the
25404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * libpng bug in gamma+compose+rgb-to-gray (the double gamma
25414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * correction bug).  Fix this by dropping the gamma correction in
25424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * this case and doing it in the palette; this will result in
25434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * duplicate palette entries, but that's better than the
25444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * alternative of double gamma correction.
25454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
25464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
25474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_ptr->num_trans > 0) &&
25484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
25494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
25504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  cmap_entries = make_gray_file_colormap(display);
25514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  data_encoding = P_FILE;
25524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
25534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
25554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  cmap_entries = make_gray_colormap(display);
25564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* But if the input has alpha or transparency it must be removed
25584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
25594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
25604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_ptr->num_trans > 0)
25614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
25624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_color_16 c;
25634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 gray = back_g;
25644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* We need to ensure that the application background exists in
25664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * the colormap and that completely transparent pixels map to
25674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * it.  Achieve this simply by ensuring that the entry
25684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * selected for the background really is the background color.
25694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
25704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (data_encoding == P_FILE) /* from the fixup above */
25714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
25724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* The app supplied a gray which is in output_encoding, we
25734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * need to convert it to a value of the input (P_FILE)
25744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * encoding then set this palette entry to the required
25754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * output encoding.
25764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
25774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (output_encoding == P_sRGB)
25784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        gray = png_sRGB_table[gray]; /* now P_LINEAR */
25794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     gray = PNG_DIV257(png_gamma_16bit_correct(gray,
25814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_ptr->colorspace.gamma)); /* now P_FILE */
25824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* And make sure the corresponding palette entry contains
25844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * exactly the required sRGB value.
25854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
25864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_create_colormap_entry(display, gray, back_g, back_g,
25874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        back_g, 0/*unused*/, output_encoding);
25884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
25894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else if (output_encoding == P_LINEAR)
25914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
25924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     gray = PNG_sRGB_FROM_LINEAR(gray * 255);
25934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
25944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* And make sure the corresponding palette entry matches.
25954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
25964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_create_colormap_entry(display, gray, back_g, back_g,
25974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        back_g, 0/*unused*/, P_LINEAR);
25984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
25994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* The background passed to libpng, however, must be the
26014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * output (normally sRGB) value.
26024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
26034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  c.index = 0; /*unused*/
26044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
26054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* NOTE: the following is apparently a bug in libpng. Without
26074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * it the transparent color recognition in
26084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * png_set_background_fixed seems to go wrong.
26094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
26104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  expand_tRNS = 1;
26114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_set_background_fixed(png_ptr, &c,
26124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
26134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     0/*gamma: not used*/);
26144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
26154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_NONE;
26174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
26184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
26194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else /* output is color */
26214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
26224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* We could use png_quantize here so long as there is no transparent
26234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * color or alpha; png_quantize ignores alpha.  Easier overall just
26244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
26254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * Consequently we always want libpng to produce sRGB data.
26264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
26274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            data_encoding = P_sRGB;
26284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Is there any transparency or alpha? */
26304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
26314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_ptr->num_trans > 0)
26324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
26334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Is there alpha in the output too?  If so all four channels are
26344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * processed into a special RGB cube with alpha support.
26354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
26364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
26374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
26384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 r;
26394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
26414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_error(png_ptr, "rgb+alpha color-map: too few entries");
26424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  cmap_entries = make_rgb_colormap(display);
26444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Add a transparent entry. */
26464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, cmap_entries, 255, 255,
26474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     255, 0, P_sRGB);
26484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* This is stored as the background index for the processing
26504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * algorithm.
26514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
26524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  background_index = cmap_entries++;
26534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Add 27 r,g,b entries each with alpha 0.5. */
26554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (r=0; r<256; r = (r << 1) | 0x7f)
26564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
26574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_uint_32 g;
26584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     for (g=0; g<256; g = (g << 1) | 0x7f)
26604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
26614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_uint_32 b;
26624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        /* This generates components with the values 0, 127 and
26644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * 255
26654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         */
26664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        for (b=0; b<256; b = (b << 1) | 0x7f)
26674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           png_create_colormap_entry(display, cmap_entries++,
26684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              r, g, b, 128, P_sRGB);
26694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
26704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
26714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  expand_tRNS = 1;
26734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  output_processing = PNG_CMAP_RGB_ALPHA;
26744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
26754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
26774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
26784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Alpha/transparency must be removed.  The background must
26794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * exist in the color map (achieved by setting adding it after
26804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * the 666 color-map).  If the standard processing code will
26814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * pick up this entry automatically that's all that is
26824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * required; libpng can be called to do the background
26834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * processing.
26844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
26854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  unsigned int sample_size =
26864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     PNG_IMAGE_SAMPLE_SIZE(output_format);
26874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_32 r, g, b; /* sRGB background */
26884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
26904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_error(png_ptr, "rgb-alpha color-map: too few entries");
26914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  cmap_entries = make_rgb_colormap(display);
26934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, cmap_entries, back_r,
26954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        back_g, back_b, 0/*unused*/, output_encoding);
26964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
26974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (output_encoding == P_LINEAR)
26984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
26994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     r = PNG_sRGB_FROM_LINEAR(back_r * 255);
27004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     g = PNG_sRGB_FROM_LINEAR(back_g * 255);
27014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     b = PNG_sRGB_FROM_LINEAR(back_b * 255);
27024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
27034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else
27054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
27064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     r = back_r;
27074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     g = back_g;
27084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     b = back_g;
27094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
27104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Compare the newly-created color-map entry with the one the
27124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * PNG_CMAP_RGB algorithm will use.  If the two entries don't
27134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * match, add the new one and set this as the background
27144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * index.
27154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
27164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (memcmp((png_const_bytep)display->colormap +
27174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        sample_size * cmap_entries,
27184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     (png_const_bytep)display->colormap +
27194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        sample_size * PNG_RGB_INDEX(r,g,b),
27204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     sample_size) != 0)
27214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
27224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* The background color must be added. */
27234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     background_index = cmap_entries++;
27244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Add 27 r,g,b entries each with created by composing with
27264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * the background at alpha 0.5.
27274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
27284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     for (r=0; r<256; r = (r << 1) | 0x7f)
27294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
27304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        for (g=0; g<256; g = (g << 1) | 0x7f)
27314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        {
27324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           /* This generates components with the values 0, 127
27334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                            * and 255
27344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                            */
27354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           for (b=0; b<256; b = (b << 1) | 0x7f)
27364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              png_create_colormap_entry(display, cmap_entries++,
27374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 png_colormap_compose(display, r, P_sRGB, 128,
27384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                    back_r, output_encoding),
27394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 png_colormap_compose(display, g, P_sRGB, 128,
27404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                    back_g, output_encoding),
27414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 png_colormap_compose(display, b, P_sRGB, 128,
27424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                    back_b, output_encoding),
27434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 0/*unused*/, output_encoding);
27444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        }
27454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
27464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     expand_tRNS = 1;
27484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     output_processing = PNG_CMAP_RGB_ALPHA;
27494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
27504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else /* background color is in the standard color-map */
27524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
27534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_color_16 c;
27544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     c.index = 0; /*unused*/
27564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     c.red = (png_uint_16)back_r;
27574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     c.gray = c.green = (png_uint_16)back_g;
27584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     c.blue = (png_uint_16)back_b;
27594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_set_background_fixed(png_ptr, &c,
27614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
27624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        0/*gamma: not used*/);
27634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     output_processing = PNG_CMAP_RGB;
27654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
27664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
27674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
27684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else /* no alpha or transparency in the input */
27704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
27714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Alpha in the output is irrelevant, simply map the opaque input
27724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * pixels to the 6x6x6 color-map.
27734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
27744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
27754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_error(png_ptr, "rgb color-map: too few entries");
27764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cmap_entries = make_rgb_colormap(display);
27784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               output_processing = PNG_CMAP_RGB;
27794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
27804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
27814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
27824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_COLOR_TYPE_PALETTE:
27844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* It's already got a color-map.  It may be necessary to eliminate the
27854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * tRNS entries though.
27864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
27874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
27884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            unsigned int num_trans = png_ptr->num_trans;
27894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
27904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_const_colorp colormap = png_ptr->palette;
27914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            const int do_background = trans != NULL &&
27924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
27934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            unsigned int i;
27944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Just in case: */
27964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (trans == NULL)
27974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               num_trans = 0;
27984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
27994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            output_processing = PNG_CMAP_NONE;
28004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            data_encoding = P_FILE; /* Don't change from color-map indices */
28014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            cmap_entries = png_ptr->num_palette;
28024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (cmap_entries > 256)
28034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               cmap_entries = 256;
28044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (cmap_entries > image->colormap_entries)
28064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_error(png_ptr, "palette color-map: too few entries");
28074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            for (i=0; i < cmap_entries; ++i)
28094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
28104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (do_background != 0 && i < num_trans && trans[i] < 255)
28114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
28124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (trans[i] == 0)
28134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_create_colormap_entry(display, i, back_r, back_g,
28144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        back_b, 0, output_encoding);
28154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else
28174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
28184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Must compose the PNG file color in the color-map entry
28194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * on the sRGB color in 'back'.
28204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
28214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_create_colormap_entry(display, i,
28224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_colormap_compose(display, colormap[i].red, P_FILE,
28234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           trans[i], back_r, output_encoding),
28244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_colormap_compose(display, colormap[i].green, P_FILE,
28254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           trans[i], back_g, output_encoding),
28264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_colormap_compose(display, colormap[i].blue, P_FILE,
28274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           trans[i], back_b, output_encoding),
28284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        output_encoding == P_LINEAR ? trans[i] * 257U :
28294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           trans[i],
28304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        output_encoding);
28314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
28324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
28334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
28354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_create_colormap_entry(display, i, colormap[i].red,
28364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     colormap[i].green, colormap[i].blue,
28374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
28384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
28394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The PNG data may have indices packed in fewer than 8 bits, it
28414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * must be expanded if so.
28424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
28434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (png_ptr->bit_depth < 8)
28444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_set_packing(png_ptr);
28454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
28464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
28474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
28494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "invalid PNG color type");
28504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /*NOT REACHED*/
28514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
28524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Now deal with the output processing */
28544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (expand_tRNS != 0 && png_ptr->num_trans > 0 &&
28554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
28564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_tRNS_to_alpha(png_ptr);
28574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (data_encoding)
28594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
28604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case P_sRGB:
28614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Change to 8-bit sRGB */
28624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
28634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* FALL THROUGH */
28644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case P_FILE:
28664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_ptr->bit_depth > 8)
28674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_scale_16(png_ptr);
28684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
28694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef __GNUC__
28714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
28724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "bad data option (internal error)");
28734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
28744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
28754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
28774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "color map overflow (BAD internal error)");
28784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   image->colormap_entries = cmap_entries;
28804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Double check using the recorded background index */
28824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (output_processing)
28834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
28844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_NONE:
28854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (background_index != PNG_CMAP_NONE_BACKGROUND)
28864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            goto bad_background;
28874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
28884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_GA:
28904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (background_index != PNG_CMAP_GA_BACKGROUND)
28914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            goto bad_background;
28924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
28934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
28944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_TRANS:
28954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (background_index >= cmap_entries ||
28964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            background_index != PNG_CMAP_TRANS_BACKGROUND)
28974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            goto bad_background;
28984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
28994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_RGB:
29014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (background_index != PNG_CMAP_RGB_BACKGROUND)
29024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            goto bad_background;
29034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
29044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_RGB_ALPHA:
29064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
29074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            goto bad_background;
29084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
29094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
29114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "bad processing option (internal error)");
29124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      bad_background:
29144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "bad background index (internal error)");
29154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
29164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   display->colormap_processing = output_processing;
29184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 1/*ok*/;
29204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
29214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* The final part of the color-map read called from png_image_finish_read. */
29234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
29244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_and_map(png_voidp argument)
29254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
29264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_image_read_control *display = png_voidcast(png_image_read_control*,
29274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      argument);
29284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = display->image;
29294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = image->opaque->png_ptr;
29304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int passes;
29314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Called when the libpng data must be transformed into the color-mapped
29334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * form.  There is a local row buffer in display->local and this routine must
29344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * do the interlace handling.
29354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
29364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (png_ptr->interlaced)
29374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
29384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_INTERLACE_NONE:
29394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         passes = 1;
29404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
29414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_INTERLACE_ADAM7:
29434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         passes = PNG_INTERLACE_ADAM7_PASSES;
29444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
29454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
29474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "unknown interlace type");
29484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
29494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
29514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32  height = image->height;
29524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32  width = image->width;
29534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int          proc = display->colormap_processing;
29544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_bytep    first_row = png_voidcast(png_bytep, display->first_row);
29554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ptrdiff_t    step_row = display->row_bytes;
29564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int pass;
29574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (pass = 0; pass < passes; ++pass)
29594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
29604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         unsigned int     startx, stepx, stepy;
29614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32      y;
29624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
29644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
29654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The row may be empty for a short image: */
29664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (PNG_PASS_COLS(width, pass) == 0)
29674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               continue;
29684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            startx = PNG_PASS_START_COL(pass);
29704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepx = PNG_PASS_COL_OFFSET(pass);
29714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = PNG_PASS_START_ROW(pass);
29724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepy = PNG_PASS_ROW_OFFSET(pass);
29734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
29744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
29764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
29774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = 0;
29784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            startx = 0;
29794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepx = stepy = 1;
29804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
29814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         for (; y<height; y += stepy)
29834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
29844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_bytep inrow = png_voidcast(png_bytep, display->local_row);
29854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_bytep outrow = first_row + y * step_row;
29864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_const_bytep end_row = outrow + width;
29874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Read read the libpng data into the temporary buffer. */
29894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_read_row(png_ptr, inrow, NULL);
29904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
29914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Now process the row according to the processing option, note
29924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * that the caller verifies that the format of the libpng output
29934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * data is as required.
29944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
29954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            outrow += startx;
29964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            switch (proc)
29974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
29984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               case PNG_CMAP_GA:
29994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; outrow < end_row; outrow += stepx)
30004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
30014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* The data is always in the PNG order */
30024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     unsigned int gray = *inrow++;
30034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     unsigned int alpha = *inrow++;
30044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     unsigned int entry;
30054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* NOTE: this code is copied as a comment in
30074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * make_ga_colormap above.  Please update the
30084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * comment if you change this code!
30094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
30104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (alpha > 229) /* opaque */
30114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
30124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        entry = (231 * gray + 128) >> 8;
30134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
30144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else if (alpha < 26) /* transparent */
30154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
30164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        entry = 231;
30174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
30184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else /* partially opaque */
30194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
30204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
30214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
30224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     *outrow = (png_byte)entry;
30244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
30254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  break;
30264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               case PNG_CMAP_TRANS:
30284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; outrow < end_row; outrow += stepx)
30294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
30304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_byte gray = *inrow++;
30314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_byte alpha = *inrow++;
30324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (alpha == 0)
30344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        *outrow = PNG_CMAP_TRANS_BACKGROUND;
30354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else if (gray != PNG_CMAP_TRANS_BACKGROUND)
30374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        *outrow = gray;
30384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else
30404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
30414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
30424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  break;
30434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               case PNG_CMAP_RGB:
30454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; outrow < end_row; outrow += stepx)
30464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
30474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
30484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     inrow += 3;
30494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
30504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  break;
30514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               case PNG_CMAP_RGB_ALPHA:
30534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; outrow < end_row; outrow += stepx)
30544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
30554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     unsigned int alpha = inrow[3];
30564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Because the alpha entries only hold alpha==0.5 values
30584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * split the processing at alpha==0.25 (64) and 0.75
30594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      * (196).
30604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      */
30614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (alpha >= 196)
30634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
30644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           inrow[2]);
30654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else if (alpha < 64)
30674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
30684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else
30704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
30714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        /* Likewise there are three entries for each of r, g
30724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * and b.  We could select the entry by popcount on
30734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * the top two bits on those architectures that
30744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * support it, this is what the code below does,
30754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * crudely.
30764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         */
30774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
30784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        /* Here are how the values map:
30804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         *
30814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * 0x00 .. 0x3f -> 0
30824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * 0x40 .. 0xbf -> 1
30834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * 0xc0 .. 0xff -> 2
30844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         *
30854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * So, as above with the explicit alpha checks, the
30864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * breakpoints are at 64 and 196.
30874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         */
30884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (inrow[0] & 0x80) back_i += 9; /* red */
30894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (inrow[0] & 0x40) back_i += 9;
30904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (inrow[0] & 0x80) back_i += 3; /* green */
30914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (inrow[0] & 0x40) back_i += 3;
30924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (inrow[0] & 0x80) back_i += 1; /* blue */
30934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (inrow[0] & 0x40) back_i += 1;
30944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        *outrow = (png_byte)back_i;
30964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
30974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
30984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     inrow += 4;
30994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
31004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  break;
31014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               default:
31034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  break;
31044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
31054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
31064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
31074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
31084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 1;
31104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
31114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
31134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_colormapped(png_voidp argument)
31144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
31154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_image_read_control *display = png_voidcast(png_image_read_control*,
31164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      argument);
31174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = display->image;
31184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_controlp control = image->opaque;
31194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = control->png_ptr;
31204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_inforp info_ptr = control->info_ptr;
31214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int passes = 0; /* As a flag */
31234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   PNG_SKIP_CHUNKS(png_ptr);
31254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Update the 'info' structure and make sure the result is as required; first
31274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * make sure to turn on the interlace handling if it will be required
31284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * (because it can't be turned on *after* the call to png_read_update_info!)
31294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
31304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (display->colormap_processing == PNG_CMAP_NONE)
31314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      passes = png_set_interlace_handling(png_ptr);
31324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_update_info(png_ptr, info_ptr);
31344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* The expected output can be deduced from the colormap_processing option. */
31364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (display->colormap_processing)
31374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
31384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_NONE:
31394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Output must be one channel and one byte per pixel, the output
31404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * encoding can be anything.
31414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
31424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
31434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
31444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            info_ptr->bit_depth == 8)
31454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
31464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         goto bad_output;
31484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_TRANS:
31504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_GA:
31514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Output must be two channels and the 'G' one must be sRGB, the latter
31524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * can be checked with an exact number because it should have been set
31534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * to this number above!
31544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
31554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
31564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            info_ptr->bit_depth == 8 &&
31574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
31584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->colormap_entries == 256)
31594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
31604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         goto bad_output;
31624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_RGB:
31644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Output must be 8-bit sRGB encoded RGB */
31654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
31664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            info_ptr->bit_depth == 8 &&
31674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
31684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->colormap_entries == 216)
31694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
31704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         goto bad_output;
31724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_CMAP_RGB_ALPHA:
31744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Output must be 8-bit sRGB encoded RGBA */
31754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
31764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            info_ptr->bit_depth == 8 &&
31774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
31784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            image->colormap_entries == 244 /* 216 + 1 + 27 */)
31794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            break;
31804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* goto bad_output; */
31824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* FALL THROUGH */
31834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
31854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      bad_output:
31864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "bad color-map processing (internal error)");
31874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
31884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Now read the rows.  Do this here if it is possible to read directly into
31904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * the output buffer, otherwise allocate a local row buffer of the maximum
31914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * size libpng requires and call the relevant processing routine safely.
31924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
31934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
31944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_voidp first_row = display->buffer;
31954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ptrdiff_t row_bytes = display->row_stride;
31964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* The following expression is designed to work correctly whether it gives
31984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * a signed or an unsigned result.
31994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
32004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row_bytes < 0)
32014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
32024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         char *ptr = png_voidcast(char*, first_row);
32034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         ptr += (image->height-1) * (-row_bytes);
32044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         first_row = png_voidcast(png_voidp, ptr);
32054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
32064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->first_row = first_row;
32084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->row_bytes = row_bytes;
32094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
32104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (passes == 0)
32124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
32134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int result;
32144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
32154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->local_row = row;
32174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      result = png_safe_execute(image, png_image_read_and_map, display);
32184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->local_row = NULL;
32194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_free(png_ptr, row);
32204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return result;
32224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
32234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else
32254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
32264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_alloc_size_t row_bytes = display->row_bytes;
32274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      while (--passes >= 0)
32294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
32304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32      y = image->height;
32314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep        row = png_voidcast(png_bytep, display->first_row);
32324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         while (y-- > 0)
32344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
32354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_read_row(png_ptr, row, NULL);
32364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            row += row_bytes;
32374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
32384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
32394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return 1;
32414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
32424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
32434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* Just the row reading part of png_image_read. */
32454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
32464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_composite(png_voidp argument)
32474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
32484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_image_read_control *display = png_voidcast(png_image_read_control*,
32494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      argument);
32504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = display->image;
32514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = image->opaque->png_ptr;
32524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int passes;
32534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (png_ptr->interlaced)
32554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
32564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_INTERLACE_NONE:
32574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         passes = 1;
32584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
32594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_INTERLACE_ADAM7:
32614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         passes = PNG_INTERLACE_ADAM7_PASSES;
32624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
32634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
32654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "unknown interlace type");
32664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
32674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
32694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32  height = image->height;
32704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32  width = image->width;
32714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ptrdiff_t    step_row = display->row_bytes;
32724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      unsigned int channels =
32734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
32744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int pass;
32754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      for (pass = 0; pass < passes; ++pass)
32774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
32784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         unsigned int     startx, stepx, stepy;
32794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32      y;
32804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
32824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
32834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The row may be empty for a short image: */
32844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (PNG_PASS_COLS(width, pass) == 0)
32854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               continue;
32864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            startx = PNG_PASS_START_COL(pass) * channels;
32884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepx = PNG_PASS_COL_OFFSET(pass) * channels;
32894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = PNG_PASS_START_ROW(pass);
32904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepy = PNG_PASS_ROW_OFFSET(pass);
32914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
32924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
32934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
32944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
32954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            y = 0;
32964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            startx = 0;
32974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepx = channels;
32984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            stepy = 1;
32994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
33004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         for (; y<height; y += stepy)
33024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
33034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_bytep inrow = png_voidcast(png_bytep, display->local_row);
33044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_bytep outrow;
33054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_const_bytep end_row;
33064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Read the row, which is packed: */
33084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_read_row(png_ptr, inrow, NULL);
33094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            outrow = png_voidcast(png_bytep, display->first_row);
33114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            outrow += y * step_row;
33124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            end_row = outrow + width * channels;
33134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Now do the composition on each pixel in this row. */
33154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            outrow += startx;
33164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            for (; outrow < end_row; outrow += stepx)
33174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
33184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_byte alpha = inrow[channels];
33194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (alpha > 0) /* else no change to the output */
33214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
33224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  unsigned int c;
33234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (c=0; c<channels; ++c)
33254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
33264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_uint_32 component = inrow[c];
33274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (alpha < 255) /* else just use component */
33294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
33304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        /* This is PNG_OPTIMIZED_ALPHA, the component value
33314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * is a linear 8-bit value.  Combine this with the
33324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * current outrow[c] value which is sRGB encoded.
33334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * Arithmetic here is 16-bits to preserve the output
33344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * values correctly.
33354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         */
33364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        component *= 257*255; /* =65535 */
33374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        component += (255-alpha)*png_sRGB_table[outrow[c]];
33384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        /* So 'component' is scaled by 255*65535 and is
33404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * therefore appropriate for the sRGB to linear
33414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         * conversion table.
33424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         */
33434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        component = PNG_sRGB_FROM_LINEAR(component);
33444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
33454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     outrow[c] = (png_byte)component;
33474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
33484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
33494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               inrow += channels+1; /* components and alpha channel */
33514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
33524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
33534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
33544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
33554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 1;
33574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
33584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* The do_local_background case; called when all the following transforms are to
33604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * be done:
33614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
33624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * PNG_RGB_TO_GRAY
33634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * PNG_COMPOSITE
33644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * PNG_GAMMA
33654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann *
33664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * This is a work-around for the fact that both the PNG_RGB_TO_GRAY and
33674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * PNG_COMPOSITE code performs gamma correction, so we get double gamma
33684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * correction.  The fix-up is to prevent the PNG_COMPOSITE operation from
33694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * happening inside libpng, so this routine sees an 8 or 16-bit gray+alpha
33704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann * row and handles the removal or pre-multiplication of the alpha channel.
33714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann */
33724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
33734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_background(png_voidp argument)
33744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
33754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_image_read_control *display = png_voidcast(png_image_read_control*,
33764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      argument);
33774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = display->image;
33784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = image->opaque->png_ptr;
33794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_inforp info_ptr = image->opaque->info_ptr;
33804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 height = image->height;
33814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 width = image->width;
33824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int pass, passes;
33834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Double check the convoluted logic below.  We expect to get here with
33854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * libpng doing rgb to gray and gamma correction but background processing
33864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * left to the png_image_read_background function.  The rows libpng produce
33874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * might be 8 or 16-bit but should always have two channels; gray plus alpha.
33884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
33894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
33904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "lost rgb to gray");
33914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
33934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "unexpected compose");
33944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (png_get_channels(png_ptr, info_ptr) != 2)
33964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "lost/gained channels");
33974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
33984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Expect the 8-bit case to always remove the alpha channel */
33994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
34004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
34014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_error(png_ptr, "unexpected 8-bit transformation");
34024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (png_ptr->interlaced)
34044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
34054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_INTERLACE_NONE:
34064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         passes = 1;
34074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
34084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case PNG_INTERLACE_ADAM7:
34104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         passes = PNG_INTERLACE_ADAM7_PASSES;
34114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
34124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
34144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "unknown interlace type");
34154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
34164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Use direct access to info_ptr here because otherwise the simplified API
34184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * would require PNG_EASY_ACCESS_SUPPORTED (just for this.)  Note this is
34194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * checking the value after libpng expansions, not the original value in the
34204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * PNG.
34214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
34224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   switch (info_ptr->bit_depth)
34234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
34244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case 8:
34254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
34264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * to be removed by composing on a background: either the row if
34274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * display->background is NULL or display->background->green if not.
34284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
34294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
34304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
34314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_bytep first_row = png_voidcast(png_bytep, display->first_row);
34324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            ptrdiff_t step_row = display->row_bytes;
34334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            for (pass = 0; pass < passes; ++pass)
34354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
34364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_bytep        row = png_voidcast(png_bytep,
34374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                                   display->first_row);
34384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               unsigned int     startx, stepx, stepy;
34394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_uint_32      y;
34404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
34424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
34434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* The row may be empty for a short image: */
34444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (PNG_PASS_COLS(width, pass) == 0)
34454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     continue;
34464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  startx = PNG_PASS_START_COL(pass);
34484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepx = PNG_PASS_COL_OFFSET(pass);
34494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  y = PNG_PASS_START_ROW(pass);
34504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepy = PNG_PASS_ROW_OFFSET(pass);
34514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
34524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
34544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
34554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  y = 0;
34564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  startx = 0;
34574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepx = stepy = 1;
34584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
34594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (display->background == NULL)
34614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
34624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; y<height; y += stepy)
34634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
34644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_bytep inrow = png_voidcast(png_bytep,
34654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        display->local_row);
34664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_bytep outrow = first_row + y * step_row;
34674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_const_bytep end_row = outrow + width;
34684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Read the row, which is packed: */
34704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_read_row(png_ptr, inrow, NULL);
34714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Now do the composition on each pixel in this row. */
34734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     outrow += startx;
34744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     for (; outrow < end_row; outrow += stepx)
34754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
34764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_byte alpha = inrow[1];
34774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (alpha > 0) /* else no change to the output */
34794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        {
34804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           png_uint_32 component = inrow[0];
34814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           if (alpha < 255) /* else just use component */
34834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           {
34844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              /* Since PNG_OPTIMIZED_ALPHA was not set it is
34854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                               * necessary to invert the sRGB transfer
34864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                               * function and multiply the alpha out.
34874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                               */
34884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              component = png_sRGB_table[component] * alpha;
34894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              component += png_sRGB_table[outrow[0]] *
34904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 (255-alpha);
34914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              component = PNG_sRGB_FROM_LINEAR(component);
34924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           }
34934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           outrow[0] = (png_byte)component;
34954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        }
34964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
34974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        inrow += 2; /* gray and alpha channel */
34984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
34994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
35004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
35014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else /* constant background value */
35034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
35044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_byte background8 = display->background->green;
35054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_16 background = png_sRGB_table[background8];
35064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; y<height; y += stepy)
35084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
35094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_bytep inrow = png_voidcast(png_bytep,
35104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        display->local_row);
35114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_bytep outrow = first_row + y * step_row;
35124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_const_bytep end_row = outrow + width;
35134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Read the row, which is packed: */
35154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_read_row(png_ptr, inrow, NULL);
35164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     /* Now do the composition on each pixel in this row. */
35184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     outrow += startx;
35194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     for (; outrow < end_row; outrow += stepx)
35204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
35214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_byte alpha = inrow[1];
35224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (alpha > 0) /* else use background */
35244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        {
35254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           png_uint_32 component = inrow[0];
35264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           if (alpha < 255) /* else just use component */
35284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           {
35294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              component = png_sRGB_table[component] * alpha;
35304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              component += background * (255-alpha);
35314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              component = PNG_sRGB_FROM_LINEAR(component);
35324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           }
35334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           outrow[0] = (png_byte)component;
35354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        }
35364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        else
35384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           outrow[0] = background8;
35394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        inrow += 2; /* gray and alpha channel */
35414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
35424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     row += display->row_bytes;
35444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
35454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
35464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
35474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
35484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
35494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      case 16:
35514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
35524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * still be done and, maybe, the alpha channel removed.  This code also
35534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * handles the alpha-first option.
35544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
35554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
35564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_16p first_row = png_voidcast(png_uint_16p,
35574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               display->first_row);
35584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* The division by two is safe because the caller passed in a
35594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * stride which was multiplied by 2 (below) to get row_bytes.
35604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
35614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            ptrdiff_t    step_row = display->row_bytes / 2;
35624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
35634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            unsigned int outchannels = 1+preserve_alpha;
35644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            int swap_alpha = 0;
35654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#           ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
35674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (preserve_alpha != 0 &&
35684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   (image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
35694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  swap_alpha = 1;
35704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#           endif
35714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            for (pass = 0; pass < passes; ++pass)
35734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
35744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               unsigned int     startx, stepx, stepy;
35754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_uint_32      y;
35764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* The 'x' start and step are adjusted to output components here.
35784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
35794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
35804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
35814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* The row may be empty for a short image: */
35824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if (PNG_PASS_COLS(width, pass) == 0)
35834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     continue;
35844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  startx = PNG_PASS_START_COL(pass) * outchannels;
35864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
35874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  y = PNG_PASS_START_ROW(pass);
35884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepy = PNG_PASS_ROW_OFFSET(pass);
35894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
35904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
35924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
35934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  y = 0;
35944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  startx = 0;
35954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepx = outchannels;
35964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  stepy = 1;
35974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
35984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
35994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               for (; y<height; y += stepy)
36004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
36014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_const_uint_16p inrow;
36024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_16p outrow = first_row + y*step_row;
36034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_uint_16p end_row = outrow + width * outchannels;
36044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Read the row, which is packed: */
36064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_read_row(png_ptr, png_voidcast(png_bytep,
36074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     display->local_row), NULL);
36084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  inrow = png_voidcast(png_const_uint_16p, display->local_row);
36094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Now do the pre-multiplication on each pixel in this row.
36114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
36124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  outrow += startx;
36134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  for (; outrow < end_row; outrow += stepx)
36144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  {
36154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_uint_32 component = inrow[0];
36164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     png_uint_16 alpha = inrow[1];
36174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (alpha > 0) /* else 0 */
36194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     {
36204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        if (alpha < 65535) /* else just use component */
36214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        {
36224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           component *= alpha;
36234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           component += 32767;
36244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                           component /= 65535;
36254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        }
36264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     }
36274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     else
36294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        component = 0;
36304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     outrow[swap_alpha] = (png_uint_16)component;
36324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     if (preserve_alpha != 0)
36334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        outrow[1 ^ swap_alpha] = alpha;
36344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     inrow += 2; /* components and alpha channel */
36364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  }
36374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
36384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
36394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
36404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         break;
36414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef __GNUC__
36434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      default:
36444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "unexpected bit depth");
36454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
36464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
36474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 1;
36494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
36504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann/* The guts of png_image_finish_read as a png_safe_execute callback. */
36524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic int
36534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_read_direct(png_voidp argument)
36544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
36554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_image_read_control *display = png_voidcast(png_image_read_control*,
36564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      argument);
36574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_imagep image = display->image;
36584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_structrp png_ptr = image->opaque->png_ptr;
36594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_inforp info_ptr = image->opaque->info_ptr;
36604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_uint_32 format = image->format;
36624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
36634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int do_local_compose = 0;
36644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int do_local_background = 0; /* to avoid double gamma correction bug */
36654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   int passes = 0;
36664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Add transforms to ensure the correct output format is produced then check
36684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * that the required implementation support is there.  Always expand; always
36694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * need 8 bits minimum, no palette and expanded tRNS.
36704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
36714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_set_expand(png_ptr);
36724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Now check the format to see if it was modified. */
36744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
36754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 base_format = png_image_format(png_ptr) &
36764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;
36774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 change = format ^ base_format;
36784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_fixed_point output_gamma;
36794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int mode; /* alpha mode */
36804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Do this first so that we have a record if rgb to gray is happening. */
36824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((change & PNG_FORMAT_FLAG_COLOR) != 0)
36834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
36844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* gray<->color transformation required. */
36854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
36864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_gray_to_rgb(png_ptr);
36874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
36884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
36894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
36904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* libpng can't do both rgb to gray and
36914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * background/pre-multiplication if there is also significant gamma
36924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * correction, because both operations require linear colors and
36934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * the code only supports one transform doing the gamma correction.
36944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * Handle this by doing the pre-multiplication or background
36954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * operation in this code, if necessary.
36964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
36974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * TODO: fix this by rewriting pngrtran.c (!)
36984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
36994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * For the moment (given that fixing this in pngrtran.c is an
37004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * enormous change) 'do_local_background' is used to indicate that
37014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * the problem exists.
37024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
37034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
37044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               do_local_background = 1/*maybe*/;
37054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
37074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
37084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
37094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         change &= ~PNG_FORMAT_FLAG_COLOR;
37114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
37124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
37144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
37154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
37164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_fixed_point input_gamma_default;
37174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
37194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
37204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            input_gamma_default = PNG_GAMMA_LINEAR;
37214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
37224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            input_gamma_default = PNG_DEFAULT_sRGB;
37234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Call png_set_alpha_mode to set the default for the input gamma; the
37254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * output gamma is set by a second call below.
37264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
37274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
37284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
37294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (linear != 0)
37314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
37324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* If there *is* an alpha channel in the input it must be multiplied
37334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
37344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
37354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
37364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            mode = PNG_ALPHA_STANDARD; /* associated alpha */
37374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
37394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            mode = PNG_ALPHA_PNG;
37404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         output_gamma = PNG_GAMMA_LINEAR;
37424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
37434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
37454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
37464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         mode = PNG_ALPHA_PNG;
37474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         output_gamma = PNG_DEFAULT_sRGB;
37484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
37494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* If 'do_local_background' is set check for the presence of gamma
37514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * correction; this is part of the work-round for the libpng bug
37524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * described above.
37534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       *
37544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * TODO: fix libpng and remove this.
37554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
37564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (do_local_background != 0)
37574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
37584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_fixed_point gtest;
37594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
37614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * gamma correction, the screen gamma hasn't been set on png_struct
37624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * yet; it's set below.  png_struct::gamma, however, is set to the
37634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * final value.
37644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
37654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (png_muldiv(&gtest, output_gamma, png_ptr->colorspace.gamma,
37664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
37674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            do_local_background = 0;
37684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else if (mode == PNG_ALPHA_STANDARD)
37704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
37714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            do_local_background = 2/*required*/;
37724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
37734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
37744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* else leave as 1 for the checks below */
37764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
37774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* If the bit-depth changes then handle that here. */
37794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((change & PNG_FORMAT_FLAG_LINEAR) != 0)
37804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
37814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (linear != 0 /*16-bit output*/)
37824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_expand_16(png_ptr);
37834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else /* 8-bit output */
37854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_scale_16(png_ptr);
37864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         change &= ~PNG_FORMAT_FLAG_LINEAR;
37884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
37894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Now the background/alpha channel changes. */
37914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((change & PNG_FORMAT_FLAG_ALPHA) != 0)
37924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
37934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* Removing an alpha channel requires composition for the 8-bit
37944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * formats; for the 16-bit it is already done, above, by the
37954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          * pre-multiplication and the channel just needs to be stripped.
37964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          */
37974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
37984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
37994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* If RGB->gray is happening the alpha channel must be left and the
38004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * operation completed locally.
38014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             *
38024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * TODO: fix libpng and remove this.
38034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
38044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (do_local_background != 0)
38054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               do_local_background = 2/*required*/;
38064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* 16-bit output: just remove the channel */
38084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else if (linear != 0) /* compose on black (well, pre-multiply) */
38094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_set_strip_alpha(png_ptr);
38104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* 8-bit output: do an appropriate compose */
38124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else if (display->background != NULL)
38134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
38144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_color_16 c;
38154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.index = 0; /*unused*/
38174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.red = display->background->red;
38184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.green = display->background->green;
38194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.blue = display->background->blue;
38204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               c.gray = display->background->green;
38214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* This is always an 8-bit sRGB value, using the 'green' channel
38234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * for gray is much better than calculating the luminance here;
38244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * we can get off-by-one errors in that calculation relative to
38254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * the app expectations and that will show up in transparent
38264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * pixels.
38274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
38284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_set_background_fixed(png_ptr, &c,
38294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
38304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  0/*gamma: not used*/);
38314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
38324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else /* compose on row: implemented below. */
38344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
38354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               do_local_compose = 1;
38364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* This leaves the alpha channel in the output, so it has to be
38374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * removed by the code below.  Set the encoding to the 'OPTIMIZE'
38384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * one so the code only has to hack on the pixels that require
38394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * composition.
38404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
38414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               mode = PNG_ALPHA_OPTIMIZED;
38424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
38434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
38444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else /* output needs an alpha channel */
38464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
38474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* This is tricky because it happens before the swap operation has
38484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * been accomplished; however, the swap does *not* swap the added
38494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * alpha channel (weird API), so it must be added in the correct
38504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * place.
38514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
38524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_uint_32 filler; /* opaque filler */
38534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            int where;
38544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (linear != 0)
38564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               filler = 65535;
38574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
38594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               filler = 255;
38604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_FORMAT_AFIRST_SUPPORTED
38624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
38634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
38644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               where = PNG_FILLER_BEFORE;
38654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               change &= ~PNG_FORMAT_FLAG_AFIRST;
38664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
38674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
38694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
38704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            where = PNG_FILLER_AFTER;
38714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_add_alpha(png_ptr, filler, where);
38734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
38744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* This stops the (irrelevant) call to swap_alpha below. */
38764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         change &= ~PNG_FORMAT_FLAG_ALPHA;
38774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
38784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Now set the alpha mode correctly; this is always done, even if there is
38804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * no alpha channel in either the input or the output because it correctly
38814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * sets the output gamma.
38824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
38834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
38844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef PNG_FORMAT_BGR_SUPPORTED
38864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((change & PNG_FORMAT_FLAG_BGR) != 0)
38874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
38884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Check only the output format; PNG is never BGR; don't do this if
38894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * the output is gray, but fix up the 'format' value in that case.
38904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
38914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
38924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_set_bgr(png_ptr);
38934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
38954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               format &= ~PNG_FORMAT_FLAG_BGR;
38964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
38974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            change &= ~PNG_FORMAT_FLAG_BGR;
38984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
38994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
39004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
39024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((change & PNG_FORMAT_FLAG_AFIRST) != 0)
39034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
39044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Only relevant if there is an alpha channel - it's particularly
39054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * important to handle this correctly because do_local_compose may
39064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * be set above and then libpng will keep the alpha channel for this
39074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * code to remove.
39084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
39094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)
39104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
39114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               /* Disable this if doing a local background,
39124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                * TODO: remove this when local background is no longer required.
39134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                */
39144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if (do_local_background != 2)
39154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_set_swap_alpha(png_ptr);
39164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
39174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
39194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               format &= ~PNG_FORMAT_FLAG_AFIRST;
39204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            change &= ~PNG_FORMAT_FLAG_AFIRST;
39224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
39234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
39244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* If the *output* is 16-bit then we need to check for a byte-swap on this
39264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * architecture.
39274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
39284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (linear != 0)
39294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
39304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         PNG_CONST png_uint_16 le = 0x0001;
39314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((*(png_const_bytep) & le) != 0)
39334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_set_swap(png_ptr);
39344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
39354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* If change is not now 0 some transformation is missing - error out. */
39374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (change != 0)
39384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "png_read_image: unsupported transformation");
39394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
39404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   PNG_SKIP_CHUNKS(png_ptr);
39424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Update the 'info' structure and make sure the result is as required; first
39444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * make sure to turn on the interlace handling if it will be required
39454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * (because it can't be turned on *after* the call to png_read_update_info!)
39464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *
39474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * TODO: remove the do_local_background fixup below.
39484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
39494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (do_local_compose == 0 && do_local_background != 2)
39504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      passes = png_set_interlace_handling(png_ptr);
39514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   png_read_update_info(png_ptr, info_ptr);
39534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
39554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_uint_32 info_format = 0;
39564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
39584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         info_format |= PNG_FORMAT_FLAG_COLOR;
39594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
39614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
39624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         /* do_local_compose removes this channel below. */
39634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (do_local_compose == 0)
39644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
39654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* do_local_background does the same if required. */
39664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (do_local_background != 2 ||
39674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               (format & PNG_FORMAT_FLAG_ALPHA) != 0)
39684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               info_format |= PNG_FORMAT_FLAG_ALPHA;
39694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
39704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
39714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else if (do_local_compose != 0) /* internal error */
39734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "png_image_read: alpha channel lost");
39744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (info_ptr->bit_depth == 16)
39764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         info_format |= PNG_FORMAT_FLAG_LINEAR;
39774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_FORMAT_BGR_SUPPORTED
39794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if ((png_ptr->transformations & PNG_BGR) != 0)
39804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         info_format |= PNG_FORMAT_FLAG_BGR;
39814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
39824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PNG_FORMAT_AFIRST_SUPPORTED
39844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (do_local_background == 2)
39854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
39864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
39874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               info_format |= PNG_FORMAT_FLAG_AFIRST;
39884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
39894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
39914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
39924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
39934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
39944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (do_local_background == 2)
39954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               png_error(png_ptr, "unexpected alpha swap transformation");
39964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
39974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            info_format |= PNG_FORMAT_FLAG_AFIRST;
39984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
39994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#     endif
40004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* This is actually an internal error. */
40024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (info_format != format)
40034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_error(png_ptr, "png_read_image: invalid transformations");
40044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
40054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   /* Now read the rows.  If do_local_compose is set then it is necessary to use
40074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * a local row buffer.  The output will be GA, RGBA or BGRA and must be
40084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * converted to G, RGB or BGR as appropriate.  The 'local_row' member of the
40094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    * display acts as a flag.
40104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    */
40114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
40124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_voidp first_row = display->buffer;
40134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ptrdiff_t row_bytes = display->row_stride;
40144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (linear != 0)
40164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         row_bytes *= 2;
40174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* The following expression is designed to work correctly whether it gives
40194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * a signed or an unsigned result.
40204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
40214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (row_bytes < 0)
40224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
40234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         char *ptr = png_voidcast(char*, first_row);
40244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         ptr += (image->height-1) * (-row_bytes);
40254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         first_row = png_voidcast(png_voidp, ptr);
40264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
40274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->first_row = first_row;
40294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->row_bytes = row_bytes;
40304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
40314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (do_local_compose != 0)
40334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
40344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int result;
40354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
40364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->local_row = row;
40384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      result = png_safe_execute(image, png_image_read_composite, display);
40394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->local_row = NULL;
40404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_free(png_ptr, row);
40414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return result;
40434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
40444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (do_local_background == 2)
40464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
40474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int result;
40484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
40494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->local_row = row;
40514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      result = png_safe_execute(image, png_image_read_background, display);
40524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      display->local_row = NULL;
40534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_free(png_ptr, row);
40544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return result;
40564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
40574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else
40594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
40604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      png_alloc_size_t row_bytes = display->row_bytes;
40614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      while (--passes >= 0)
40634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
40644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32      y = image->height;
40654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_bytep        row = png_voidcast(png_bytep, display->first_row);
40664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         while (y-- > 0)
40684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
40694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            png_read_row(png_ptr, row, NULL);
40704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            row += row_bytes;
40714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
40724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
40734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return 1;
40754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
40764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
40774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannint PNGAPI
40794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannpng_image_finish_read(png_imagep image, png_const_colorp background,
40804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   void *buffer, png_int_32 row_stride, void *colormap)
40814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann{
40824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   if (image != NULL && image->version == PNG_IMAGE_VERSION)
40834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   {
40844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      /* Check for row_stride overflow.  This check is not performed on the
40854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * original PNG format because it may not occur in the output PNG format
40864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       * and libpng deals with the issues of reading the original.
40874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann       */
40884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
40894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
40914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      {
40924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         png_uint_32 check;
40934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         const png_uint_32 png_row_stride = image->width * channels;
40944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (row_stride == 0)
40964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            row_stride = (png_int_32)/*SAFE*/png_row_stride;
40974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
40984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (row_stride < 0)
40994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            check = -row_stride;
41004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
41024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            check = row_stride;
41034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
41054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         {
41064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            /* Now check for overflow of the image buffer calculation; this
41074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * limits the whole image size to 32 bits for API compatibility with
41084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
41094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann             */
41104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            if (image->height <= 0xFFFFFFFF/png_row_stride)
41114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            {
41124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
41134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  (image->colormap_entries > 0 && colormap != NULL))
41144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               {
41154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  int result;
41164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_image_read_control display;
41174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  memset(&display, 0, (sizeof display));
41194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  display.image = image;
41204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  display.buffer = buffer;
41214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  display.row_stride = row_stride;
41224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  display.colormap = colormap;
41234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  display.background = background;
41244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  display.local_row = NULL;
41254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  /* Choose the correct 'end' routine; for the color-map case
41274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   * all the setup has already been done.
41284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   */
41294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
41304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     result = png_safe_execute(image,
41314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                    png_image_read_colormap, &display) &&
41324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              png_safe_execute(image,
41334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                    png_image_read_colormapped, &display);
41344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  else
41364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     result =
41374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        png_safe_execute(image,
41384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              png_image_read_direct, &display);
41394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  png_image_free(image);
41414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  return result;
41424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               }
41434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               else
41454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  return png_image_error(image,
41464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     "png_image_finish_read[color-map]: no color-map");
41474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            }
41484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            else
41504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               return png_image_error(image,
41514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  "png_image_finish_read: image too large");
41524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         }
41534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         else
41554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            return png_image_error(image,
41564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann               "png_image_finish_read: invalid argument");
41574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
41584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      else
41604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         return png_image_error(image,
41614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            "png_image_finish_read: row_stride too large");
41624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   }
41634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   else if (image != NULL)
41654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return png_image_error(image,
41664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann         "png_image_finish_read: damaged PNG_IMAGE_VERSION");
41674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann   return 0;
41694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
41704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
41714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* SIMPLIFIED_READ */
41724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif /* READ */
4173