media/libpng/pngread.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libpng/pngread.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,4178 @@
     1.4 +
     1.5 +/* pngread.c - read a PNG file
     1.6 + *
     1.7 + * Last changed in libpng 1.6.10 [March 6, 2014]
     1.8 + * Copyright (c) 1998-2014 Glenn Randers-Pehrson
     1.9 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
    1.10 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
    1.11 + *
    1.12 + * This code is released under the libpng license.
    1.13 + * For conditions of distribution and use, see the disclaimer
    1.14 + * and license in png.h
    1.15 + *
    1.16 + * This file contains routines that an application calls directly to
    1.17 + * read a PNG file or stream.
    1.18 + */
    1.19 +
    1.20 +#include "pngpriv.h"
    1.21 +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
    1.22 +#  include <errno.h>
    1.23 +#endif
    1.24 +
    1.25 +#ifdef PNG_READ_SUPPORTED
    1.26 +
    1.27 +/* Create a PNG structure for reading, and allocate any memory needed. */
    1.28 +PNG_FUNCTION(png_structp,PNGAPI
    1.29 +png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
    1.30 +    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
    1.31 +{
    1.32 +#ifndef PNG_USER_MEM_SUPPORTED
    1.33 +   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
    1.34 +      error_fn, warn_fn, NULL, NULL, NULL);
    1.35 +#else
    1.36 +   return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
    1.37 +       warn_fn, NULL, NULL, NULL);
    1.38 +}
    1.39 +
    1.40 +/* Alternate create PNG structure for reading, and allocate any memory
    1.41 + * needed.
    1.42 + */
    1.43 +PNG_FUNCTION(png_structp,PNGAPI
    1.44 +png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
    1.45 +    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
    1.46 +    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
    1.47 +{
    1.48 +   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
    1.49 +      error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
    1.50 +#endif /* PNG_USER_MEM_SUPPORTED */
    1.51 +
    1.52 +   if (png_ptr != NULL)
    1.53 +   {
    1.54 +      png_ptr->mode = PNG_IS_READ_STRUCT;
    1.55 +
    1.56 +      /* Added in libpng-1.6.0; this can be used to detect a read structure if
    1.57 +       * required (it will be zero in a write structure.)
    1.58 +       */
    1.59 +#     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    1.60 +         png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
    1.61 +#     endif
    1.62 +
    1.63 +#     ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
    1.64 +         png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
    1.65 +
    1.66 +         /* In stable builds only warn if an application error can be completely
    1.67 +          * handled.
    1.68 +          */
    1.69 +#        if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
    1.70 +            png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
    1.71 +#        endif
    1.72 +#     endif
    1.73 +
    1.74 +      /* TODO: delay this, it can be done in png_init_io (if the app doesn't
    1.75 +       * do it itself) avoiding setting the default function if it is not
    1.76 +       * required.
    1.77 +       */
    1.78 +      png_set_read_fn(png_ptr, NULL, NULL);
    1.79 +   }
    1.80 +
    1.81 +   return png_ptr;
    1.82 +}
    1.83 +
    1.84 +
    1.85 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    1.86 +/* Read the information before the actual image data.  This has been
    1.87 + * changed in v0.90 to allow reading a file that already has the magic
    1.88 + * bytes read from the stream.  You can tell libpng how many bytes have
    1.89 + * been read from the beginning of the stream (up to the maximum of 8)
    1.90 + * via png_set_sig_bytes(), and we will only check the remaining bytes
    1.91 + * here.  The application can then have access to the signature bytes we
    1.92 + * read if it is determined that this isn't a valid PNG file.
    1.93 + */
    1.94 +void PNGAPI
    1.95 +png_read_info(png_structrp png_ptr, png_inforp info_ptr)
    1.96 +{
    1.97 +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    1.98 +   int keep;
    1.99 +#endif
   1.100 +
   1.101 +   png_debug(1, "in png_read_info");
   1.102 +
   1.103 +   if (png_ptr == NULL || info_ptr == NULL)
   1.104 +      return;
   1.105 +
   1.106 +   /* Read and check the PNG file signature. */
   1.107 +   png_read_sig(png_ptr, info_ptr);
   1.108 +
   1.109 +   for (;;)
   1.110 +   {
   1.111 +      png_uint_32 length = png_read_chunk_header(png_ptr);
   1.112 +      png_uint_32 chunk_name = png_ptr->chunk_name;
   1.113 +
   1.114 +      /* IDAT logic needs to happen here to simplify getting the two flags
   1.115 +       * right.
   1.116 +       */
   1.117 +      if (chunk_name == png_IDAT)
   1.118 +      {
   1.119 +         if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1.120 +            png_chunk_error(png_ptr, "Missing IHDR before IDAT");
   1.121 +
   1.122 +         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
   1.123 +             !(png_ptr->mode & PNG_HAVE_PLTE))
   1.124 +            png_chunk_error(png_ptr, "Missing PLTE before IDAT");
   1.125 +
   1.126 +         else if (png_ptr->mode & PNG_AFTER_IDAT)
   1.127 +            png_chunk_benign_error(png_ptr, "Too many IDATs found");
   1.128 +
   1.129 +         png_ptr->mode |= PNG_HAVE_IDAT;
   1.130 +      }
   1.131 +
   1.132 +      else if (png_ptr->mode & PNG_HAVE_IDAT)
   1.133 +         png_ptr->mode |= PNG_AFTER_IDAT;
   1.134 +
   1.135 +      /* This should be a binary subdivision search or a hash for
   1.136 +       * matching the chunk name rather than a linear search.
   1.137 +       */
   1.138 +      if (chunk_name == png_IHDR)
   1.139 +         png_handle_IHDR(png_ptr, info_ptr, length);
   1.140 +
   1.141 +      else if (chunk_name == png_IEND)
   1.142 +         png_handle_IEND(png_ptr, info_ptr, length);
   1.143 +
   1.144 +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   1.145 +      else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
   1.146 +      {
   1.147 +         png_handle_unknown(png_ptr, info_ptr, length, keep);
   1.148 +
   1.149 +         if (chunk_name == png_PLTE)
   1.150 +            png_ptr->mode |= PNG_HAVE_PLTE;
   1.151 +
   1.152 +         else if (chunk_name == png_IDAT)
   1.153 +         {
   1.154 +            png_ptr->idat_size = 0; /* It has been consumed */
   1.155 +            break;
   1.156 +         }
   1.157 +      }
   1.158 +#endif
   1.159 +      else if (chunk_name == png_PLTE)
   1.160 +         png_handle_PLTE(png_ptr, info_ptr, length);
   1.161 +
   1.162 +      else if (chunk_name == png_IDAT)
   1.163 +      {
   1.164 +#ifdef PNG_READ_APNG_SUPPORTED
   1.165 +         png_have_info(png_ptr, info_ptr);
   1.166 +#endif
   1.167 +         png_ptr->idat_size = length;
   1.168 +         break;
   1.169 +      }
   1.170 +
   1.171 +#ifdef PNG_READ_bKGD_SUPPORTED
   1.172 +      else if (chunk_name == png_bKGD)
   1.173 +         png_handle_bKGD(png_ptr, info_ptr, length);
   1.174 +#endif
   1.175 +
   1.176 +#ifdef PNG_READ_cHRM_SUPPORTED
   1.177 +      else if (chunk_name == png_cHRM)
   1.178 +         png_handle_cHRM(png_ptr, info_ptr, length);
   1.179 +#endif
   1.180 +
   1.181 +#ifdef PNG_READ_gAMA_SUPPORTED
   1.182 +      else if (chunk_name == png_gAMA)
   1.183 +         png_handle_gAMA(png_ptr, info_ptr, length);
   1.184 +#endif
   1.185 +
   1.186 +#ifdef PNG_READ_hIST_SUPPORTED
   1.187 +      else if (chunk_name == png_hIST)
   1.188 +         png_handle_hIST(png_ptr, info_ptr, length);
   1.189 +#endif
   1.190 +
   1.191 +#ifdef PNG_READ_oFFs_SUPPORTED
   1.192 +      else if (chunk_name == png_oFFs)
   1.193 +         png_handle_oFFs(png_ptr, info_ptr, length);
   1.194 +#endif
   1.195 +
   1.196 +#ifdef PNG_READ_pCAL_SUPPORTED
   1.197 +      else if (chunk_name == png_pCAL)
   1.198 +         png_handle_pCAL(png_ptr, info_ptr, length);
   1.199 +#endif
   1.200 +
   1.201 +#ifdef PNG_READ_sCAL_SUPPORTED
   1.202 +      else if (chunk_name == png_sCAL)
   1.203 +         png_handle_sCAL(png_ptr, info_ptr, length);
   1.204 +#endif
   1.205 +
   1.206 +#ifdef PNG_READ_pHYs_SUPPORTED
   1.207 +      else if (chunk_name == png_pHYs)
   1.208 +         png_handle_pHYs(png_ptr, info_ptr, length);
   1.209 +#endif
   1.210 +
   1.211 +#ifdef PNG_READ_sBIT_SUPPORTED
   1.212 +      else if (chunk_name == png_sBIT)
   1.213 +         png_handle_sBIT(png_ptr, info_ptr, length);
   1.214 +#endif
   1.215 +
   1.216 +#ifdef PNG_READ_sRGB_SUPPORTED
   1.217 +      else if (chunk_name == png_sRGB)
   1.218 +         png_handle_sRGB(png_ptr, info_ptr, length);
   1.219 +#endif
   1.220 +
   1.221 +#ifdef PNG_READ_iCCP_SUPPORTED
   1.222 +      else if (chunk_name == png_iCCP)
   1.223 +         png_handle_iCCP(png_ptr, info_ptr, length);
   1.224 +#endif
   1.225 +
   1.226 +#ifdef PNG_READ_sPLT_SUPPORTED
   1.227 +      else if (chunk_name == png_sPLT)
   1.228 +         png_handle_sPLT(png_ptr, info_ptr, length);
   1.229 +#endif
   1.230 +
   1.231 +#ifdef PNG_READ_tEXt_SUPPORTED
   1.232 +      else if (chunk_name == png_tEXt)
   1.233 +         png_handle_tEXt(png_ptr, info_ptr, length);
   1.234 +#endif
   1.235 +
   1.236 +#ifdef PNG_READ_tIME_SUPPORTED
   1.237 +      else if (chunk_name == png_tIME)
   1.238 +         png_handle_tIME(png_ptr, info_ptr, length);
   1.239 +#endif
   1.240 +
   1.241 +#ifdef PNG_READ_tRNS_SUPPORTED
   1.242 +      else if (chunk_name == png_tRNS)
   1.243 +         png_handle_tRNS(png_ptr, info_ptr, length);
   1.244 +#endif
   1.245 +
   1.246 +#ifdef PNG_READ_zTXt_SUPPORTED
   1.247 +      else if (chunk_name == png_zTXt)
   1.248 +         png_handle_zTXt(png_ptr, info_ptr, length);
   1.249 +#endif
   1.250 +
   1.251 +#ifdef PNG_READ_iTXt_SUPPORTED
   1.252 +      else if (chunk_name == png_iTXt)
   1.253 +         png_handle_iTXt(png_ptr, info_ptr, length);
   1.254 +#endif
   1.255 +
   1.256 +#ifdef PNG_READ_APNG_SUPPORTED
   1.257 +      else if (chunk_name == png_acTL)
   1.258 +         png_handle_acTL(png_ptr, info_ptr, length);
   1.259 +
   1.260 +      else if (chunk_name == png_fcTL)
   1.261 +         png_handle_fcTL(png_ptr, info_ptr, length);
   1.262 +
   1.263 +      else if (chunk_name == png_fdAT)
   1.264 +         png_handle_fdAT(png_ptr, info_ptr, length);
   1.265 +#endif
   1.266 +
   1.267 +      else
   1.268 +         png_handle_unknown(png_ptr, info_ptr, length,
   1.269 +            PNG_HANDLE_CHUNK_AS_DEFAULT);
   1.270 +   }
   1.271 +}
   1.272 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1.273 +
   1.274 +#ifdef PNG_READ_APNG_SUPPORTED
   1.275 +void PNGAPI
   1.276 +png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
   1.277 +{
   1.278 +    png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
   1.279 +
   1.280 +    png_debug(0, "Reading frame head");
   1.281 +
   1.282 +    if (!(png_ptr->mode & PNG_HAVE_acTL))
   1.283 +        png_error(png_ptr, "attempt to png_read_frame_head() but "
   1.284 +                           "no acTL present");
   1.285 +
   1.286 +    /* do nothing for the main IDAT */
   1.287 +    if (png_ptr->num_frames_read == 0)
   1.288 +        return;
   1.289 +
   1.290 +    png_read_reset(png_ptr);
   1.291 +    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
   1.292 +    png_ptr->mode &= ~PNG_HAVE_fcTL;
   1.293 +
   1.294 +    have_chunk_after_DAT = 0;
   1.295 +    for (;;)
   1.296 +    {
   1.297 +        png_uint_32 length = png_read_chunk_header(png_ptr);
   1.298 +
   1.299 +        if (png_ptr->chunk_name == png_IDAT)
   1.300 +        {
   1.301 +            /* discard trailing IDATs for the first frame */
   1.302 +            if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
   1.303 +                png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
   1.304 +            png_crc_finish(png_ptr, length);
   1.305 +        }
   1.306 +
   1.307 +        else if (png_ptr->chunk_name == png_fcTL)
   1.308 +        {
   1.309 +            png_handle_fcTL(png_ptr, info_ptr, length);
   1.310 +            have_chunk_after_DAT = 1;
   1.311 +        }
   1.312 +
   1.313 +        else if (png_ptr->chunk_name == png_fdAT)
   1.314 +        {
   1.315 +            png_ensure_sequence_number(png_ptr, length);
   1.316 +
   1.317 +            /* discard trailing fdATs for frames other than the first */
   1.318 +            if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
   1.319 +                png_crc_finish(png_ptr, length - 4);
   1.320 +            else if(png_ptr->mode & PNG_HAVE_fcTL)
   1.321 +            {
   1.322 +                png_ptr->idat_size = length - 4;
   1.323 +                png_ptr->mode |= PNG_HAVE_IDAT;
   1.324 +
   1.325 +                break;
   1.326 +            }
   1.327 +            else
   1.328 +                png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
   1.329 +        }
   1.330 +        else
   1.331 +        {
   1.332 +            png_warning(png_ptr, "Skipped (ignored) a chunk "
   1.333 +                                 "between APNG chunks");
   1.334 +            png_crc_finish(png_ptr, length);
   1.335 +        }
   1.336 +    }
   1.337 +}
   1.338 +#endif /* PNG_READ_APNG_SUPPORTED */
   1.339 +
   1.340 +/* Optional call to update the users info_ptr structure */
   1.341 +void PNGAPI
   1.342 +png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
   1.343 +{
   1.344 +   png_debug(1, "in png_read_update_info");
   1.345 +
   1.346 +   if (png_ptr != NULL)
   1.347 +   {
   1.348 +      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
   1.349 +      {
   1.350 +         png_read_start_row(png_ptr);
   1.351 +
   1.352 +#        ifdef PNG_READ_TRANSFORMS_SUPPORTED
   1.353 +            png_read_transform_info(png_ptr, info_ptr);
   1.354 +#        else
   1.355 +            PNG_UNUSED(info_ptr)
   1.356 +#        endif
   1.357 +      }
   1.358 +
   1.359 +      /* New in 1.6.0 this avoids the bug of doing the initializations twice */
   1.360 +      else
   1.361 +         png_app_error(png_ptr,
   1.362 +            "png_read_update_info/png_start_read_image: duplicate call");
   1.363 +   }
   1.364 +}
   1.365 +
   1.366 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
   1.367 +/* Initialize palette, background, etc, after transformations
   1.368 + * are set, but before any reading takes place.  This allows
   1.369 + * the user to obtain a gamma-corrected palette, for example.
   1.370 + * If the user doesn't call this, we will do it ourselves.
   1.371 + */
   1.372 +void PNGAPI
   1.373 +png_start_read_image(png_structrp png_ptr)
   1.374 +{
   1.375 +   png_debug(1, "in png_start_read_image");
   1.376 +
   1.377 +   if (png_ptr != NULL)
   1.378 +   {
   1.379 +      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
   1.380 +         png_read_start_row(png_ptr);
   1.381 +
   1.382 +      /* New in 1.6.0 this avoids the bug of doing the initializations twice */
   1.383 +      else
   1.384 +         png_app_error(png_ptr,
   1.385 +            "png_start_read_image/png_read_update_info: duplicate call");
   1.386 +   }
   1.387 +}
   1.388 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1.389 +
   1.390 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
   1.391 +#ifdef PNG_MNG_FEATURES_SUPPORTED
   1.392 +/* Undoes intrapixel differencing,
   1.393 + * NOTE: this is apparently only supported in the 'sequential' reader.
   1.394 + */
   1.395 +static void
   1.396 +png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
   1.397 +{
   1.398 +   png_debug(1, "in png_do_read_intrapixel");
   1.399 +
   1.400 +   if (
   1.401 +       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   1.402 +   {
   1.403 +      int bytes_per_pixel;
   1.404 +      png_uint_32 row_width = row_info->width;
   1.405 +
   1.406 +      if (row_info->bit_depth == 8)
   1.407 +      {
   1.408 +         png_bytep rp;
   1.409 +         png_uint_32 i;
   1.410 +
   1.411 +         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   1.412 +            bytes_per_pixel = 3;
   1.413 +
   1.414 +         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
   1.415 +            bytes_per_pixel = 4;
   1.416 +
   1.417 +         else
   1.418 +            return;
   1.419 +
   1.420 +         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
   1.421 +         {
   1.422 +            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
   1.423 +            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
   1.424 +         }
   1.425 +      }
   1.426 +      else if (row_info->bit_depth == 16)
   1.427 +      {
   1.428 +         png_bytep rp;
   1.429 +         png_uint_32 i;
   1.430 +
   1.431 +         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
   1.432 +            bytes_per_pixel = 6;
   1.433 +
   1.434 +         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
   1.435 +            bytes_per_pixel = 8;
   1.436 +
   1.437 +         else
   1.438 +            return;
   1.439 +
   1.440 +         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
   1.441 +         {
   1.442 +            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
   1.443 +            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
   1.444 +            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
   1.445 +            png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
   1.446 +            png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
   1.447 +            *(rp    ) = (png_byte)((red >> 8) & 0xff);
   1.448 +            *(rp + 1) = (png_byte)(red & 0xff);
   1.449 +            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
   1.450 +            *(rp + 5) = (png_byte)(blue & 0xff);
   1.451 +         }
   1.452 +      }
   1.453 +   }
   1.454 +}
   1.455 +#endif /* PNG_MNG_FEATURES_SUPPORTED */
   1.456 +
   1.457 +void PNGAPI
   1.458 +png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
   1.459 +{
   1.460 +   png_row_info row_info;
   1.461 +
   1.462 +   if (png_ptr == NULL)
   1.463 +      return;
   1.464 +
   1.465 +   png_debug2(1, "in png_read_row (row %lu, pass %d)",
   1.466 +       (unsigned long)png_ptr->row_number, png_ptr->pass);
   1.467 +
   1.468 +   /* png_read_start_row sets the information (in particular iwidth) for this
   1.469 +    * interlace pass.
   1.470 +    */
   1.471 +   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
   1.472 +      png_read_start_row(png_ptr);
   1.473 +
   1.474 +   /* 1.5.6: row_info moved out of png_struct to a local here. */
   1.475 +   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
   1.476 +   row_info.color_type = png_ptr->color_type;
   1.477 +   row_info.bit_depth = png_ptr->bit_depth;
   1.478 +   row_info.channels = png_ptr->channels;
   1.479 +   row_info.pixel_depth = png_ptr->pixel_depth;
   1.480 +   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
   1.481 +
   1.482 +   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
   1.483 +   {
   1.484 +   /* Check for transforms that have been set but were defined out */
   1.485 +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
   1.486 +   if (png_ptr->transformations & PNG_INVERT_MONO)
   1.487 +      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
   1.488 +#endif
   1.489 +
   1.490 +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
   1.491 +   if (png_ptr->transformations & PNG_FILLER)
   1.492 +      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
   1.493 +#endif
   1.494 +
   1.495 +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
   1.496 +    !defined(PNG_READ_PACKSWAP_SUPPORTED)
   1.497 +   if (png_ptr->transformations & PNG_PACKSWAP)
   1.498 +      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
   1.499 +#endif
   1.500 +
   1.501 +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
   1.502 +   if (png_ptr->transformations & PNG_PACK)
   1.503 +      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
   1.504 +#endif
   1.505 +
   1.506 +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
   1.507 +   if (png_ptr->transformations & PNG_SHIFT)
   1.508 +      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
   1.509 +#endif
   1.510 +
   1.511 +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
   1.512 +   if (png_ptr->transformations & PNG_BGR)
   1.513 +      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
   1.514 +#endif
   1.515 +
   1.516 +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
   1.517 +   if (png_ptr->transformations & PNG_SWAP_BYTES)
   1.518 +      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
   1.519 +#endif
   1.520 +   }
   1.521 +
   1.522 +#ifdef PNG_READ_INTERLACING_SUPPORTED
   1.523 +   /* If interlaced and we do not need a new row, combine row and return.
   1.524 +    * Notice that the pixels we have from previous rows have been transformed
   1.525 +    * already; we can only combine like with like (transformed or
   1.526 +    * untransformed) and, because of the libpng API for interlaced images, this
   1.527 +    * means we must transform before de-interlacing.
   1.528 +    */
   1.529 +   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
   1.530 +   {
   1.531 +      switch (png_ptr->pass)
   1.532 +      {
   1.533 +         case 0:
   1.534 +            if (png_ptr->row_number & 0x07)
   1.535 +            {
   1.536 +               if (dsp_row != NULL)
   1.537 +                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.538 +               png_read_finish_row(png_ptr);
   1.539 +               return;
   1.540 +            }
   1.541 +            break;
   1.542 +
   1.543 +         case 1:
   1.544 +            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
   1.545 +            {
   1.546 +               if (dsp_row != NULL)
   1.547 +                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.548 +
   1.549 +               png_read_finish_row(png_ptr);
   1.550 +               return;
   1.551 +            }
   1.552 +            break;
   1.553 +
   1.554 +         case 2:
   1.555 +            if ((png_ptr->row_number & 0x07) != 4)
   1.556 +            {
   1.557 +               if (dsp_row != NULL && (png_ptr->row_number & 4))
   1.558 +                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.559 +
   1.560 +               png_read_finish_row(png_ptr);
   1.561 +               return;
   1.562 +            }
   1.563 +            break;
   1.564 +
   1.565 +         case 3:
   1.566 +            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
   1.567 +            {
   1.568 +               if (dsp_row != NULL)
   1.569 +                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.570 +
   1.571 +               png_read_finish_row(png_ptr);
   1.572 +               return;
   1.573 +            }
   1.574 +            break;
   1.575 +
   1.576 +         case 4:
   1.577 +            if ((png_ptr->row_number & 3) != 2)
   1.578 +            {
   1.579 +               if (dsp_row != NULL && (png_ptr->row_number & 2))
   1.580 +                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.581 +
   1.582 +               png_read_finish_row(png_ptr);
   1.583 +               return;
   1.584 +            }
   1.585 +            break;
   1.586 +
   1.587 +         case 5:
   1.588 +            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
   1.589 +            {
   1.590 +               if (dsp_row != NULL)
   1.591 +                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.592 +
   1.593 +               png_read_finish_row(png_ptr);
   1.594 +               return;
   1.595 +            }
   1.596 +            break;
   1.597 +
   1.598 +         default:
   1.599 +         case 6:
   1.600 +            if (!(png_ptr->row_number & 1))
   1.601 +            {
   1.602 +               png_read_finish_row(png_ptr);
   1.603 +               return;
   1.604 +            }
   1.605 +            break;
   1.606 +      }
   1.607 +   }
   1.608 +#endif
   1.609 +
   1.610 +   if (!(png_ptr->mode & PNG_HAVE_IDAT))
   1.611 +      png_error(png_ptr, "Invalid attempt to read row data");
   1.612 +
   1.613 +   /* Fill the row with IDAT data: */
   1.614 +   png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
   1.615 +
   1.616 +   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
   1.617 +   {
   1.618 +      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
   1.619 +         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
   1.620 +            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
   1.621 +      else
   1.622 +         png_error(png_ptr, "bad adaptive filter value");
   1.623 +   }
   1.624 +
   1.625 +   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
   1.626 +    * 1.5.6, while the buffer really is this big in current versions of libpng
   1.627 +    * it may not be in the future, so this was changed just to copy the
   1.628 +    * interlaced count:
   1.629 +    */
   1.630 +   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
   1.631 +
   1.632 +#ifdef PNG_MNG_FEATURES_SUPPORTED
   1.633 +   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
   1.634 +       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
   1.635 +   {
   1.636 +      /* Intrapixel differencing */
   1.637 +      png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
   1.638 +   }
   1.639 +#endif
   1.640 +
   1.641 +#ifdef PNG_READ_TRANSFORMS_SUPPORTED
   1.642 +   if (png_ptr->transformations)
   1.643 +      png_do_read_transformations(png_ptr, &row_info);
   1.644 +#endif
   1.645 +
   1.646 +   /* The transformed pixel depth should match the depth now in row_info. */
   1.647 +   if (png_ptr->transformed_pixel_depth == 0)
   1.648 +   {
   1.649 +      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
   1.650 +      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
   1.651 +         png_error(png_ptr, "sequential row overflow");
   1.652 +   }
   1.653 +
   1.654 +   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
   1.655 +      png_error(png_ptr, "internal sequential row size calculation error");
   1.656 +
   1.657 +#ifdef PNG_READ_INTERLACING_SUPPORTED
   1.658 +   /* Blow up interlaced rows to full size */
   1.659 +   if (png_ptr->interlaced &&
   1.660 +      (png_ptr->transformations & PNG_INTERLACE))
   1.661 +   {
   1.662 +      if (png_ptr->pass < 6)
   1.663 +         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
   1.664 +            png_ptr->transformations);
   1.665 +
   1.666 +      if (dsp_row != NULL)
   1.667 +         png_combine_row(png_ptr, dsp_row, 1/*display*/);
   1.668 +
   1.669 +      if (row != NULL)
   1.670 +         png_combine_row(png_ptr, row, 0/*row*/);
   1.671 +   }
   1.672 +
   1.673 +   else
   1.674 +#endif
   1.675 +   {
   1.676 +      if (row != NULL)
   1.677 +         png_combine_row(png_ptr, row, -1/*ignored*/);
   1.678 +
   1.679 +      if (dsp_row != NULL)
   1.680 +         png_combine_row(png_ptr, dsp_row, -1/*ignored*/);
   1.681 +   }
   1.682 +   png_read_finish_row(png_ptr);
   1.683 +
   1.684 +   if (png_ptr->read_row_fn != NULL)
   1.685 +      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
   1.686 +
   1.687 +}
   1.688 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1.689 +
   1.690 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
   1.691 +/* Read one or more rows of image data.  If the image is interlaced,
   1.692 + * and png_set_interlace_handling() has been called, the rows need to
   1.693 + * contain the contents of the rows from the previous pass.  If the
   1.694 + * image has alpha or transparency, and png_handle_alpha()[*] has been
   1.695 + * called, the rows contents must be initialized to the contents of the
   1.696 + * screen.
   1.697 + *
   1.698 + * "row" holds the actual image, and pixels are placed in it
   1.699 + * as they arrive.  If the image is displayed after each pass, it will
   1.700 + * appear to "sparkle" in.  "display_row" can be used to display a
   1.701 + * "chunky" progressive image, with finer detail added as it becomes
   1.702 + * available.  If you do not want this "chunky" display, you may pass
   1.703 + * NULL for display_row.  If you do not want the sparkle display, and
   1.704 + * you have not called png_handle_alpha(), you may pass NULL for rows.
   1.705 + * If you have called png_handle_alpha(), and the image has either an
   1.706 + * alpha channel or a transparency chunk, you must provide a buffer for
   1.707 + * rows.  In this case, you do not have to provide a display_row buffer
   1.708 + * also, but you may.  If the image is not interlaced, or if you have
   1.709 + * not called png_set_interlace_handling(), the display_row buffer will
   1.710 + * be ignored, so pass NULL to it.
   1.711 + *
   1.712 + * [*] png_handle_alpha() does not exist yet, as of this version of libpng
   1.713 + */
   1.714 +
   1.715 +void PNGAPI
   1.716 +png_read_rows(png_structrp png_ptr, png_bytepp row,
   1.717 +    png_bytepp display_row, png_uint_32 num_rows)
   1.718 +{
   1.719 +   png_uint_32 i;
   1.720 +   png_bytepp rp;
   1.721 +   png_bytepp dp;
   1.722 +
   1.723 +   png_debug(1, "in png_read_rows");
   1.724 +
   1.725 +   if (png_ptr == NULL)
   1.726 +      return;
   1.727 +
   1.728 +   rp = row;
   1.729 +   dp = display_row;
   1.730 +   if (rp != NULL && dp != NULL)
   1.731 +      for (i = 0; i < num_rows; i++)
   1.732 +      {
   1.733 +         png_bytep rptr = *rp++;
   1.734 +         png_bytep dptr = *dp++;
   1.735 +
   1.736 +         png_read_row(png_ptr, rptr, dptr);
   1.737 +      }
   1.738 +
   1.739 +   else if (rp != NULL)
   1.740 +      for (i = 0; i < num_rows; i++)
   1.741 +      {
   1.742 +         png_bytep rptr = *rp;
   1.743 +         png_read_row(png_ptr, rptr, NULL);
   1.744 +         rp++;
   1.745 +      }
   1.746 +
   1.747 +   else if (dp != NULL)
   1.748 +      for (i = 0; i < num_rows; i++)
   1.749 +      {
   1.750 +         png_bytep dptr = *dp;
   1.751 +         png_read_row(png_ptr, NULL, dptr);
   1.752 +         dp++;
   1.753 +      }
   1.754 +}
   1.755 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1.756 +
   1.757 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
   1.758 +/* Read the entire image.  If the image has an alpha channel or a tRNS
   1.759 + * chunk, and you have called png_handle_alpha()[*], you will need to
   1.760 + * initialize the image to the current image that PNG will be overlaying.
   1.761 + * We set the num_rows again here, in case it was incorrectly set in
   1.762 + * png_read_start_row() by a call to png_read_update_info() or
   1.763 + * png_start_read_image() if png_set_interlace_handling() wasn't called
   1.764 + * prior to either of these functions like it should have been.  You can
   1.765 + * only call this function once.  If you desire to have an image for
   1.766 + * each pass of a interlaced image, use png_read_rows() instead.
   1.767 + *
   1.768 + * [*] png_handle_alpha() does not exist yet, as of this version of libpng
   1.769 + */
   1.770 +void PNGAPI
   1.771 +png_read_image(png_structrp png_ptr, png_bytepp image)
   1.772 +{
   1.773 +   png_uint_32 i, image_height;
   1.774 +   int pass, j;
   1.775 +   png_bytepp rp;
   1.776 +
   1.777 +   png_debug(1, "in png_read_image");
   1.778 +
   1.779 +   if (png_ptr == NULL)
   1.780 +      return;
   1.781 +
   1.782 +#ifdef PNG_READ_INTERLACING_SUPPORTED
   1.783 +   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
   1.784 +   {
   1.785 +      pass = png_set_interlace_handling(png_ptr);
   1.786 +      /* And make sure transforms are initialized. */
   1.787 +      png_start_read_image(png_ptr);
   1.788 +   }
   1.789 +   else
   1.790 +   {
   1.791 +      if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
   1.792 +      {
   1.793 +         /* Caller called png_start_read_image or png_read_update_info without
   1.794 +          * first turning on the PNG_INTERLACE transform.  We can fix this here,
   1.795 +          * but the caller should do it!
   1.796 +          */
   1.797 +         png_warning(png_ptr, "Interlace handling should be turned on when "
   1.798 +            "using png_read_image");
   1.799 +         /* Make sure this is set correctly */
   1.800 +         png_ptr->num_rows = png_ptr->height;
   1.801 +      }
   1.802 +
   1.803 +      /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
   1.804 +       * the above error case.
   1.805 +       */
   1.806 +      pass = png_set_interlace_handling(png_ptr);
   1.807 +   }
   1.808 +#else
   1.809 +   if (png_ptr->interlaced)
   1.810 +      png_error(png_ptr,
   1.811 +          "Cannot read interlaced image -- interlace handler disabled");
   1.812 +
   1.813 +   pass = 1;
   1.814 +#endif
   1.815 +
   1.816 +   image_height=png_ptr->height;
   1.817 +
   1.818 +   for (j = 0; j < pass; j++)
   1.819 +   {
   1.820 +      rp = image;
   1.821 +      for (i = 0; i < image_height; i++)
   1.822 +      {
   1.823 +         png_read_row(png_ptr, *rp, NULL);
   1.824 +         rp++;
   1.825 +      }
   1.826 +   }
   1.827 +}
   1.828 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1.829 +
   1.830 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
   1.831 +/* Read the end of the PNG file.  Will not read past the end of the
   1.832 + * file, will verify the end is accurate, and will read any comments
   1.833 + * or time information at the end of the file, if info is not NULL.
   1.834 + */
   1.835 +void PNGAPI
   1.836 +png_read_end(png_structrp png_ptr, png_inforp info_ptr)
   1.837 +{
   1.838 +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   1.839 +   int keep;
   1.840 +#endif
   1.841 +
   1.842 +   png_debug(1, "in png_read_end");
   1.843 +
   1.844 +   if (png_ptr == NULL)
   1.845 +      return;
   1.846 +
   1.847 +   /* If png_read_end is called in the middle of reading the rows there may
   1.848 +    * still be pending IDAT data and an owned zstream.  Deal with this here.
   1.849 +    */
   1.850 +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   1.851 +   if (!png_chunk_unknown_handling(png_ptr, png_IDAT))
   1.852 +#endif
   1.853 +      png_read_finish_IDAT(png_ptr);
   1.854 +
   1.855 +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
   1.856 +   /* Report invalid palette index; added at libng-1.5.10 */
   1.857 +   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
   1.858 +      png_ptr->num_palette_max > png_ptr->num_palette)
   1.859 +     png_benign_error(png_ptr, "Read palette index exceeding num_palette");
   1.860 +#endif
   1.861 +
   1.862 +   do
   1.863 +   {
   1.864 +      png_uint_32 length = png_read_chunk_header(png_ptr);
   1.865 +      png_uint_32 chunk_name = png_ptr->chunk_name;
   1.866 +
   1.867 +      if (chunk_name == png_IEND)
   1.868 +         png_handle_IEND(png_ptr, info_ptr, length);
   1.869 +
   1.870 +      else if (chunk_name == png_IHDR)
   1.871 +         png_handle_IHDR(png_ptr, info_ptr, length);
   1.872 +
   1.873 +      else if (info_ptr == NULL)
   1.874 +         png_crc_finish(png_ptr, length);
   1.875 +
   1.876 +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   1.877 +      else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
   1.878 +      {
   1.879 +         if (chunk_name == png_IDAT)
   1.880 +         {
   1.881 +            if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
   1.882 +               png_benign_error(png_ptr, "Too many IDATs found");
   1.883 +         }
   1.884 +         png_handle_unknown(png_ptr, info_ptr, length, keep);
   1.885 +         if (chunk_name == png_PLTE)
   1.886 +            png_ptr->mode |= PNG_HAVE_PLTE;
   1.887 +      }
   1.888 +#endif
   1.889 +
   1.890 +      else if (chunk_name == png_IDAT)
   1.891 +      {
   1.892 +         /* Zero length IDATs are legal after the last IDAT has been
   1.893 +          * read, but not after other chunks have been read.
   1.894 +          */
   1.895 +         if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
   1.896 +            png_benign_error(png_ptr, "Too many IDATs found");
   1.897 +
   1.898 +         png_crc_finish(png_ptr, length);
   1.899 +      }
   1.900 +      else if (chunk_name == png_PLTE)
   1.901 +         png_handle_PLTE(png_ptr, info_ptr, length);
   1.902 +
   1.903 +#ifdef PNG_READ_bKGD_SUPPORTED
   1.904 +      else if (chunk_name == png_bKGD)
   1.905 +         png_handle_bKGD(png_ptr, info_ptr, length);
   1.906 +#endif
   1.907 +
   1.908 +#ifdef PNG_READ_cHRM_SUPPORTED
   1.909 +      else if (chunk_name == png_cHRM)
   1.910 +         png_handle_cHRM(png_ptr, info_ptr, length);
   1.911 +#endif
   1.912 +
   1.913 +#ifdef PNG_READ_gAMA_SUPPORTED
   1.914 +      else if (chunk_name == png_gAMA)
   1.915 +         png_handle_gAMA(png_ptr, info_ptr, length);
   1.916 +#endif
   1.917 +
   1.918 +#ifdef PNG_READ_hIST_SUPPORTED
   1.919 +      else if (chunk_name == png_hIST)
   1.920 +         png_handle_hIST(png_ptr, info_ptr, length);
   1.921 +#endif
   1.922 +
   1.923 +#ifdef PNG_READ_oFFs_SUPPORTED
   1.924 +      else if (chunk_name == png_oFFs)
   1.925 +         png_handle_oFFs(png_ptr, info_ptr, length);
   1.926 +#endif
   1.927 +
   1.928 +#ifdef PNG_READ_pCAL_SUPPORTED
   1.929 +      else if (chunk_name == png_pCAL)
   1.930 +         png_handle_pCAL(png_ptr, info_ptr, length);
   1.931 +#endif
   1.932 +
   1.933 +#ifdef PNG_READ_sCAL_SUPPORTED
   1.934 +      else if (chunk_name == png_sCAL)
   1.935 +         png_handle_sCAL(png_ptr, info_ptr, length);
   1.936 +#endif
   1.937 +
   1.938 +#ifdef PNG_READ_pHYs_SUPPORTED
   1.939 +      else if (chunk_name == png_pHYs)
   1.940 +         png_handle_pHYs(png_ptr, info_ptr, length);
   1.941 +#endif
   1.942 +
   1.943 +#ifdef PNG_READ_sBIT_SUPPORTED
   1.944 +      else if (chunk_name == png_sBIT)
   1.945 +         png_handle_sBIT(png_ptr, info_ptr, length);
   1.946 +#endif
   1.947 +
   1.948 +#ifdef PNG_READ_sRGB_SUPPORTED
   1.949 +      else if (chunk_name == png_sRGB)
   1.950 +         png_handle_sRGB(png_ptr, info_ptr, length);
   1.951 +#endif
   1.952 +
   1.953 +#ifdef PNG_READ_iCCP_SUPPORTED
   1.954 +      else if (chunk_name == png_iCCP)
   1.955 +         png_handle_iCCP(png_ptr, info_ptr, length);
   1.956 +#endif
   1.957 +
   1.958 +#ifdef PNG_READ_sPLT_SUPPORTED
   1.959 +      else if (chunk_name == png_sPLT)
   1.960 +         png_handle_sPLT(png_ptr, info_ptr, length);
   1.961 +#endif
   1.962 +
   1.963 +#ifdef PNG_READ_tEXt_SUPPORTED
   1.964 +      else if (chunk_name == png_tEXt)
   1.965 +         png_handle_tEXt(png_ptr, info_ptr, length);
   1.966 +#endif
   1.967 +
   1.968 +#ifdef PNG_READ_tIME_SUPPORTED
   1.969 +      else if (chunk_name == png_tIME)
   1.970 +         png_handle_tIME(png_ptr, info_ptr, length);
   1.971 +#endif
   1.972 +
   1.973 +#ifdef PNG_READ_tRNS_SUPPORTED
   1.974 +      else if (chunk_name == png_tRNS)
   1.975 +         png_handle_tRNS(png_ptr, info_ptr, length);
   1.976 +#endif
   1.977 +
   1.978 +#ifdef PNG_READ_zTXt_SUPPORTED
   1.979 +      else if (chunk_name == png_zTXt)
   1.980 +         png_handle_zTXt(png_ptr, info_ptr, length);
   1.981 +#endif
   1.982 +
   1.983 +#ifdef PNG_READ_iTXt_SUPPORTED
   1.984 +      else if (chunk_name == png_iTXt)
   1.985 +         png_handle_iTXt(png_ptr, info_ptr, length);
   1.986 +#endif
   1.987 +
   1.988 +      else
   1.989 +         png_handle_unknown(png_ptr, info_ptr, length,
   1.990 +            PNG_HANDLE_CHUNK_AS_DEFAULT);
   1.991 +   } while (!(png_ptr->mode & PNG_HAVE_IEND));
   1.992 +}
   1.993 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1.994 +
   1.995 +/* Free all memory used in the read struct */
   1.996 +static void
   1.997 +png_read_destroy(png_structrp png_ptr)
   1.998 +{
   1.999 +   png_debug(1, "in png_read_destroy");
  1.1000 +
  1.1001 +#ifdef PNG_READ_GAMMA_SUPPORTED
  1.1002 +   png_destroy_gamma_table(png_ptr);
  1.1003 +#endif
  1.1004 +
  1.1005 +   png_free(png_ptr, png_ptr->big_row_buf);
  1.1006 +   png_free(png_ptr, png_ptr->big_prev_row);
  1.1007 +   png_free(png_ptr, png_ptr->read_buffer);
  1.1008 +
  1.1009 +#ifdef PNG_READ_QUANTIZE_SUPPORTED
  1.1010 +   png_free(png_ptr, png_ptr->palette_lookup);
  1.1011 +   png_free(png_ptr, png_ptr->quantize_index);
  1.1012 +#endif
  1.1013 +
  1.1014 +   if (png_ptr->free_me & PNG_FREE_PLTE)
  1.1015 +      png_zfree(png_ptr, png_ptr->palette);
  1.1016 +   png_ptr->free_me &= ~PNG_FREE_PLTE;
  1.1017 +
  1.1018 +#if defined(PNG_tRNS_SUPPORTED) || \
  1.1019 +    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
  1.1020 +   if (png_ptr->free_me & PNG_FREE_TRNS)
  1.1021 +      png_free(png_ptr, png_ptr->trans_alpha);
  1.1022 +   png_ptr->free_me &= ~PNG_FREE_TRNS;
  1.1023 +#endif
  1.1024 +
  1.1025 +   inflateEnd(&png_ptr->zstream);
  1.1026 +
  1.1027 +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  1.1028 +   png_free(png_ptr, png_ptr->save_buffer);
  1.1029 +#endif
  1.1030 +
  1.1031 +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\
  1.1032 +   defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
  1.1033 +   png_free(png_ptr, png_ptr->unknown_chunk.data);
  1.1034 +#endif
  1.1035 +
  1.1036 +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
  1.1037 +   png_free(png_ptr, png_ptr->chunk_list);
  1.1038 +#endif
  1.1039 +
  1.1040 +   /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
  1.1041 +    * callbacks are still set at this point.  They are required to complete the
  1.1042 +    * destruction of the png_struct itself.
  1.1043 +    */
  1.1044 +}
  1.1045 +
  1.1046 +/* Free all memory used by the read */
  1.1047 +void PNGAPI
  1.1048 +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
  1.1049 +    png_infopp end_info_ptr_ptr)
  1.1050 +{
  1.1051 +   png_structrp png_ptr = NULL;
  1.1052 +
  1.1053 +   png_debug(1, "in png_destroy_read_struct");
  1.1054 +
  1.1055 +   if (png_ptr_ptr != NULL)
  1.1056 +      png_ptr = *png_ptr_ptr;
  1.1057 +
  1.1058 +   if (png_ptr == NULL)
  1.1059 +      return;
  1.1060 +
  1.1061 +   /* libpng 1.6.0: use the API to destroy info structs to ensure consistent
  1.1062 +    * behavior.  Prior to 1.6.0 libpng did extra 'info' destruction in this API.
  1.1063 +    * The extra was, apparently, unnecessary yet this hides memory leak bugs.
  1.1064 +    */
  1.1065 +   png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
  1.1066 +   png_destroy_info_struct(png_ptr, info_ptr_ptr);
  1.1067 +
  1.1068 +   *png_ptr_ptr = NULL;
  1.1069 +   png_read_destroy(png_ptr);
  1.1070 +   png_destroy_png_struct(png_ptr);
  1.1071 +}
  1.1072 +
  1.1073 +void PNGAPI
  1.1074 +png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
  1.1075 +{
  1.1076 +   if (png_ptr == NULL)
  1.1077 +      return;
  1.1078 +
  1.1079 +   png_ptr->read_row_fn = read_row_fn;
  1.1080 +}
  1.1081 +
  1.1082 +
  1.1083 +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
  1.1084 +#ifdef PNG_INFO_IMAGE_SUPPORTED
  1.1085 +void PNGAPI
  1.1086 +png_read_png(png_structrp png_ptr, png_inforp info_ptr,
  1.1087 +                           int transforms,
  1.1088 +                           voidp params)
  1.1089 +{
  1.1090 +   if (png_ptr == NULL || info_ptr == NULL)
  1.1091 +      return;
  1.1092 +
  1.1093 +   /* png_read_info() gives us all of the information from the
  1.1094 +    * PNG file before the first IDAT (image data chunk).
  1.1095 +    */
  1.1096 +   png_read_info(png_ptr, info_ptr);
  1.1097 +   if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
  1.1098 +      png_error(png_ptr, "Image is too high to process with png_read_png()");
  1.1099 +
  1.1100 +   /* -------------- image transformations start here ------------------- */
  1.1101 +   /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
  1.1102 +    * is not implemented.  This will only happen in de-configured (non-default)
  1.1103 +    * libpng builds.  The results can be unexpected - png_read_png may return
  1.1104 +    * short or mal-formed rows because the transform is skipped.
  1.1105 +    */
  1.1106 +
  1.1107 +   /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
  1.1108 +    */
  1.1109 +   if (transforms & PNG_TRANSFORM_SCALE_16)
  1.1110 +     /* Added at libpng-1.5.4. "strip_16" produces the same result that it
  1.1111 +      * did in earlier versions, while "scale_16" is now more accurate.
  1.1112 +      */
  1.1113 +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
  1.1114 +      png_set_scale_16(png_ptr);
  1.1115 +#else
  1.1116 +      png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
  1.1117 +#endif
  1.1118 +
  1.1119 +   /* If both SCALE and STRIP are required pngrtran will effectively cancel the
  1.1120 +    * latter by doing SCALE first.  This is ok and allows apps not to check for
  1.1121 +    * which is supported to get the right answer.
  1.1122 +    */
  1.1123 +   if (transforms & PNG_TRANSFORM_STRIP_16)
  1.1124 +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
  1.1125 +      png_set_strip_16(png_ptr);
  1.1126 +#else
  1.1127 +      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
  1.1128 +#endif
  1.1129 +
  1.1130 +   /* Strip alpha bytes from the input data without combining with
  1.1131 +    * the background (not recommended).
  1.1132 +    */
  1.1133 +   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
  1.1134 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
  1.1135 +      png_set_strip_alpha(png_ptr);
  1.1136 +#else
  1.1137 +      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
  1.1138 +#endif
  1.1139 +
  1.1140 +   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
  1.1141 +    * byte into separate bytes (useful for paletted and grayscale images).
  1.1142 +    */
  1.1143 +   if (transforms & PNG_TRANSFORM_PACKING)
  1.1144 +#ifdef PNG_READ_PACK_SUPPORTED
  1.1145 +      png_set_packing(png_ptr);
  1.1146 +#else
  1.1147 +      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
  1.1148 +#endif
  1.1149 +
  1.1150 +   /* Change the order of packed pixels to least significant bit first
  1.1151 +    * (not useful if you are using png_set_packing).
  1.1152 +    */
  1.1153 +   if (transforms & PNG_TRANSFORM_PACKSWAP)
  1.1154 +#ifdef PNG_READ_PACKSWAP_SUPPORTED
  1.1155 +      png_set_packswap(png_ptr);
  1.1156 +#else
  1.1157 +      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
  1.1158 +#endif
  1.1159 +
  1.1160 +   /* Expand paletted colors into true RGB triplets
  1.1161 +    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
  1.1162 +    * Expand paletted or RGB images with transparency to full alpha
  1.1163 +    * channels so the data will be available as RGBA quartets.
  1.1164 +    */
  1.1165 +   if (transforms & PNG_TRANSFORM_EXPAND)
  1.1166 +#ifdef PNG_READ_EXPAND_SUPPORTED
  1.1167 +      png_set_expand(png_ptr);
  1.1168 +#else
  1.1169 +      png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
  1.1170 +#endif
  1.1171 +
  1.1172 +   /* We don't handle background color or gamma transformation or quantizing.
  1.1173 +    */
  1.1174 +
  1.1175 +   /* Invert monochrome files to have 0 as white and 1 as black
  1.1176 +    */
  1.1177 +   if (transforms & PNG_TRANSFORM_INVERT_MONO)
  1.1178 +#ifdef PNG_READ_INVERT_SUPPORTED
  1.1179 +      png_set_invert_mono(png_ptr);
  1.1180 +#else
  1.1181 +      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
  1.1182 +#endif
  1.1183 +
  1.1184 +   /* If you want to shift the pixel values from the range [0,255] or
  1.1185 +    * [0,65535] to the original [0,7] or [0,31], or whatever range the
  1.1186 +    * colors were originally in:
  1.1187 +    */
  1.1188 +   if (transforms & PNG_TRANSFORM_SHIFT)
  1.1189 +#ifdef PNG_READ_SHIFT_SUPPORTED
  1.1190 +      if (info_ptr->valid & PNG_INFO_sBIT)
  1.1191 +         png_set_shift(png_ptr, &info_ptr->sig_bit);
  1.1192 +#else
  1.1193 +      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
  1.1194 +#endif
  1.1195 +
  1.1196 +   /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
  1.1197 +   if (transforms & PNG_TRANSFORM_BGR)
  1.1198 +#ifdef PNG_READ_BGR_SUPPORTED
  1.1199 +      png_set_bgr(png_ptr);
  1.1200 +#else
  1.1201 +      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
  1.1202 +#endif
  1.1203 +
  1.1204 +   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
  1.1205 +   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
  1.1206 +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
  1.1207 +      png_set_swap_alpha(png_ptr);
  1.1208 +#else
  1.1209 +      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
  1.1210 +#endif
  1.1211 +
  1.1212 +   /* Swap bytes of 16-bit files to least significant byte first */
  1.1213 +   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
  1.1214 +#ifdef PNG_READ_SWAP_SUPPORTED
  1.1215 +      png_set_swap(png_ptr);
  1.1216 +#else
  1.1217 +      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
  1.1218 +#endif
  1.1219 +
  1.1220 +/* Added at libpng-1.2.41 */
  1.1221 +   /* Invert the alpha channel from opacity to transparency */
  1.1222 +   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
  1.1223 +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
  1.1224 +      png_set_invert_alpha(png_ptr);
  1.1225 +#else
  1.1226 +      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
  1.1227 +#endif
  1.1228 +
  1.1229 +/* Added at libpng-1.2.41 */
  1.1230 +   /* Expand grayscale image to RGB */
  1.1231 +   if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
  1.1232 +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
  1.1233 +      png_set_gray_to_rgb(png_ptr);
  1.1234 +#else
  1.1235 +      png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
  1.1236 +#endif
  1.1237 +
  1.1238 +/* Added at libpng-1.5.4 */
  1.1239 +   if (transforms & PNG_TRANSFORM_EXPAND_16)
  1.1240 +#ifdef PNG_READ_EXPAND_16_SUPPORTED
  1.1241 +      png_set_expand_16(png_ptr);
  1.1242 +#else
  1.1243 +      png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
  1.1244 +#endif
  1.1245 +
  1.1246 +   /* We don't handle adding filler bytes */
  1.1247 +
  1.1248 +   /* We use png_read_image and rely on that for interlace handling, but we also
  1.1249 +    * call png_read_update_info therefore must turn on interlace handling now:
  1.1250 +    */
  1.1251 +   (void)png_set_interlace_handling(png_ptr);
  1.1252 +
  1.1253 +   /* Optional call to gamma correct and add the background to the palette
  1.1254 +    * and update info structure.  REQUIRED if you are expecting libpng to
  1.1255 +    * update the palette for you (i.e., you selected such a transform above).
  1.1256 +    */
  1.1257 +   png_read_update_info(png_ptr, info_ptr);
  1.1258 +
  1.1259 +   /* -------------- image transformations end here ------------------- */
  1.1260 +
  1.1261 +   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
  1.1262 +   if (info_ptr->row_pointers == NULL)
  1.1263 +   {
  1.1264 +      png_uint_32 iptr;
  1.1265 +
  1.1266 +      info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
  1.1267 +          info_ptr->height * (sizeof (png_bytep))));
  1.1268 +
  1.1269 +      for (iptr=0; iptr<info_ptr->height; iptr++)
  1.1270 +         info_ptr->row_pointers[iptr] = NULL;
  1.1271 +
  1.1272 +      info_ptr->free_me |= PNG_FREE_ROWS;
  1.1273 +
  1.1274 +      for (iptr = 0; iptr < info_ptr->height; iptr++)
  1.1275 +         info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
  1.1276 +            png_malloc(png_ptr, info_ptr->rowbytes));
  1.1277 +   }
  1.1278 +
  1.1279 +   png_read_image(png_ptr, info_ptr->row_pointers);
  1.1280 +   info_ptr->valid |= PNG_INFO_IDAT;
  1.1281 +
  1.1282 +   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
  1.1283 +   png_read_end(png_ptr, info_ptr);
  1.1284 +
  1.1285 +   PNG_UNUSED(params)
  1.1286 +}
  1.1287 +#endif /* PNG_INFO_IMAGE_SUPPORTED */
  1.1288 +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
  1.1289 +
  1.1290 +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
  1.1291 +/* SIMPLIFIED READ
  1.1292 + *
  1.1293 + * This code currently relies on the sequential reader, though it could easily
  1.1294 + * be made to work with the progressive one.
  1.1295 + */
  1.1296 +/* Arguments to png_image_finish_read: */
  1.1297 +
  1.1298 +/* Encoding of PNG data (used by the color-map code) */
  1.1299 +#  define P_NOTSET  0 /* File encoding not yet known */
  1.1300 +#  define P_sRGB    1 /* 8-bit encoded to sRGB gamma */
  1.1301 +#  define P_LINEAR  2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
  1.1302 +#  define P_FILE    3 /* 8-bit encoded to file gamma, not sRGB or linear */
  1.1303 +#  define P_LINEAR8 4 /* 8-bit linear: only from a file value */
  1.1304 +
  1.1305 +/* Color-map processing: after libpng has run on the PNG image further
  1.1306 + * processing may be needed to conver the data to color-map indicies.
  1.1307 + */
  1.1308 +#define PNG_CMAP_NONE      0
  1.1309 +#define PNG_CMAP_GA        1 /* Process GA data to a color-map with alpha */
  1.1310 +#define PNG_CMAP_TRANS     2 /* Process GA data to a background index */
  1.1311 +#define PNG_CMAP_RGB       3 /* Process RGB data */
  1.1312 +#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */
  1.1313 +
  1.1314 +/* The following document where the background is for each processing case. */
  1.1315 +#define PNG_CMAP_NONE_BACKGROUND      256
  1.1316 +#define PNG_CMAP_GA_BACKGROUND        231
  1.1317 +#define PNG_CMAP_TRANS_BACKGROUND     254
  1.1318 +#define PNG_CMAP_RGB_BACKGROUND       256
  1.1319 +#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
  1.1320 +
  1.1321 +typedef struct
  1.1322 +{
  1.1323 +   /* Arguments: */
  1.1324 +   png_imagep image;
  1.1325 +   png_voidp  buffer;
  1.1326 +   png_int_32 row_stride;
  1.1327 +   png_voidp  colormap;
  1.1328 +   png_const_colorp background;
  1.1329 +   /* Local variables: */
  1.1330 +   png_voidp       local_row;
  1.1331 +   png_voidp       first_row;
  1.1332 +   ptrdiff_t       row_bytes;           /* step between rows */
  1.1333 +   int             file_encoding;       /* E_ values above */
  1.1334 +   png_fixed_point gamma_to_linear;     /* For P_FILE, reciprocal of gamma */
  1.1335 +   int             colormap_processing; /* PNG_CMAP_ values above */
  1.1336 +} png_image_read_control;
  1.1337 +
  1.1338 +/* Do all the *safe* initialization - 'safe' means that png_error won't be
  1.1339 + * called, so setting up the jmp_buf is not required.  This means that anything
  1.1340 + * called from here must *not* call png_malloc - it has to call png_malloc_warn
  1.1341 + * instead so that control is returned safely back to this routine.
  1.1342 + */
  1.1343 +static int
  1.1344 +png_image_read_init(png_imagep image)
  1.1345 +{
  1.1346 +   if (image->opaque == NULL)
  1.1347 +   {
  1.1348 +      png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
  1.1349 +          png_safe_error, png_safe_warning);
  1.1350 +
  1.1351 +      /* And set the rest of the structure to NULL to ensure that the various
  1.1352 +       * fields are consistent.
  1.1353 +       */
  1.1354 +      memset(image, 0, (sizeof *image));
  1.1355 +      image->version = PNG_IMAGE_VERSION;
  1.1356 +
  1.1357 +      if (png_ptr != NULL)
  1.1358 +      {
  1.1359 +         png_infop info_ptr = png_create_info_struct(png_ptr);
  1.1360 +
  1.1361 +         if (info_ptr != NULL)
  1.1362 +         {
  1.1363 +            png_controlp control = png_voidcast(png_controlp,
  1.1364 +               png_malloc_warn(png_ptr, (sizeof *control)));
  1.1365 +
  1.1366 +            if (control != NULL)
  1.1367 +            {
  1.1368 +               memset(control, 0, (sizeof *control));
  1.1369 +
  1.1370 +               control->png_ptr = png_ptr;
  1.1371 +               control->info_ptr = info_ptr;
  1.1372 +               control->for_write = 0;
  1.1373 +
  1.1374 +               image->opaque = control;
  1.1375 +               return 1;
  1.1376 +            }
  1.1377 +
  1.1378 +            /* Error clean up */
  1.1379 +            png_destroy_info_struct(png_ptr, &info_ptr);
  1.1380 +         }
  1.1381 +
  1.1382 +         png_destroy_read_struct(&png_ptr, NULL, NULL);
  1.1383 +      }
  1.1384 +
  1.1385 +      return png_image_error(image, "png_image_read: out of memory");
  1.1386 +   }
  1.1387 +
  1.1388 +   return png_image_error(image, "png_image_read: opaque pointer not NULL");
  1.1389 +}
  1.1390 +
  1.1391 +/* Utility to find the base format of a PNG file from a png_struct. */
  1.1392 +static png_uint_32
  1.1393 +png_image_format(png_structrp png_ptr)
  1.1394 +{
  1.1395 +   png_uint_32 format = 0;
  1.1396 +
  1.1397 +   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
  1.1398 +      format |= PNG_FORMAT_FLAG_COLOR;
  1.1399 +
  1.1400 +   if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)
  1.1401 +      format |= PNG_FORMAT_FLAG_ALPHA;
  1.1402 +
  1.1403 +   /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS
  1.1404 +    * sets the png_struct fields; that's all we are interested in here.  The
  1.1405 +    * precise interaction with an app call to png_set_tRNS and PNG file reading
  1.1406 +    * is unclear.
  1.1407 +    */
  1.1408 +   else if (png_ptr->num_trans > 0)
  1.1409 +      format |= PNG_FORMAT_FLAG_ALPHA;
  1.1410 +
  1.1411 +   if (png_ptr->bit_depth == 16)
  1.1412 +      format |= PNG_FORMAT_FLAG_LINEAR;
  1.1413 +
  1.1414 +   if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE)
  1.1415 +      format |= PNG_FORMAT_FLAG_COLORMAP;
  1.1416 +
  1.1417 +   return format;
  1.1418 +}
  1.1419 +
  1.1420 +/* Is the given gamma significantly different from sRGB?  The test is the same
  1.1421 + * one used in pngrtran.c when deciding whether to do gamma correction.  The
  1.1422 + * arithmetic optimizes the division by using the fact that the inverse of the
  1.1423 + * file sRGB gamma is 2.2
  1.1424 + */
  1.1425 +static int
  1.1426 +png_gamma_not_sRGB(png_fixed_point g)
  1.1427 +{
  1.1428 +   if (g < PNG_FP_1)
  1.1429 +   {
  1.1430 +      /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
  1.1431 +      if (g == 0)
  1.1432 +         return 0;
  1.1433 +
  1.1434 +      return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
  1.1435 +   }
  1.1436 +
  1.1437 +   return 1;
  1.1438 +}
  1.1439 +
  1.1440 +/* Do the main body of a 'png_image_begin_read' function; read the PNG file
  1.1441 + * header and fill in all the information.  This is executed in a safe context,
  1.1442 + * unlike the init routine above.
  1.1443 + */
  1.1444 +static int
  1.1445 +png_image_read_header(png_voidp argument)
  1.1446 +{
  1.1447 +   png_imagep image = png_voidcast(png_imagep, argument);
  1.1448 +   png_structrp png_ptr = image->opaque->png_ptr;
  1.1449 +   png_inforp info_ptr = image->opaque->info_ptr;
  1.1450 +
  1.1451 +   png_set_benign_errors(png_ptr, 1/*warn*/);
  1.1452 +   png_read_info(png_ptr, info_ptr);
  1.1453 +
  1.1454 +   /* Do this the fast way; just read directly out of png_struct. */
  1.1455 +   image->width = png_ptr->width;
  1.1456 +   image->height = png_ptr->height;
  1.1457 +
  1.1458 +   {
  1.1459 +      png_uint_32 format = png_image_format(png_ptr);
  1.1460 +
  1.1461 +      image->format = format;
  1.1462 +
  1.1463 +#ifdef PNG_COLORSPACE_SUPPORTED
  1.1464 +      /* Does the colorspace match sRGB?  If there is no color endpoint
  1.1465 +       * (colorant) information assume yes, otherwise require the
  1.1466 +       * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set.  If the
  1.1467 +       * colorspace has been determined to be invalid ignore it.
  1.1468 +       */
  1.1469 +      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
  1.1470 +         & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
  1.1471 +            PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
  1.1472 +         image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
  1.1473 +#endif
  1.1474 +   }
  1.1475 +
  1.1476 +   /* We need the maximum number of entries regardless of the format the
  1.1477 +    * application sets here.
  1.1478 +    */
  1.1479 +   {
  1.1480 +      png_uint_32 cmap_entries;
  1.1481 +
  1.1482 +      switch (png_ptr->color_type)
  1.1483 +      {
  1.1484 +         case PNG_COLOR_TYPE_GRAY:
  1.1485 +            cmap_entries = 1U << png_ptr->bit_depth;
  1.1486 +            break;
  1.1487 +
  1.1488 +         case PNG_COLOR_TYPE_PALETTE:
  1.1489 +            cmap_entries = png_ptr->num_palette;
  1.1490 +            break;
  1.1491 +
  1.1492 +         default:
  1.1493 +            cmap_entries = 256;
  1.1494 +            break;
  1.1495 +      }
  1.1496 +
  1.1497 +      if (cmap_entries > 256)
  1.1498 +         cmap_entries = 256;
  1.1499 +
  1.1500 +      image->colormap_entries = cmap_entries;
  1.1501 +   }
  1.1502 +
  1.1503 +   return 1;
  1.1504 +}
  1.1505 +
  1.1506 +#ifdef PNG_STDIO_SUPPORTED
  1.1507 +int PNGAPI
  1.1508 +png_image_begin_read_from_stdio(png_imagep image, FILE* file)
  1.1509 +{
  1.1510 +   if (image != NULL && image->version == PNG_IMAGE_VERSION)
  1.1511 +   {
  1.1512 +      if (file != NULL)
  1.1513 +      {
  1.1514 +         if (png_image_read_init(image))
  1.1515 +         {
  1.1516 +            /* This is slightly evil, but png_init_io doesn't do anything other
  1.1517 +             * than this and we haven't changed the standard IO functions so
  1.1518 +             * this saves a 'safe' function.
  1.1519 +             */
  1.1520 +            image->opaque->png_ptr->io_ptr = file;
  1.1521 +            return png_safe_execute(image, png_image_read_header, image);
  1.1522 +         }
  1.1523 +      }
  1.1524 +
  1.1525 +      else
  1.1526 +         return png_image_error(image,
  1.1527 +            "png_image_begin_read_from_stdio: invalid argument");
  1.1528 +   }
  1.1529 +
  1.1530 +   else if (image != NULL)
  1.1531 +      return png_image_error(image,
  1.1532 +         "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
  1.1533 +
  1.1534 +   return 0;
  1.1535 +}
  1.1536 +
  1.1537 +int PNGAPI
  1.1538 +png_image_begin_read_from_file(png_imagep image, const char *file_name)
  1.1539 +{
  1.1540 +   if (image != NULL && image->version == PNG_IMAGE_VERSION)
  1.1541 +   {
  1.1542 +      if (file_name != NULL)
  1.1543 +      {
  1.1544 +         FILE *fp = fopen(file_name, "rb");
  1.1545 +
  1.1546 +         if (fp != NULL)
  1.1547 +         {
  1.1548 +            if (png_image_read_init(image))
  1.1549 +            {
  1.1550 +               image->opaque->png_ptr->io_ptr = fp;
  1.1551 +               image->opaque->owned_file = 1;
  1.1552 +               return png_safe_execute(image, png_image_read_header, image);
  1.1553 +            }
  1.1554 +
  1.1555 +            /* Clean up: just the opened file. */
  1.1556 +            (void)fclose(fp);
  1.1557 +         }
  1.1558 +
  1.1559 +         else
  1.1560 +            return png_image_error(image, strerror(errno));
  1.1561 +      }
  1.1562 +
  1.1563 +      else
  1.1564 +         return png_image_error(image,
  1.1565 +            "png_image_begin_read_from_file: invalid argument");
  1.1566 +   }
  1.1567 +
  1.1568 +   else if (image != NULL)
  1.1569 +      return png_image_error(image,
  1.1570 +         "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
  1.1571 +
  1.1572 +   return 0;
  1.1573 +}
  1.1574 +#endif /* PNG_STDIO_SUPPORTED */
  1.1575 +
  1.1576 +static void PNGCBAPI
  1.1577 +png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
  1.1578 +{
  1.1579 +   if (png_ptr != NULL)
  1.1580 +   {
  1.1581 +      png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
  1.1582 +      if (image != NULL)
  1.1583 +      {
  1.1584 +         png_controlp cp = image->opaque;
  1.1585 +         if (cp != NULL)
  1.1586 +         {
  1.1587 +            png_const_bytep memory = cp->memory;
  1.1588 +            png_size_t size = cp->size;
  1.1589 +
  1.1590 +            if (memory != NULL && size >= need)
  1.1591 +            {
  1.1592 +               memcpy(out, memory, need);
  1.1593 +               cp->memory = memory + need;
  1.1594 +               cp->size = size - need;
  1.1595 +               return;
  1.1596 +            }
  1.1597 +
  1.1598 +            png_error(png_ptr, "read beyond end of data");
  1.1599 +         }
  1.1600 +      }
  1.1601 +
  1.1602 +      png_error(png_ptr, "invalid memory read");
  1.1603 +   }
  1.1604 +}
  1.1605 +
  1.1606 +int PNGAPI png_image_begin_read_from_memory(png_imagep image,
  1.1607 +   png_const_voidp memory, png_size_t size)
  1.1608 +{
  1.1609 +   if (image != NULL && image->version == PNG_IMAGE_VERSION)
  1.1610 +   {
  1.1611 +      if (memory != NULL && size > 0)
  1.1612 +      {
  1.1613 +         if (png_image_read_init(image))
  1.1614 +         {
  1.1615 +            /* Now set the IO functions to read from the memory buffer and
  1.1616 +             * store it into io_ptr.  Again do this in-place to avoid calling a
  1.1617 +             * libpng function that requires error handling.
  1.1618 +             */
  1.1619 +            image->opaque->memory = png_voidcast(png_const_bytep, memory);
  1.1620 +            image->opaque->size = size;
  1.1621 +            image->opaque->png_ptr->io_ptr = image;
  1.1622 +            image->opaque->png_ptr->read_data_fn = png_image_memory_read;
  1.1623 +
  1.1624 +            return png_safe_execute(image, png_image_read_header, image);
  1.1625 +         }
  1.1626 +      }
  1.1627 +
  1.1628 +      else
  1.1629 +         return png_image_error(image,
  1.1630 +            "png_image_begin_read_from_memory: invalid argument");
  1.1631 +   }
  1.1632 +
  1.1633 +   else if (image != NULL)
  1.1634 +      return png_image_error(image,
  1.1635 +         "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
  1.1636 +
  1.1637 +   return 0;
  1.1638 +}
  1.1639 +
  1.1640 +/* Utility function to skip chunks that are not used by the simplified image
  1.1641 + * read functions and an appropriate macro to call it.
  1.1642 + */
  1.1643 +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
  1.1644 +static void
  1.1645 +png_image_skip_unused_chunks(png_structrp png_ptr)
  1.1646 +{
  1.1647 +   /* Prepare the reader to ignore all recognized chunks whose data will not
  1.1648 +    * be used, i.e., all chunks recognized by libpng except for those
  1.1649 +    * involved in basic image reading:
  1.1650 +    *
  1.1651 +    *    IHDR, PLTE, IDAT, IEND
  1.1652 +    *
  1.1653 +    * Or image data handling:
  1.1654 +    *
  1.1655 +    *    tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
  1.1656 +    *
  1.1657 +    * This provides a small performance improvement and eliminates any
  1.1658 +    * potential vulnerability to security problems in the unused chunks.
  1.1659 +    *
  1.1660 +    * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
  1.1661 +    * too.  This allows the simplified API to be compiled without iCCP support,
  1.1662 +    * however if the support is there the chunk is still checked to detect
  1.1663 +    * errors (which are unfortunately quite common.)
  1.1664 +    */
  1.1665 +   {
  1.1666 +         static PNG_CONST png_byte chunks_to_process[] = {
  1.1667 +            98,  75,  71,  68, '\0',  /* bKGD */
  1.1668 +            99,  72,  82,  77, '\0',  /* cHRM */
  1.1669 +           103,  65,  77,  65, '\0',  /* gAMA */
  1.1670 +#        ifdef PNG_READ_iCCP_SUPPORTED
  1.1671 +           105,  67,  67,  80, '\0',  /* iCCP */
  1.1672 +#        endif
  1.1673 +           115,  66,  73,  84, '\0',  /* sBIT */
  1.1674 +           115,  82,  71,  66, '\0',  /* sRGB */
  1.1675 +           };
  1.1676 +
  1.1677 +       /* Ignore unknown chunks and all other chunks except for the
  1.1678 +        * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
  1.1679 +        */
  1.1680 +       png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
  1.1681 +         NULL, -1);
  1.1682 +
  1.1683 +       /* But do not ignore image data handling chunks */
  1.1684 +       png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
  1.1685 +         chunks_to_process, (sizeof chunks_to_process)/5);
  1.1686 +    }
  1.1687 +}
  1.1688 +
  1.1689 +#  define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
  1.1690 +#else
  1.1691 +#  define PNG_SKIP_CHUNKS(p) ((void)0)
  1.1692 +#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */
  1.1693 +
  1.1694 +/* The following macro gives the exact rounded answer for all values in the
  1.1695 + * range 0..255 (it actually divides by 51.2, but the rounding still generates
  1.1696 + * the correct numbers 0..5
  1.1697 + */
  1.1698 +#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
  1.1699 +
  1.1700 +/* Utility functions to make particular color-maps */
  1.1701 +static void
  1.1702 +set_file_encoding(png_image_read_control *display)
  1.1703 +{
  1.1704 +   png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
  1.1705 +   if (png_gamma_significant(g))
  1.1706 +   {
  1.1707 +      if (png_gamma_not_sRGB(g))
  1.1708 +      {
  1.1709 +         display->file_encoding = P_FILE;
  1.1710 +         display->gamma_to_linear = png_reciprocal(g);
  1.1711 +      }
  1.1712 +
  1.1713 +      else
  1.1714 +         display->file_encoding = P_sRGB;
  1.1715 +   }
  1.1716 +
  1.1717 +   else
  1.1718 +      display->file_encoding = P_LINEAR8;
  1.1719 +}
  1.1720 +
  1.1721 +static unsigned int
  1.1722 +decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
  1.1723 +{
  1.1724 +   if (encoding == P_FILE) /* double check */
  1.1725 +      encoding = display->file_encoding;
  1.1726 +
  1.1727 +   if (encoding == P_NOTSET) /* must be the file encoding */
  1.1728 +   {
  1.1729 +      set_file_encoding(display);
  1.1730 +      encoding = display->file_encoding;
  1.1731 +   }
  1.1732 +
  1.1733 +   switch (encoding)
  1.1734 +   {
  1.1735 +      case P_FILE:
  1.1736 +         value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
  1.1737 +         break;
  1.1738 +
  1.1739 +      case P_sRGB:
  1.1740 +         value = png_sRGB_table[value];
  1.1741 +         break;
  1.1742 +
  1.1743 +      case P_LINEAR:
  1.1744 +         break;
  1.1745 +
  1.1746 +      case P_LINEAR8:
  1.1747 +         value *= 257;
  1.1748 +         break;
  1.1749 +
  1.1750 +      default:
  1.1751 +         png_error(display->image->opaque->png_ptr,
  1.1752 +            "unexpected encoding (internal error)");
  1.1753 +         break;
  1.1754 +   }
  1.1755 +
  1.1756 +   return value;
  1.1757 +}
  1.1758 +
  1.1759 +static png_uint_32
  1.1760 +png_colormap_compose(png_image_read_control *display,
  1.1761 +   png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
  1.1762 +   png_uint_32 background, int encoding)
  1.1763 +{
  1.1764 +   /* The file value is composed on the background, the background has the given
  1.1765 +    * encoding and so does the result, the file is encoded with P_FILE and the
  1.1766 +    * file and alpha are 8-bit values.  The (output) encoding will always be
  1.1767 +    * P_LINEAR or P_sRGB.
  1.1768 +    */
  1.1769 +   png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
  1.1770 +   png_uint_32 b = decode_gamma(display, background, encoding);
  1.1771 +
  1.1772 +   /* The alpha is always an 8-bit value (it comes from the palette), the value
  1.1773 +    * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.
  1.1774 +    */
  1.1775 +   f = f * alpha + b * (255-alpha);
  1.1776 +
  1.1777 +   if (encoding == P_LINEAR)
  1.1778 +   {
  1.1779 +      /* Scale to 65535; divide by 255, approximately (in fact this is extremely
  1.1780 +       * accurate, it divides by 255.00000005937181414556, with no overflow.)
  1.1781 +       */
  1.1782 +      f *= 257; /* Now scaled by 65535 */
  1.1783 +      f += f >> 16;
  1.1784 +      f = (f+32768) >> 16;
  1.1785 +   }
  1.1786 +
  1.1787 +   else /* P_sRGB */
  1.1788 +      f = PNG_sRGB_FROM_LINEAR(f);
  1.1789 +
  1.1790 +   return f;
  1.1791 +}
  1.1792 +
  1.1793 +/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
  1.1794 + * be 8-bit.
  1.1795 + */
  1.1796 +static void
  1.1797 +png_create_colormap_entry(png_image_read_control *display,
  1.1798 +   png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
  1.1799 +   png_uint_32 alpha, int encoding)
  1.1800 +{
  1.1801 +   png_imagep image = display->image;
  1.1802 +   const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ?
  1.1803 +      P_LINEAR : P_sRGB;
  1.1804 +   const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
  1.1805 +      (red != green || green != blue);
  1.1806 +
  1.1807 +   if (ip > 255)
  1.1808 +      png_error(image->opaque->png_ptr, "color-map index out of range");
  1.1809 +
  1.1810 +   /* Update the cache with whether the file gamma is significantly different
  1.1811 +    * from sRGB.
  1.1812 +    */
  1.1813 +   if (encoding == P_FILE)
  1.1814 +   {
  1.1815 +      if (display->file_encoding == P_NOTSET)
  1.1816 +         set_file_encoding(display);
  1.1817 +
  1.1818 +      /* Note that the cached value may be P_FILE too, but if it is then the
  1.1819 +       * gamma_to_linear member has been set.
  1.1820 +       */
  1.1821 +      encoding = display->file_encoding;
  1.1822 +   }
  1.1823 +
  1.1824 +   if (encoding == P_FILE)
  1.1825 +   {
  1.1826 +      png_fixed_point g = display->gamma_to_linear;
  1.1827 +
  1.1828 +      red = png_gamma_16bit_correct(red*257, g);
  1.1829 +      green = png_gamma_16bit_correct(green*257, g);
  1.1830 +      blue = png_gamma_16bit_correct(blue*257, g);
  1.1831 +
  1.1832 +      if (convert_to_Y || output_encoding == P_LINEAR)
  1.1833 +      {
  1.1834 +         alpha *= 257;
  1.1835 +         encoding = P_LINEAR;
  1.1836 +      }
  1.1837 +
  1.1838 +      else
  1.1839 +      {
  1.1840 +         red = PNG_sRGB_FROM_LINEAR(red * 255);
  1.1841 +         green = PNG_sRGB_FROM_LINEAR(green * 255);
  1.1842 +         blue = PNG_sRGB_FROM_LINEAR(blue * 255);
  1.1843 +         encoding = P_sRGB;
  1.1844 +      }
  1.1845 +   }
  1.1846 +
  1.1847 +   else if (encoding == P_LINEAR8)
  1.1848 +   {
  1.1849 +      /* This encoding occurs quite frequently in test cases because PngSuite
  1.1850 +       * includes a gAMA 1.0 chunk with most images.
  1.1851 +       */
  1.1852 +      red *= 257;
  1.1853 +      green *= 257;
  1.1854 +      blue *= 257;
  1.1855 +      alpha *= 257;
  1.1856 +      encoding = P_LINEAR;
  1.1857 +   }
  1.1858 +
  1.1859 +   else if (encoding == P_sRGB && (convert_to_Y || output_encoding == P_LINEAR))
  1.1860 +   {
  1.1861 +      /* The values are 8-bit sRGB values, but must be converted to 16-bit
  1.1862 +       * linear.
  1.1863 +       */
  1.1864 +      red = png_sRGB_table[red];
  1.1865 +      green = png_sRGB_table[green];
  1.1866 +      blue = png_sRGB_table[blue];
  1.1867 +      alpha *= 257;
  1.1868 +      encoding = P_LINEAR;
  1.1869 +   }
  1.1870 +
  1.1871 +   /* This is set if the color isn't gray but the output is. */
  1.1872 +   if (encoding == P_LINEAR)
  1.1873 +   {
  1.1874 +      if (convert_to_Y)
  1.1875 +      {
  1.1876 +         /* NOTE: these values are copied from png_do_rgb_to_gray */
  1.1877 +         png_uint_32 y = (png_uint_32)6968 * red  + (png_uint_32)23434 * green +
  1.1878 +            (png_uint_32)2366 * blue;
  1.1879 +
  1.1880 +         if (output_encoding == P_LINEAR)
  1.1881 +            y = (y + 16384) >> 15;
  1.1882 +
  1.1883 +         else
  1.1884 +         {
  1.1885 +            /* y is scaled by 32768, we need it scaled by 255: */
  1.1886 +            y = (y + 128) >> 8;
  1.1887 +            y *= 255;
  1.1888 +            y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
  1.1889 +            encoding = P_sRGB;
  1.1890 +         }
  1.1891 +
  1.1892 +         blue = red = green = y;
  1.1893 +      }
  1.1894 +
  1.1895 +      else if (output_encoding == P_sRGB)
  1.1896 +      {
  1.1897 +         red = PNG_sRGB_FROM_LINEAR(red * 255);
  1.1898 +         green = PNG_sRGB_FROM_LINEAR(green * 255);
  1.1899 +         blue = PNG_sRGB_FROM_LINEAR(blue * 255);
  1.1900 +         alpha = PNG_DIV257(alpha);
  1.1901 +         encoding = P_sRGB;
  1.1902 +      }
  1.1903 +   }
  1.1904 +
  1.1905 +   if (encoding != output_encoding)
  1.1906 +      png_error(image->opaque->png_ptr, "bad encoding (internal error)");
  1.1907 +
  1.1908 +   /* Store the value. */
  1.1909 +   {
  1.1910 +#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
  1.1911 +         const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
  1.1912 +            (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
  1.1913 +#     else
  1.1914 +#        define afirst 0
  1.1915 +#     endif
  1.1916 +#     ifdef PNG_FORMAT_BGR_SUPPORTED
  1.1917 +         const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0;
  1.1918 +#     else
  1.1919 +#        define bgr 0
  1.1920 +#     endif
  1.1921 +
  1.1922 +      if (output_encoding == P_LINEAR)
  1.1923 +      {
  1.1924 +         png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
  1.1925 +
  1.1926 +         entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
  1.1927 +
  1.1928 +         /* The linear 16-bit values must be pre-multiplied by the alpha channel
  1.1929 +          * value, if less than 65535 (this is, effectively, composite on black
  1.1930 +          * if the alpha channel is removed.)
  1.1931 +          */
  1.1932 +         switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
  1.1933 +         {
  1.1934 +            case 4:
  1.1935 +               entry[afirst ? 0 : 3] = (png_uint_16)alpha;
  1.1936 +               /* FALL THROUGH */
  1.1937 +
  1.1938 +            case 3:
  1.1939 +               if (alpha < 65535)
  1.1940 +               {
  1.1941 +                  if (alpha > 0)
  1.1942 +                  {
  1.1943 +                     blue = (blue * alpha + 32767U)/65535U;
  1.1944 +                     green = (green * alpha + 32767U)/65535U;
  1.1945 +                     red = (red * alpha + 32767U)/65535U;
  1.1946 +                  }
  1.1947 +
  1.1948 +                  else
  1.1949 +                     red = green = blue = 0;
  1.1950 +               }
  1.1951 +               entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
  1.1952 +               entry[afirst + 1] = (png_uint_16)green;
  1.1953 +               entry[afirst + bgr] = (png_uint_16)red;
  1.1954 +               break;
  1.1955 +
  1.1956 +            case 2:
  1.1957 +               entry[1 ^ afirst] = (png_uint_16)alpha;
  1.1958 +               /* FALL THROUGH */
  1.1959 +
  1.1960 +            case 1:
  1.1961 +               if (alpha < 65535)
  1.1962 +               {
  1.1963 +                  if (alpha > 0)
  1.1964 +                     green = (green * alpha + 32767U)/65535U;
  1.1965 +
  1.1966 +                  else
  1.1967 +                     green = 0;
  1.1968 +               }
  1.1969 +               entry[afirst] = (png_uint_16)green;
  1.1970 +               break;
  1.1971 +
  1.1972 +            default:
  1.1973 +               break;
  1.1974 +         }
  1.1975 +      }
  1.1976 +
  1.1977 +      else /* output encoding is P_sRGB */
  1.1978 +      {
  1.1979 +         png_bytep entry = png_voidcast(png_bytep, display->colormap);
  1.1980 +
  1.1981 +         entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
  1.1982 +
  1.1983 +         switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
  1.1984 +         {
  1.1985 +            case 4:
  1.1986 +               entry[afirst ? 0 : 3] = (png_byte)alpha;
  1.1987 +            case 3:
  1.1988 +               entry[afirst + (2 ^ bgr)] = (png_byte)blue;
  1.1989 +               entry[afirst + 1] = (png_byte)green;
  1.1990 +               entry[afirst + bgr] = (png_byte)red;
  1.1991 +               break;
  1.1992 +
  1.1993 +            case 2:
  1.1994 +               entry[1 ^ afirst] = (png_byte)alpha;
  1.1995 +            case 1:
  1.1996 +               entry[afirst] = (png_byte)green;
  1.1997 +               break;
  1.1998 +
  1.1999 +            default:
  1.2000 +               break;
  1.2001 +         }
  1.2002 +      }
  1.2003 +
  1.2004 +#     ifdef afirst
  1.2005 +#        undef afirst
  1.2006 +#     endif
  1.2007 +#     ifdef bgr
  1.2008 +#        undef bgr
  1.2009 +#     endif
  1.2010 +   }
  1.2011 +}
  1.2012 +
  1.2013 +static int
  1.2014 +make_gray_file_colormap(png_image_read_control *display)
  1.2015 +{
  1.2016 +   unsigned int i;
  1.2017 +
  1.2018 +   for (i=0; i<256; ++i)
  1.2019 +      png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
  1.2020 +
  1.2021 +   return i;
  1.2022 +}
  1.2023 +
  1.2024 +static int
  1.2025 +make_gray_colormap(png_image_read_control *display)
  1.2026 +{
  1.2027 +   unsigned int i;
  1.2028 +
  1.2029 +   for (i=0; i<256; ++i)
  1.2030 +      png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
  1.2031 +
  1.2032 +   return i;
  1.2033 +}
  1.2034 +#define PNG_GRAY_COLORMAP_ENTRIES 256
  1.2035 +
  1.2036 +static int
  1.2037 +make_ga_colormap(png_image_read_control *display)
  1.2038 +{
  1.2039 +   unsigned int i, a;
  1.2040 +
  1.2041 +   /* Alpha is retained, the output will be a color-map with entries
  1.2042 +    * selected by six levels of alpha.  One transparent entry, 6 gray
  1.2043 +    * levels for all the intermediate alpha values, leaving 230 entries
  1.2044 +    * for the opaque grays.  The color-map entries are the six values
  1.2045 +    * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the
  1.2046 +    * relevant entry.
  1.2047 +    *
  1.2048 +    * if (alpha > 229) // opaque
  1.2049 +    * {
  1.2050 +    *    // The 231 entries are selected to make the math below work:
  1.2051 +    *    base = 0;
  1.2052 +    *    entry = (231 * gray + 128) >> 8;
  1.2053 +    * }
  1.2054 +    * else if (alpha < 26) // transparent
  1.2055 +    * {
  1.2056 +    *    base = 231;
  1.2057 +    *    entry = 0;
  1.2058 +    * }
  1.2059 +    * else // partially opaque
  1.2060 +    * {
  1.2061 +    *    base = 226 + 6 * PNG_DIV51(alpha);
  1.2062 +    *    entry = PNG_DIV51(gray);
  1.2063 +    * }
  1.2064 +    */
  1.2065 +   i = 0;
  1.2066 +   while (i < 231)
  1.2067 +   {
  1.2068 +      unsigned int gray = (i * 256 + 115) / 231;
  1.2069 +      png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
  1.2070 +   }
  1.2071 +
  1.2072 +   /* 255 is used here for the component values for consistency with the code
  1.2073 +    * that undoes premultiplication in pngwrite.c.
  1.2074 +    */
  1.2075 +   png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
  1.2076 +
  1.2077 +   for (a=1; a<5; ++a)
  1.2078 +   {
  1.2079 +      unsigned int g;
  1.2080 +
  1.2081 +      for (g=0; g<6; ++g)
  1.2082 +         png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
  1.2083 +            P_sRGB);
  1.2084 +   }
  1.2085 +
  1.2086 +   return i;
  1.2087 +}
  1.2088 +
  1.2089 +#define PNG_GA_COLORMAP_ENTRIES 256
  1.2090 +
  1.2091 +static int
  1.2092 +make_rgb_colormap(png_image_read_control *display)
  1.2093 +{
  1.2094 +   unsigned int i, r;
  1.2095 +
  1.2096 +   /* Build a 6x6x6 opaque RGB cube */
  1.2097 +   for (i=r=0; r<6; ++r)
  1.2098 +   {
  1.2099 +      unsigned int g;
  1.2100 +
  1.2101 +      for (g=0; g<6; ++g)
  1.2102 +      {
  1.2103 +         unsigned int b;
  1.2104 +
  1.2105 +         for (b=0; b<6; ++b)
  1.2106 +            png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
  1.2107 +               P_sRGB);
  1.2108 +      }
  1.2109 +   }
  1.2110 +
  1.2111 +   return i;
  1.2112 +}
  1.2113 +
  1.2114 +#define PNG_RGB_COLORMAP_ENTRIES 216
  1.2115 +
  1.2116 +/* Return a palette index to the above palette given three 8-bit sRGB values. */
  1.2117 +#define PNG_RGB_INDEX(r,g,b) \
  1.2118 +   ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
  1.2119 +
  1.2120 +static int
  1.2121 +png_image_read_colormap(png_voidp argument)
  1.2122 +{
  1.2123 +   png_image_read_control *display =
  1.2124 +      png_voidcast(png_image_read_control*, argument);
  1.2125 +   const png_imagep image = display->image;
  1.2126 +
  1.2127 +   const png_structrp png_ptr = image->opaque->png_ptr;
  1.2128 +   const png_uint_32 output_format = image->format;
  1.2129 +   const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ?
  1.2130 +      P_LINEAR : P_sRGB;
  1.2131 +
  1.2132 +   unsigned int cmap_entries;
  1.2133 +   unsigned int output_processing;        /* Output processing option */
  1.2134 +   unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
  1.2135 +
  1.2136 +   /* Background information; the background color and the index of this color
  1.2137 +    * in the color-map if it exists (else 256).
  1.2138 +    */
  1.2139 +   unsigned int background_index = 256;
  1.2140 +   png_uint_32 back_r, back_g, back_b;
  1.2141 +
  1.2142 +   /* Flags to accumulate things that need to be done to the input. */
  1.2143 +   int expand_tRNS = 0;
  1.2144 +
  1.2145 +   /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is
  1.2146 +    * very difficult to do, the results look awful, and it is difficult to see
  1.2147 +    * what possible use it is because the application can't control the
  1.2148 +    * color-map.
  1.2149 +    */
  1.2150 +   if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
  1.2151 +         png_ptr->num_trans > 0) /* alpha in input */ &&
  1.2152 +      ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
  1.2153 +   {
  1.2154 +      if (output_encoding == P_LINEAR) /* compose on black */
  1.2155 +         back_b = back_g = back_r = 0;
  1.2156 +
  1.2157 +      else if (display->background == NULL /* no way to remove it */)
  1.2158 +         png_error(png_ptr,
  1.2159 +            "a background color must be supplied to remove alpha/transparency");
  1.2160 +
  1.2161 +      /* Get a copy of the background color (this avoids repeating the checks
  1.2162 +       * below.)  The encoding is 8-bit sRGB or 16-bit linear, depending on the
  1.2163 +       * output format.
  1.2164 +       */
  1.2165 +      else
  1.2166 +      {
  1.2167 +         back_g = display->background->green;
  1.2168 +         if (output_format & PNG_FORMAT_FLAG_COLOR)
  1.2169 +         {
  1.2170 +            back_r = display->background->red;
  1.2171 +            back_b = display->background->blue;
  1.2172 +         }
  1.2173 +         else
  1.2174 +            back_b = back_r = back_g;
  1.2175 +      }
  1.2176 +   }
  1.2177 +
  1.2178 +   else if (output_encoding == P_LINEAR)
  1.2179 +      back_b = back_r = back_g = 65535;
  1.2180 +
  1.2181 +   else
  1.2182 +      back_b = back_r = back_g = 255;
  1.2183 +
  1.2184 +   /* Default the input file gamma if required - this is necessary because
  1.2185 +    * libpng assumes that if no gamma information is present the data is in the
  1.2186 +    * output format, but the simplified API deduces the gamma from the input
  1.2187 +    * format.
  1.2188 +    */
  1.2189 +   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
  1.2190 +   {
  1.2191 +      /* Do this directly, not using the png_colorspace functions, to ensure
  1.2192 +       * that it happens even if the colorspace is invalid (though probably if
  1.2193 +       * it is the setting will be ignored)  Note that the same thing can be
  1.2194 +       * achieved at the application interface with png_set_gAMA.
  1.2195 +       */
  1.2196 +      if (png_ptr->bit_depth == 16 &&
  1.2197 +         (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
  1.2198 +         png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
  1.2199 +
  1.2200 +      else
  1.2201 +         png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
  1.2202 +
  1.2203 +      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
  1.2204 +   }
  1.2205 +
  1.2206 +   /* Decide what to do based on the PNG color type of the input data.  The
  1.2207 +    * utility function png_create_colormap_entry deals with most aspects of the
  1.2208 +    * output transformations; this code works out how to produce bytes of
  1.2209 +    * color-map entries from the original format.
  1.2210 +    */
  1.2211 +   switch (png_ptr->color_type)
  1.2212 +   {
  1.2213 +      case PNG_COLOR_TYPE_GRAY:
  1.2214 +         if (png_ptr->bit_depth <= 8)
  1.2215 +         {
  1.2216 +            /* There at most 256 colors in the output, regardless of
  1.2217 +             * transparency.
  1.2218 +             */
  1.2219 +            unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;
  1.2220 +
  1.2221 +            cmap_entries = 1U << png_ptr->bit_depth;
  1.2222 +            if (cmap_entries > image->colormap_entries)
  1.2223 +               png_error(png_ptr, "gray[8] color-map: too few entries");
  1.2224 +
  1.2225 +            step = 255 / (cmap_entries - 1);
  1.2226 +            output_processing = PNG_CMAP_NONE;
  1.2227 +
  1.2228 +            /* If there is a tRNS chunk then this either selects a transparent
  1.2229 +             * value or, if the output has no alpha, the background color.
  1.2230 +             */
  1.2231 +            if (png_ptr->num_trans > 0)
  1.2232 +            {
  1.2233 +               trans = png_ptr->trans_color.gray;
  1.2234 +
  1.2235 +               if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
  1.2236 +                  back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
  1.2237 +            }
  1.2238 +
  1.2239 +            /* png_create_colormap_entry just takes an RGBA and writes the
  1.2240 +             * corresponding color-map entry using the format from 'image',
  1.2241 +             * including the required conversion to sRGB or linear as
  1.2242 +             * appropriate.  The input values are always either sRGB (if the
  1.2243 +             * gamma correction flag is 0) or 0..255 scaled file encoded values
  1.2244 +             * (if the function must gamma correct them).
  1.2245 +             */
  1.2246 +            for (i=val=0; i<cmap_entries; ++i, val += step)
  1.2247 +            {
  1.2248 +               /* 'i' is a file value.  While this will result in duplicated
  1.2249 +                * entries for 8-bit non-sRGB encoded files it is necessary to
  1.2250 +                * have non-gamma corrected values to do tRNS handling.
  1.2251 +                */
  1.2252 +               if (i != trans)
  1.2253 +                  png_create_colormap_entry(display, i, val, val, val, 255,
  1.2254 +                     P_FILE/*8-bit with file gamma*/);
  1.2255 +
  1.2256 +               /* Else this entry is transparent.  The colors don't matter if
  1.2257 +                * there is an alpha channel (back_alpha == 0), but it does no
  1.2258 +                * harm to pass them in; the values are not set above so this
  1.2259 +                * passes in white.
  1.2260 +                *
  1.2261 +                * NOTE: this preserves the full precision of the application
  1.2262 +                * supplied background color when it is used.
  1.2263 +                */
  1.2264 +               else
  1.2265 +                  png_create_colormap_entry(display, i, back_r, back_g, back_b,
  1.2266 +                     back_alpha, output_encoding);
  1.2267 +            }
  1.2268 +
  1.2269 +            /* We need libpng to preserve the original encoding. */
  1.2270 +            data_encoding = P_FILE;
  1.2271 +
  1.2272 +            /* The rows from libpng, while technically gray values, are now also
  1.2273 +             * color-map indicies; however, they may need to be expanded to 1
  1.2274 +             * byte per pixel.  This is what png_set_packing does (i.e., it
  1.2275 +             * unpacks the bit values into bytes.)
  1.2276 +             */
  1.2277 +            if (png_ptr->bit_depth < 8)
  1.2278 +               png_set_packing(png_ptr);
  1.2279 +         }
  1.2280 +
  1.2281 +         else /* bit depth is 16 */
  1.2282 +         {
  1.2283 +            /* The 16-bit input values can be converted directly to 8-bit gamma
  1.2284 +             * encoded values; however, if a tRNS chunk is present 257 color-map
  1.2285 +             * entries are required.  This means that the extra entry requires
  1.2286 +             * special processing; add an alpha channel, sacrifice gray level
  1.2287 +             * 254 and convert transparent (alpha==0) entries to that.
  1.2288 +             *
  1.2289 +             * Use libpng to chop the data to 8 bits.  Convert it to sRGB at the
  1.2290 +             * same time to minimize quality loss.  If a tRNS chunk is present
  1.2291 +             * this means libpng must handle it too; otherwise it is impossible
  1.2292 +             * to do the exact match on the 16-bit value.
  1.2293 +             *
  1.2294 +             * If the output has no alpha channel *and* the background color is
  1.2295 +             * gray then it is possible to let libpng handle the substitution by
  1.2296 +             * ensuring that the corresponding gray level matches the background
  1.2297 +             * color exactly.
  1.2298 +             */
  1.2299 +            data_encoding = P_sRGB;
  1.2300 +
  1.2301 +            if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
  1.2302 +               png_error(png_ptr, "gray[16] color-map: too few entries");
  1.2303 +
  1.2304 +            cmap_entries = make_gray_colormap(display);
  1.2305 +
  1.2306 +            if (png_ptr->num_trans > 0)
  1.2307 +            {
  1.2308 +               unsigned int back_alpha;
  1.2309 +
  1.2310 +               if (output_format & PNG_FORMAT_FLAG_ALPHA)
  1.2311 +                  back_alpha = 0;
  1.2312 +
  1.2313 +               else
  1.2314 +               {
  1.2315 +                  if (back_r == back_g && back_g == back_b)
  1.2316 +                  {
  1.2317 +                     /* Background is gray; no special processing will be
  1.2318 +                      * required.
  1.2319 +                      */
  1.2320 +                     png_color_16 c;
  1.2321 +                     png_uint_32 gray = back_g;
  1.2322 +
  1.2323 +                     if (output_encoding == P_LINEAR)
  1.2324 +                     {
  1.2325 +                        gray = PNG_sRGB_FROM_LINEAR(gray * 255);
  1.2326 +
  1.2327 +                        /* And make sure the corresponding palette entry
  1.2328 +                         * matches.
  1.2329 +                         */
  1.2330 +                        png_create_colormap_entry(display, gray, back_g, back_g,
  1.2331 +                           back_g, 65535, P_LINEAR);
  1.2332 +                     }
  1.2333 +
  1.2334 +                     /* The background passed to libpng, however, must be the
  1.2335 +                      * sRGB value.
  1.2336 +                      */
  1.2337 +                     c.index = 0; /*unused*/
  1.2338 +                     c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
  1.2339 +
  1.2340 +                     /* NOTE: does this work without expanding tRNS to alpha?
  1.2341 +                      * It should be the color->gray case below apparently
  1.2342 +                      * doesn't.
  1.2343 +                      */
  1.2344 +                     png_set_background_fixed(png_ptr, &c,
  1.2345 +                        PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
  1.2346 +                        0/*gamma: not used*/);
  1.2347 +
  1.2348 +                     output_processing = PNG_CMAP_NONE;
  1.2349 +                     break;
  1.2350 +                  }
  1.2351 +
  1.2352 +                  back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
  1.2353 +               }
  1.2354 +
  1.2355 +               /* output_processing means that the libpng-processed row will be
  1.2356 +                * 8-bit GA and it has to be processing to single byte color-map
  1.2357 +                * values.  Entry 254 is replaced by either a completely
  1.2358 +                * transparent entry or by the background color at full
  1.2359 +                * precision (and the background color is not a simple gray leve
  1.2360 +                * in this case.)
  1.2361 +                */
  1.2362 +               expand_tRNS = 1;
  1.2363 +               output_processing = PNG_CMAP_TRANS;
  1.2364 +               background_index = 254;
  1.2365 +
  1.2366 +               /* And set (overwrite) color-map entry 254 to the actual
  1.2367 +                * background color at full precision.
  1.2368 +                */
  1.2369 +               png_create_colormap_entry(display, 254, back_r, back_g, back_b,
  1.2370 +                  back_alpha, output_encoding);
  1.2371 +            }
  1.2372 +
  1.2373 +            else
  1.2374 +               output_processing = PNG_CMAP_NONE;
  1.2375 +         }
  1.2376 +         break;
  1.2377 +
  1.2378 +      case PNG_COLOR_TYPE_GRAY_ALPHA:
  1.2379 +         /* 8-bit or 16-bit PNG with two channels - gray and alpha.  A minimum
  1.2380 +          * of 65536 combinations.  If, however, the alpha channel is to be
  1.2381 +          * removed there are only 256 possibilities if the background is gray.
  1.2382 +          * (Otherwise there is a subset of the 65536 possibilities defined by
  1.2383 +          * the triangle between black, white and the background color.)
  1.2384 +          *
  1.2385 +          * Reduce 16-bit files to 8-bit and sRGB encode the result.  No need to
  1.2386 +          * worry about tRNS matching - tRNS is ignored if there is an alpha
  1.2387 +          * channel.
  1.2388 +          */
  1.2389 +         data_encoding = P_sRGB;
  1.2390 +
  1.2391 +         if (output_format & PNG_FORMAT_FLAG_ALPHA)
  1.2392 +         {
  1.2393 +            if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
  1.2394 +               png_error(png_ptr, "gray+alpha color-map: too few entries");
  1.2395 +
  1.2396 +            cmap_entries = make_ga_colormap(display);
  1.2397 +
  1.2398 +            background_index = PNG_CMAP_GA_BACKGROUND;
  1.2399 +            output_processing = PNG_CMAP_GA;
  1.2400 +         }
  1.2401 +
  1.2402 +         else /* alpha is removed */
  1.2403 +         {
  1.2404 +            /* Alpha must be removed as the PNG data is processed when the
  1.2405 +             * background is a color because the G and A channels are
  1.2406 +             * independent and the vector addition (non-parallel vectors) is a
  1.2407 +             * 2-D problem.
  1.2408 +             *
  1.2409 +             * This can be reduced to the same algorithm as above by making a
  1.2410 +             * colormap containing gray levels (for the opaque grays), a
  1.2411 +             * background entry (for a transparent pixel) and a set of four six
  1.2412 +             * level color values, one set for each intermediate alpha value.
  1.2413 +             * See the comments in make_ga_colormap for how this works in the
  1.2414 +             * per-pixel processing.
  1.2415 +             *
  1.2416 +             * If the background is gray, however, we only need a 256 entry gray
  1.2417 +             * level color map.  It is sufficient to make the entry generated
  1.2418 +             * for the background color be exactly the color specified.
  1.2419 +             */
  1.2420 +            if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
  1.2421 +               (back_r == back_g && back_g == back_b))
  1.2422 +            {
  1.2423 +               /* Background is gray; no special processing will be required. */
  1.2424 +               png_color_16 c;
  1.2425 +               png_uint_32 gray = back_g;
  1.2426 +
  1.2427 +               if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
  1.2428 +                  png_error(png_ptr, "gray-alpha color-map: too few entries");
  1.2429 +
  1.2430 +               cmap_entries = make_gray_colormap(display);
  1.2431 +
  1.2432 +               if (output_encoding == P_LINEAR)
  1.2433 +               {
  1.2434 +                  gray = PNG_sRGB_FROM_LINEAR(gray * 255);
  1.2435 +
  1.2436 +                  /* And make sure the corresponding palette entry matches. */
  1.2437 +                  png_create_colormap_entry(display, gray, back_g, back_g,
  1.2438 +                     back_g, 65535, P_LINEAR);
  1.2439 +               }
  1.2440 +
  1.2441 +               /* The background passed to libpng, however, must be the sRGB
  1.2442 +                * value.
  1.2443 +                */
  1.2444 +               c.index = 0; /*unused*/
  1.2445 +               c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
  1.2446 +
  1.2447 +               png_set_background_fixed(png_ptr, &c,
  1.2448 +                  PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
  1.2449 +                  0/*gamma: not used*/);
  1.2450 +
  1.2451 +               output_processing = PNG_CMAP_NONE;
  1.2452 +            }
  1.2453 +
  1.2454 +            else
  1.2455 +            {
  1.2456 +               png_uint_32 i, a;
  1.2457 +
  1.2458 +               /* This is the same as png_make_ga_colormap, above, except that
  1.2459 +                * the entries are all opaque.
  1.2460 +                */
  1.2461 +               if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
  1.2462 +                  png_error(png_ptr, "ga-alpha color-map: too few entries");
  1.2463 +
  1.2464 +               i = 0;
  1.2465 +               while (i < 231)
  1.2466 +               {
  1.2467 +                  png_uint_32 gray = (i * 256 + 115) / 231;
  1.2468 +                  png_create_colormap_entry(display, i++, gray, gray, gray,
  1.2469 +                     255, P_sRGB);
  1.2470 +               }
  1.2471 +
  1.2472 +               /* NOTE: this preserves the full precision of the application
  1.2473 +                * background color.
  1.2474 +                */
  1.2475 +               background_index = i;
  1.2476 +               png_create_colormap_entry(display, i++, back_r, back_g, back_b,
  1.2477 +                  output_encoding == P_LINEAR ? 65535U : 255U, output_encoding);
  1.2478 +
  1.2479 +               /* For non-opaque input composite on the sRGB background - this
  1.2480 +                * requires inverting the encoding for each component.  The input
  1.2481 +                * is still converted to the sRGB encoding because this is a
  1.2482 +                * reasonable approximate to the logarithmic curve of human
  1.2483 +                * visual sensitivity, at least over the narrow range which PNG
  1.2484 +                * represents.  Consequently 'G' is always sRGB encoded, while
  1.2485 +                * 'A' is linear.  We need the linear background colors.
  1.2486 +                */
  1.2487 +               if (output_encoding == P_sRGB) /* else already linear */
  1.2488 +               {
  1.2489 +                  /* This may produce a value not exactly matching the
  1.2490 +                   * background, but that's ok because these numbers are only
  1.2491 +                   * used when alpha != 0
  1.2492 +                   */
  1.2493 +                  back_r = png_sRGB_table[back_r];
  1.2494 +                  back_g = png_sRGB_table[back_g];
  1.2495 +                  back_b = png_sRGB_table[back_b];
  1.2496 +               }
  1.2497 +
  1.2498 +               for (a=1; a<5; ++a)
  1.2499 +               {
  1.2500 +                  unsigned int g;
  1.2501 +
  1.2502 +                  /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled
  1.2503 +                   * by an 8-bit alpha value (0..255).
  1.2504 +                   */
  1.2505 +                  png_uint_32 alpha = 51 * a;
  1.2506 +                  png_uint_32 back_rx = (255-alpha) * back_r;
  1.2507 +                  png_uint_32 back_gx = (255-alpha) * back_g;
  1.2508 +                  png_uint_32 back_bx = (255-alpha) * back_b;
  1.2509 +
  1.2510 +                  for (g=0; g<6; ++g)
  1.2511 +                  {
  1.2512 +                     png_uint_32 gray = png_sRGB_table[g*51] * alpha;
  1.2513 +
  1.2514 +                     png_create_colormap_entry(display, i++,
  1.2515 +                        PNG_sRGB_FROM_LINEAR(gray + back_rx),
  1.2516 +                        PNG_sRGB_FROM_LINEAR(gray + back_gx),
  1.2517 +                        PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
  1.2518 +                  }
  1.2519 +               }
  1.2520 +
  1.2521 +               cmap_entries = i;
  1.2522 +               output_processing = PNG_CMAP_GA;
  1.2523 +            }
  1.2524 +         }
  1.2525 +         break;
  1.2526 +
  1.2527 +      case PNG_COLOR_TYPE_RGB:
  1.2528 +      case PNG_COLOR_TYPE_RGB_ALPHA:
  1.2529 +         /* Exclude the case where the output is gray; we can always handle this
  1.2530 +          * with the cases above.
  1.2531 +          */
  1.2532 +         if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
  1.2533 +         {
  1.2534 +            /* The color-map will be grayscale, so we may as well convert the
  1.2535 +             * input RGB values to a simple grayscale and use the grayscale
  1.2536 +             * code above.
  1.2537 +             *
  1.2538 +             * NOTE: calling this apparently damages the recognition of the
  1.2539 +             * transparent color in background color handling; call
  1.2540 +             * png_set_tRNS_to_alpha before png_set_background_fixed.
  1.2541 +             */
  1.2542 +            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
  1.2543 +               -1);
  1.2544 +            data_encoding = P_sRGB;
  1.2545 +
  1.2546 +            /* The output will now be one or two 8-bit gray or gray+alpha
  1.2547 +             * channels.  The more complex case arises when the input has alpha.
  1.2548 +             */
  1.2549 +            if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
  1.2550 +               png_ptr->num_trans > 0) &&
  1.2551 +               (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
  1.2552 +            {
  1.2553 +               /* Both input and output have an alpha channel, so no background
  1.2554 +                * processing is required; just map the GA bytes to the right
  1.2555 +                * color-map entry.
  1.2556 +                */
  1.2557 +               expand_tRNS = 1;
  1.2558 +
  1.2559 +               if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
  1.2560 +                  png_error(png_ptr, "rgb[ga] color-map: too few entries");
  1.2561 +
  1.2562 +               cmap_entries = make_ga_colormap(display);
  1.2563 +               background_index = PNG_CMAP_GA_BACKGROUND;
  1.2564 +               output_processing = PNG_CMAP_GA;
  1.2565 +            }
  1.2566 +
  1.2567 +            else
  1.2568 +            {
  1.2569 +               /* Either the input or the output has no alpha channel, so there
  1.2570 +                * will be no non-opaque pixels in the color-map; it will just be
  1.2571 +                * grayscale.
  1.2572 +                */
  1.2573 +               if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
  1.2574 +                  png_error(png_ptr, "rgb[gray] color-map: too few entries");
  1.2575 +
  1.2576 +               /* Ideally this code would use libpng to do the gamma correction,
  1.2577 +                * but if an input alpha channel is to be removed we will hit the
  1.2578 +                * libpng bug in gamma+compose+rgb-to-gray (the double gamma
  1.2579 +                * correction bug).  Fix this by dropping the gamma correction in
  1.2580 +                * this case and doing it in the palette; this will result in
  1.2581 +                * duplicate palette entries, but that's better than the
  1.2582 +                * alternative of double gamma correction.
  1.2583 +                */
  1.2584 +               if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
  1.2585 +                  png_ptr->num_trans > 0) &&
  1.2586 +                  png_gamma_not_sRGB(png_ptr->colorspace.gamma))
  1.2587 +               {
  1.2588 +                  cmap_entries = make_gray_file_colormap(display);
  1.2589 +                  data_encoding = P_FILE;
  1.2590 +               }
  1.2591 +
  1.2592 +               else
  1.2593 +                  cmap_entries = make_gray_colormap(display);
  1.2594 +
  1.2595 +               /* But if the input has alpha or transparency it must be removed
  1.2596 +                */
  1.2597 +               if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
  1.2598 +                  png_ptr->num_trans > 0)
  1.2599 +               {
  1.2600 +                  png_color_16 c;
  1.2601 +                  png_uint_32 gray = back_g;
  1.2602 +
  1.2603 +                  /* We need to ensure that the application background exists in
  1.2604 +                   * the colormap and that completely transparent pixels map to
  1.2605 +                   * it.  Achieve this simply by ensuring that the entry
  1.2606 +                   * selected for the background really is the background color.
  1.2607 +                   */
  1.2608 +                  if (data_encoding == P_FILE) /* from the fixup above */
  1.2609 +                  {
  1.2610 +                     /* The app supplied a gray which is in output_encoding, we
  1.2611 +                      * need to convert it to a value of the input (P_FILE)
  1.2612 +                      * encoding then set this palette entry to the required
  1.2613 +                      * output encoding.
  1.2614 +                      */
  1.2615 +                     if (output_encoding == P_sRGB)
  1.2616 +                        gray = png_sRGB_table[gray]; /* now P_LINEAR */
  1.2617 +
  1.2618 +                     gray = PNG_DIV257(png_gamma_16bit_correct(gray,
  1.2619 +                        png_ptr->colorspace.gamma)); /* now P_FILE */
  1.2620 +
  1.2621 +                     /* And make sure the corresponding palette entry contains
  1.2622 +                      * exactly the required sRGB value.
  1.2623 +                      */
  1.2624 +                     png_create_colormap_entry(display, gray, back_g, back_g,
  1.2625 +                        back_g, 0/*unused*/, output_encoding);
  1.2626 +                  }
  1.2627 +
  1.2628 +                  else if (output_encoding == P_LINEAR)
  1.2629 +                  {
  1.2630 +                     gray = PNG_sRGB_FROM_LINEAR(gray * 255);
  1.2631 +
  1.2632 +                     /* And make sure the corresponding palette entry matches.
  1.2633 +                      */
  1.2634 +                     png_create_colormap_entry(display, gray, back_g, back_g,
  1.2635 +                        back_g, 0/*unused*/, P_LINEAR);
  1.2636 +                  }
  1.2637 +
  1.2638 +                  /* The background passed to libpng, however, must be the
  1.2639 +                   * output (normally sRGB) value.
  1.2640 +                   */
  1.2641 +                  c.index = 0; /*unused*/
  1.2642 +                  c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
  1.2643 +
  1.2644 +                  /* NOTE: the following is apparently a bug in libpng. Without
  1.2645 +                   * it the transparent color recognition in
  1.2646 +                   * png_set_background_fixed seems to go wrong.
  1.2647 +                   */
  1.2648 +                  expand_tRNS = 1;
  1.2649 +                  png_set_background_fixed(png_ptr, &c,
  1.2650 +                     PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
  1.2651 +                     0/*gamma: not used*/);
  1.2652 +               }
  1.2653 +
  1.2654 +               output_processing = PNG_CMAP_NONE;
  1.2655 +            }
  1.2656 +         }
  1.2657 +
  1.2658 +         else /* output is color */
  1.2659 +         {
  1.2660 +            /* We could use png_quantize here so long as there is no transparent
  1.2661 +             * color or alpha; png_quantize ignores alpha.  Easier overall just
  1.2662 +             * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
  1.2663 +             * Consequently we always want libpng to produce sRGB data.
  1.2664 +             */
  1.2665 +            data_encoding = P_sRGB;
  1.2666 +
  1.2667 +            /* Is there any transparency or alpha? */
  1.2668 +            if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
  1.2669 +               png_ptr->num_trans > 0)
  1.2670 +            {
  1.2671 +               /* Is there alpha in the output too?  If so all four channels are
  1.2672 +                * processed into a special RGB cube with alpha support.
  1.2673 +                */
  1.2674 +               if (output_format & PNG_FORMAT_FLAG_ALPHA)
  1.2675 +               {
  1.2676 +                  png_uint_32 r;
  1.2677 +
  1.2678 +                  if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
  1.2679 +                     png_error(png_ptr, "rgb+alpha color-map: too few entries");
  1.2680 +
  1.2681 +                  cmap_entries = make_rgb_colormap(display);
  1.2682 +
  1.2683 +                  /* Add a transparent entry. */
  1.2684 +                  png_create_colormap_entry(display, cmap_entries, 255, 255,
  1.2685 +                     255, 0, P_sRGB);
  1.2686 +
  1.2687 +                  /* This is stored as the background index for the processing
  1.2688 +                   * algorithm.
  1.2689 +                   */
  1.2690 +                  background_index = cmap_entries++;
  1.2691 +
  1.2692 +                  /* Add 27 r,g,b entries each with alpha 0.5. */
  1.2693 +                  for (r=0; r<256; r = (r << 1) | 0x7f)
  1.2694 +                  {
  1.2695 +                     png_uint_32 g;
  1.2696 +
  1.2697 +                     for (g=0; g<256; g = (g << 1) | 0x7f)
  1.2698 +                     {
  1.2699 +                        png_uint_32 b;
  1.2700 +
  1.2701 +                        /* This generates components with the values 0, 127 and
  1.2702 +                         * 255
  1.2703 +                         */
  1.2704 +                        for (b=0; b<256; b = (b << 1) | 0x7f)
  1.2705 +                           png_create_colormap_entry(display, cmap_entries++,
  1.2706 +                              r, g, b, 128, P_sRGB);
  1.2707 +                     }
  1.2708 +                  }
  1.2709 +
  1.2710 +                  expand_tRNS = 1;
  1.2711 +                  output_processing = PNG_CMAP_RGB_ALPHA;
  1.2712 +               }
  1.2713 +
  1.2714 +               else
  1.2715 +               {
  1.2716 +                  /* Alpha/transparency must be removed.  The background must
  1.2717 +                   * exist in the color map (achieved by setting adding it after
  1.2718 +                   * the 666 color-map).  If the standard processing code will
  1.2719 +                   * pick up this entry automatically that's all that is
  1.2720 +                   * required; libpng can be called to do the background
  1.2721 +                   * processing.
  1.2722 +                   */
  1.2723 +                  unsigned int sample_size =
  1.2724 +                     PNG_IMAGE_SAMPLE_SIZE(output_format);
  1.2725 +                  png_uint_32 r, g, b; /* sRGB background */
  1.2726 +
  1.2727 +                  if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
  1.2728 +                     png_error(png_ptr, "rgb-alpha color-map: too few entries");
  1.2729 +
  1.2730 +                  cmap_entries = make_rgb_colormap(display);
  1.2731 +
  1.2732 +                  png_create_colormap_entry(display, cmap_entries, back_r,
  1.2733 +                        back_g, back_b, 0/*unused*/, output_encoding);
  1.2734 +
  1.2735 +                  if (output_encoding == P_LINEAR)
  1.2736 +                  {
  1.2737 +                     r = PNG_sRGB_FROM_LINEAR(back_r * 255);
  1.2738 +                     g = PNG_sRGB_FROM_LINEAR(back_g * 255);
  1.2739 +                     b = PNG_sRGB_FROM_LINEAR(back_b * 255);
  1.2740 +                  }
  1.2741 +
  1.2742 +                  else
  1.2743 +                  {
  1.2744 +                     r = back_r;
  1.2745 +                     g = back_g;
  1.2746 +                     b = back_g;
  1.2747 +                  }
  1.2748 +
  1.2749 +                  /* Compare the newly-created color-map entry with the one the
  1.2750 +                   * PNG_CMAP_RGB algorithm will use.  If the two entries don't
  1.2751 +                   * match, add the new one and set this as the background
  1.2752 +                   * index.
  1.2753 +                   */
  1.2754 +                  if (memcmp((png_const_bytep)display->colormap +
  1.2755 +                        sample_size * cmap_entries,
  1.2756 +                     (png_const_bytep)display->colormap +
  1.2757 +                        sample_size * PNG_RGB_INDEX(r,g,b),
  1.2758 +                     sample_size) != 0)
  1.2759 +                  {
  1.2760 +                     /* The background color must be added. */
  1.2761 +                     background_index = cmap_entries++;
  1.2762 +
  1.2763 +                     /* Add 27 r,g,b entries each with created by composing with
  1.2764 +                      * the background at alpha 0.5.
  1.2765 +                      */
  1.2766 +                     for (r=0; r<256; r = (r << 1) | 0x7f)
  1.2767 +                     {
  1.2768 +                        for (g=0; g<256; g = (g << 1) | 0x7f)
  1.2769 +                        {
  1.2770 +                           /* This generates components with the values 0, 127
  1.2771 +                            * and 255
  1.2772 +                            */
  1.2773 +                           for (b=0; b<256; b = (b << 1) | 0x7f)
  1.2774 +                              png_create_colormap_entry(display, cmap_entries++,
  1.2775 +                                 png_colormap_compose(display, r, P_sRGB, 128,
  1.2776 +                                    back_r, output_encoding),
  1.2777 +                                 png_colormap_compose(display, g, P_sRGB, 128,
  1.2778 +                                    back_g, output_encoding),
  1.2779 +                                 png_colormap_compose(display, b, P_sRGB, 128,
  1.2780 +                                    back_b, output_encoding),
  1.2781 +                                 0/*unused*/, output_encoding);
  1.2782 +                        }
  1.2783 +                     }
  1.2784 +
  1.2785 +                     expand_tRNS = 1;
  1.2786 +                     output_processing = PNG_CMAP_RGB_ALPHA;
  1.2787 +                  }
  1.2788 +
  1.2789 +                  else /* background color is in the standard color-map */
  1.2790 +                  {
  1.2791 +                     png_color_16 c;
  1.2792 +
  1.2793 +                     c.index = 0; /*unused*/
  1.2794 +                     c.red = (png_uint_16)back_r;
  1.2795 +                     c.gray = c.green = (png_uint_16)back_g;
  1.2796 +                     c.blue = (png_uint_16)back_b;
  1.2797 +
  1.2798 +                     png_set_background_fixed(png_ptr, &c,
  1.2799 +                        PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
  1.2800 +                        0/*gamma: not used*/);
  1.2801 +
  1.2802 +                     output_processing = PNG_CMAP_RGB;
  1.2803 +                  }
  1.2804 +               }
  1.2805 +            }
  1.2806 +
  1.2807 +            else /* no alpha or transparency in the input */
  1.2808 +            {
  1.2809 +               /* Alpha in the output is irrelevant, simply map the opaque input
  1.2810 +                * pixels to the 6x6x6 color-map.
  1.2811 +                */
  1.2812 +               if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
  1.2813 +                  png_error(png_ptr, "rgb color-map: too few entries");
  1.2814 +
  1.2815 +               cmap_entries = make_rgb_colormap(display);
  1.2816 +               output_processing = PNG_CMAP_RGB;
  1.2817 +            }
  1.2818 +         }
  1.2819 +         break;
  1.2820 +
  1.2821 +      case PNG_COLOR_TYPE_PALETTE:
  1.2822 +         /* It's already got a color-map.  It may be necessary to eliminate the
  1.2823 +          * tRNS entries though.
  1.2824 +          */
  1.2825 +         {
  1.2826 +            unsigned int num_trans = png_ptr->num_trans;
  1.2827 +            png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
  1.2828 +            png_const_colorp colormap = png_ptr->palette;
  1.2829 +            const int do_background = trans != NULL &&
  1.2830 +               (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
  1.2831 +            unsigned int i;
  1.2832 +
  1.2833 +            /* Just in case: */
  1.2834 +            if (trans == NULL)
  1.2835 +               num_trans = 0;
  1.2836 +
  1.2837 +            output_processing = PNG_CMAP_NONE;
  1.2838 +            data_encoding = P_FILE; /* Don't change from color-map indicies */
  1.2839 +            cmap_entries = png_ptr->num_palette;
  1.2840 +            if (cmap_entries > 256)
  1.2841 +               cmap_entries = 256;
  1.2842 +
  1.2843 +            if (cmap_entries > image->colormap_entries)
  1.2844 +               png_error(png_ptr, "palette color-map: too few entries");
  1.2845 +
  1.2846 +            for (i=0; i < cmap_entries; ++i)
  1.2847 +            {
  1.2848 +               if (do_background && i < num_trans && trans[i] < 255)
  1.2849 +               {
  1.2850 +                  if (trans[i] == 0)
  1.2851 +                     png_create_colormap_entry(display, i, back_r, back_g,
  1.2852 +                        back_b, 0, output_encoding);
  1.2853 +
  1.2854 +                  else
  1.2855 +                  {
  1.2856 +                     /* Must compose the PNG file color in the color-map entry
  1.2857 +                      * on the sRGB color in 'back'.
  1.2858 +                      */
  1.2859 +                     png_create_colormap_entry(display, i,
  1.2860 +                        png_colormap_compose(display, colormap[i].red, P_FILE,
  1.2861 +                           trans[i], back_r, output_encoding),
  1.2862 +                        png_colormap_compose(display, colormap[i].green, P_FILE,
  1.2863 +                           trans[i], back_g, output_encoding),
  1.2864 +                        png_colormap_compose(display, colormap[i].blue, P_FILE,
  1.2865 +                           trans[i], back_b, output_encoding),
  1.2866 +                        output_encoding == P_LINEAR ? trans[i] * 257U :
  1.2867 +                           trans[i],
  1.2868 +                        output_encoding);
  1.2869 +                  }
  1.2870 +               }
  1.2871 +
  1.2872 +               else
  1.2873 +                  png_create_colormap_entry(display, i, colormap[i].red,
  1.2874 +                     colormap[i].green, colormap[i].blue,
  1.2875 +                     i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
  1.2876 +            }
  1.2877 +
  1.2878 +            /* The PNG data may have indicies packed in fewer than 8 bits, it
  1.2879 +             * must be expanded if so.
  1.2880 +             */
  1.2881 +            if (png_ptr->bit_depth < 8)
  1.2882 +               png_set_packing(png_ptr);
  1.2883 +         }
  1.2884 +         break;
  1.2885 +
  1.2886 +      default:
  1.2887 +         png_error(png_ptr, "invalid PNG color type");
  1.2888 +         /*NOT REACHED*/
  1.2889 +         break;
  1.2890 +   }
  1.2891 +
  1.2892 +   /* Now deal with the output processing */
  1.2893 +   if (expand_tRNS && png_ptr->num_trans > 0 &&
  1.2894 +      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
  1.2895 +      png_set_tRNS_to_alpha(png_ptr);
  1.2896 +
  1.2897 +   switch (data_encoding)
  1.2898 +   {
  1.2899 +      default:
  1.2900 +         png_error(png_ptr, "bad data option (internal error)");
  1.2901 +         break;
  1.2902 +
  1.2903 +      case P_sRGB:
  1.2904 +         /* Change to 8-bit sRGB */
  1.2905 +         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
  1.2906 +         /* FALL THROUGH */
  1.2907 +
  1.2908 +      case P_FILE:
  1.2909 +         if (png_ptr->bit_depth > 8)
  1.2910 +            png_set_scale_16(png_ptr);
  1.2911 +         break;
  1.2912 +   }
  1.2913 +
  1.2914 +   if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
  1.2915 +      png_error(png_ptr, "color map overflow (BAD internal error)");
  1.2916 +
  1.2917 +   image->colormap_entries = cmap_entries;
  1.2918 +
  1.2919 +   /* Double check using the recorded background index */
  1.2920 +   switch (output_processing)
  1.2921 +   {
  1.2922 +      case PNG_CMAP_NONE:
  1.2923 +         if (background_index != PNG_CMAP_NONE_BACKGROUND)
  1.2924 +            goto bad_background;
  1.2925 +         break;
  1.2926 +
  1.2927 +      case PNG_CMAP_GA:
  1.2928 +         if (background_index != PNG_CMAP_GA_BACKGROUND)
  1.2929 +            goto bad_background;
  1.2930 +         break;
  1.2931 +
  1.2932 +      case PNG_CMAP_TRANS:
  1.2933 +         if (background_index >= cmap_entries ||
  1.2934 +            background_index != PNG_CMAP_TRANS_BACKGROUND)
  1.2935 +            goto bad_background;
  1.2936 +         break;
  1.2937 +
  1.2938 +      case PNG_CMAP_RGB:
  1.2939 +         if (background_index != PNG_CMAP_RGB_BACKGROUND)
  1.2940 +            goto bad_background;
  1.2941 +         break;
  1.2942 +
  1.2943 +      case PNG_CMAP_RGB_ALPHA:
  1.2944 +         if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
  1.2945 +            goto bad_background;
  1.2946 +         break;
  1.2947 +
  1.2948 +      default:
  1.2949 +         png_error(png_ptr, "bad processing option (internal error)");
  1.2950 +
  1.2951 +      bad_background:
  1.2952 +         png_error(png_ptr, "bad background index (internal error)");
  1.2953 +   }
  1.2954 +
  1.2955 +   display->colormap_processing = output_processing;
  1.2956 +
  1.2957 +   return 1/*ok*/;
  1.2958 +}
  1.2959 +
  1.2960 +/* The final part of the color-map read called from png_image_finish_read. */
  1.2961 +static int
  1.2962 +png_image_read_and_map(png_voidp argument)
  1.2963 +{
  1.2964 +   png_image_read_control *display = png_voidcast(png_image_read_control*,
  1.2965 +      argument);
  1.2966 +   png_imagep image = display->image;
  1.2967 +   png_structrp png_ptr = image->opaque->png_ptr;
  1.2968 +   int passes;
  1.2969 +
  1.2970 +   /* Called when the libpng data must be transformed into the color-mapped
  1.2971 +    * form.  There is a local row buffer in display->local and this routine must
  1.2972 +    * do the interlace handling.
  1.2973 +    */
  1.2974 +   switch (png_ptr->interlaced)
  1.2975 +   {
  1.2976 +      case PNG_INTERLACE_NONE:
  1.2977 +         passes = 1;
  1.2978 +         break;
  1.2979 +
  1.2980 +      case PNG_INTERLACE_ADAM7:
  1.2981 +         passes = PNG_INTERLACE_ADAM7_PASSES;
  1.2982 +         break;
  1.2983 +
  1.2984 +      default:
  1.2985 +         png_error(png_ptr, "unknown interlace type");
  1.2986 +   }
  1.2987 +
  1.2988 +   {
  1.2989 +      png_uint_32  height = image->height;
  1.2990 +      png_uint_32  width = image->width;
  1.2991 +      int          proc = display->colormap_processing;
  1.2992 +      png_bytep    first_row = png_voidcast(png_bytep, display->first_row);
  1.2993 +      ptrdiff_t    step_row = display->row_bytes;
  1.2994 +      int pass;
  1.2995 +
  1.2996 +      for (pass = 0; pass < passes; ++pass)
  1.2997 +      {
  1.2998 +         unsigned int     startx, stepx, stepy;
  1.2999 +         png_uint_32      y;
  1.3000 +
  1.3001 +         if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
  1.3002 +         {
  1.3003 +            /* The row may be empty for a short image: */
  1.3004 +            if (PNG_PASS_COLS(width, pass) == 0)
  1.3005 +               continue;
  1.3006 +
  1.3007 +            startx = PNG_PASS_START_COL(pass);
  1.3008 +            stepx = PNG_PASS_COL_OFFSET(pass);
  1.3009 +            y = PNG_PASS_START_ROW(pass);
  1.3010 +            stepy = PNG_PASS_ROW_OFFSET(pass);
  1.3011 +         }
  1.3012 +
  1.3013 +         else
  1.3014 +         {
  1.3015 +            y = 0;
  1.3016 +            startx = 0;
  1.3017 +            stepx = stepy = 1;
  1.3018 +         }
  1.3019 +
  1.3020 +         for (; y<height; y += stepy)
  1.3021 +         {
  1.3022 +            png_bytep inrow = png_voidcast(png_bytep, display->local_row);
  1.3023 +            png_bytep outrow = first_row + y * step_row;
  1.3024 +            png_const_bytep end_row = outrow + width;
  1.3025 +
  1.3026 +            /* Read read the libpng data into the temporary buffer. */
  1.3027 +            png_read_row(png_ptr, inrow, NULL);
  1.3028 +
  1.3029 +            /* Now process the row according to the processing option, note
  1.3030 +             * that the caller verifies that the format of the libpng output
  1.3031 +             * data is as required.
  1.3032 +             */
  1.3033 +            outrow += startx;
  1.3034 +            switch (proc)
  1.3035 +            {
  1.3036 +               case PNG_CMAP_GA:
  1.3037 +                  for (; outrow < end_row; outrow += stepx)
  1.3038 +                  {
  1.3039 +                     /* The data is always in the PNG order */
  1.3040 +                     unsigned int gray = *inrow++;
  1.3041 +                     unsigned int alpha = *inrow++;
  1.3042 +                     unsigned int entry;
  1.3043 +
  1.3044 +                     /* NOTE: this code is copied as a comment in
  1.3045 +                      * make_ga_colormap above.  Please update the
  1.3046 +                      * comment if you change this code!
  1.3047 +                      */
  1.3048 +                     if (alpha > 229) /* opaque */
  1.3049 +                     {
  1.3050 +                        entry = (231 * gray + 128) >> 8;
  1.3051 +                     }
  1.3052 +                     else if (alpha < 26) /* transparent */
  1.3053 +                     {
  1.3054 +                        entry = 231;
  1.3055 +                     }
  1.3056 +                     else /* partially opaque */
  1.3057 +                     {
  1.3058 +                        entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
  1.3059 +                     }
  1.3060 +
  1.3061 +                     *outrow = (png_byte)entry;
  1.3062 +                  }
  1.3063 +                  break;
  1.3064 +
  1.3065 +               case PNG_CMAP_TRANS:
  1.3066 +                  for (; outrow < end_row; outrow += stepx)
  1.3067 +                  {
  1.3068 +                     png_byte gray = *inrow++;
  1.3069 +                     png_byte alpha = *inrow++;
  1.3070 +
  1.3071 +                     if (alpha == 0)
  1.3072 +                        *outrow = PNG_CMAP_TRANS_BACKGROUND;
  1.3073 +
  1.3074 +                     else if (gray != PNG_CMAP_TRANS_BACKGROUND)
  1.3075 +                        *outrow = gray;
  1.3076 +
  1.3077 +                     else
  1.3078 +                        *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
  1.3079 +                  }
  1.3080 +                  break;
  1.3081 +
  1.3082 +               case PNG_CMAP_RGB:
  1.3083 +                  for (; outrow < end_row; outrow += stepx)
  1.3084 +                  {
  1.3085 +                     *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
  1.3086 +                     inrow += 3;
  1.3087 +                  }
  1.3088 +                  break;
  1.3089 +
  1.3090 +               case PNG_CMAP_RGB_ALPHA:
  1.3091 +                  for (; outrow < end_row; outrow += stepx)
  1.3092 +                  {
  1.3093 +                     unsigned int alpha = inrow[3];
  1.3094 +
  1.3095 +                     /* Because the alpha entries only hold alpha==0.5 values
  1.3096 +                      * split the processing at alpha==0.25 (64) and 0.75
  1.3097 +                      * (196).
  1.3098 +                      */
  1.3099 +
  1.3100 +                     if (alpha >= 196)
  1.3101 +                        *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
  1.3102 +                           inrow[2]);
  1.3103 +
  1.3104 +                     else if (alpha < 64)
  1.3105 +                        *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
  1.3106 +
  1.3107 +                     else
  1.3108 +                     {
  1.3109 +                        /* Likewise there are three entries for each of r, g
  1.3110 +                         * and b.  We could select the entry by popcount on
  1.3111 +                         * the top two bits on those architectures that
  1.3112 +                         * support it, this is what the code below does,
  1.3113 +                         * crudely.
  1.3114 +                         */
  1.3115 +                        unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
  1.3116 +
  1.3117 +                        /* Here are how the values map:
  1.3118 +                         *
  1.3119 +                         * 0x00 .. 0x3f -> 0
  1.3120 +                         * 0x40 .. 0xbf -> 1
  1.3121 +                         * 0xc0 .. 0xff -> 2
  1.3122 +                         *
  1.3123 +                         * So, as above with the explicit alpha checks, the
  1.3124 +                         * breakpoints are at 64 and 196.
  1.3125 +                         */
  1.3126 +                        if (inrow[0] & 0x80) back_i += 9; /* red */
  1.3127 +                        if (inrow[0] & 0x40) back_i += 9;
  1.3128 +                        if (inrow[0] & 0x80) back_i += 3; /* green */
  1.3129 +                        if (inrow[0] & 0x40) back_i += 3;
  1.3130 +                        if (inrow[0] & 0x80) back_i += 1; /* blue */
  1.3131 +                        if (inrow[0] & 0x40) back_i += 1;
  1.3132 +
  1.3133 +                        *outrow = (png_byte)back_i;
  1.3134 +                     }
  1.3135 +
  1.3136 +                     inrow += 4;
  1.3137 +                  }
  1.3138 +                  break;
  1.3139 +
  1.3140 +               default:
  1.3141 +                  break;
  1.3142 +            }
  1.3143 +         }
  1.3144 +      }
  1.3145 +   }
  1.3146 +
  1.3147 +   return 1;
  1.3148 +}
  1.3149 +
  1.3150 +static int
  1.3151 +png_image_read_colormapped(png_voidp argument)
  1.3152 +{
  1.3153 +   png_image_read_control *display = png_voidcast(png_image_read_control*,
  1.3154 +      argument);
  1.3155 +   png_imagep image = display->image;
  1.3156 +   png_controlp control = image->opaque;
  1.3157 +   png_structrp png_ptr = control->png_ptr;
  1.3158 +   png_inforp info_ptr = control->info_ptr;
  1.3159 +
  1.3160 +   int passes = 0; /* As a flag */
  1.3161 +
  1.3162 +   PNG_SKIP_CHUNKS(png_ptr);
  1.3163 +
  1.3164 +   /* Update the 'info' structure and make sure the result is as required; first
  1.3165 +    * make sure to turn on the interlace handling if it will be required
  1.3166 +    * (because it can't be turned on *after* the call to png_read_update_info!)
  1.3167 +    */
  1.3168 +   if (display->colormap_processing == PNG_CMAP_NONE)
  1.3169 +      passes = png_set_interlace_handling(png_ptr);
  1.3170 +
  1.3171 +   png_read_update_info(png_ptr, info_ptr);
  1.3172 +
  1.3173 +   /* The expected output can be deduced from the colormap_processing option. */
  1.3174 +   switch (display->colormap_processing)
  1.3175 +   {
  1.3176 +      case PNG_CMAP_NONE:
  1.3177 +         /* Output must be one channel and one byte per pixel, the output
  1.3178 +          * encoding can be anything.
  1.3179 +          */
  1.3180 +         if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
  1.3181 +            info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
  1.3182 +            info_ptr->bit_depth == 8)
  1.3183 +            break;
  1.3184 +
  1.3185 +         goto bad_output;
  1.3186 +
  1.3187 +      case PNG_CMAP_TRANS:
  1.3188 +      case PNG_CMAP_GA:
  1.3189 +         /* Output must be two channels and the 'G' one must be sRGB, the latter
  1.3190 +          * can be checked with an exact number because it should have been set
  1.3191 +          * to this number above!
  1.3192 +          */
  1.3193 +         if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
  1.3194 +            info_ptr->bit_depth == 8 &&
  1.3195 +            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
  1.3196 +            image->colormap_entries == 256)
  1.3197 +            break;
  1.3198 +
  1.3199 +         goto bad_output;
  1.3200 +
  1.3201 +      case PNG_CMAP_RGB:
  1.3202 +         /* Output must be 8-bit sRGB encoded RGB */
  1.3203 +         if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
  1.3204 +            info_ptr->bit_depth == 8 &&
  1.3205 +            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
  1.3206 +            image->colormap_entries == 216)
  1.3207 +            break;
  1.3208 +
  1.3209 +         goto bad_output;
  1.3210 +
  1.3211 +      case PNG_CMAP_RGB_ALPHA:
  1.3212 +         /* Output must be 8-bit sRGB encoded RGBA */
  1.3213 +         if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
  1.3214 +            info_ptr->bit_depth == 8 &&
  1.3215 +            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
  1.3216 +            image->colormap_entries == 244 /* 216 + 1 + 27 */)
  1.3217 +            break;
  1.3218 +
  1.3219 +         /* goto bad_output; */
  1.3220 +         /* FALL THROUGH */
  1.3221 +
  1.3222 +      default:
  1.3223 +      bad_output:
  1.3224 +         png_error(png_ptr, "bad color-map processing (internal error)");
  1.3225 +   }
  1.3226 +
  1.3227 +   /* Now read the rows.  Do this here if it is possible to read directly into
  1.3228 +    * the output buffer, otherwise allocate a local row buffer of the maximum
  1.3229 +    * size libpng requires and call the relevant processing routine safely.
  1.3230 +    */
  1.3231 +   {
  1.3232 +      png_voidp first_row = display->buffer;
  1.3233 +      ptrdiff_t row_bytes = display->row_stride;
  1.3234 +
  1.3235 +      /* The following expression is designed to work correctly whether it gives
  1.3236 +       * a signed or an unsigned result.
  1.3237 +       */
  1.3238 +      if (row_bytes < 0)
  1.3239 +      {
  1.3240 +         char *ptr = png_voidcast(char*, first_row);
  1.3241 +         ptr += (image->height-1) * (-row_bytes);
  1.3242 +         first_row = png_voidcast(png_voidp, ptr);
  1.3243 +      }
  1.3244 +
  1.3245 +      display->first_row = first_row;
  1.3246 +      display->row_bytes = row_bytes;
  1.3247 +   }
  1.3248 +
  1.3249 +   if (passes == 0)
  1.3250 +   {
  1.3251 +      int result;
  1.3252 +      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
  1.3253 +
  1.3254 +      display->local_row = row;
  1.3255 +      result = png_safe_execute(image, png_image_read_and_map, display);
  1.3256 +      display->local_row = NULL;
  1.3257 +      png_free(png_ptr, row);
  1.3258 +
  1.3259 +      return result;
  1.3260 +   }
  1.3261 +
  1.3262 +   else
  1.3263 +   {
  1.3264 +      png_alloc_size_t row_bytes = display->row_bytes;
  1.3265 +
  1.3266 +      while (--passes >= 0)
  1.3267 +      {
  1.3268 +         png_uint_32      y = image->height;
  1.3269 +         png_bytep        row = png_voidcast(png_bytep, display->first_row);
  1.3270 +
  1.3271 +         while (y-- > 0)
  1.3272 +         {
  1.3273 +            png_read_row(png_ptr, row, NULL);
  1.3274 +            row += row_bytes;
  1.3275 +         }
  1.3276 +      }
  1.3277 +
  1.3278 +      return 1;
  1.3279 +   }
  1.3280 +}
  1.3281 +
  1.3282 +/* Just the row reading part of png_image_read. */
  1.3283 +static int
  1.3284 +png_image_read_composite(png_voidp argument)
  1.3285 +{
  1.3286 +   png_image_read_control *display = png_voidcast(png_image_read_control*,
  1.3287 +      argument);
  1.3288 +   png_imagep image = display->image;
  1.3289 +   png_structrp png_ptr = image->opaque->png_ptr;
  1.3290 +   int passes;
  1.3291 +
  1.3292 +   switch (png_ptr->interlaced)
  1.3293 +   {
  1.3294 +      case PNG_INTERLACE_NONE:
  1.3295 +         passes = 1;
  1.3296 +         break;
  1.3297 +
  1.3298 +      case PNG_INTERLACE_ADAM7:
  1.3299 +         passes = PNG_INTERLACE_ADAM7_PASSES;
  1.3300 +         break;
  1.3301 +
  1.3302 +      default:
  1.3303 +         png_error(png_ptr, "unknown interlace type");
  1.3304 +   }
  1.3305 +
  1.3306 +   {
  1.3307 +      png_uint_32  height = image->height;
  1.3308 +      png_uint_32  width = image->width;
  1.3309 +      ptrdiff_t    step_row = display->row_bytes;
  1.3310 +      unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
  1.3311 +      int pass;
  1.3312 +
  1.3313 +      for (pass = 0; pass < passes; ++pass)
  1.3314 +      {
  1.3315 +         unsigned int     startx, stepx, stepy;
  1.3316 +         png_uint_32      y;
  1.3317 +
  1.3318 +         if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
  1.3319 +         {
  1.3320 +            /* The row may be empty for a short image: */
  1.3321 +            if (PNG_PASS_COLS(width, pass) == 0)
  1.3322 +               continue;
  1.3323 +
  1.3324 +            startx = PNG_PASS_START_COL(pass) * channels;
  1.3325 +            stepx = PNG_PASS_COL_OFFSET(pass) * channels;
  1.3326 +            y = PNG_PASS_START_ROW(pass);
  1.3327 +            stepy = PNG_PASS_ROW_OFFSET(pass);
  1.3328 +         }
  1.3329 +
  1.3330 +         else
  1.3331 +         {
  1.3332 +            y = 0;
  1.3333 +            startx = 0;
  1.3334 +            stepx = channels;
  1.3335 +            stepy = 1;
  1.3336 +         }
  1.3337 +
  1.3338 +         for (; y<height; y += stepy)
  1.3339 +         {
  1.3340 +            png_bytep inrow = png_voidcast(png_bytep, display->local_row);
  1.3341 +            png_bytep outrow;
  1.3342 +            png_const_bytep end_row;
  1.3343 +
  1.3344 +            /* Read the row, which is packed: */
  1.3345 +            png_read_row(png_ptr, inrow, NULL);
  1.3346 +
  1.3347 +            outrow = png_voidcast(png_bytep, display->first_row);
  1.3348 +            outrow += y * step_row;
  1.3349 +            end_row = outrow + width * channels;
  1.3350 +
  1.3351 +            /* Now do the composition on each pixel in this row. */
  1.3352 +            outrow += startx;
  1.3353 +            for (; outrow < end_row; outrow += stepx)
  1.3354 +            {
  1.3355 +               png_byte alpha = inrow[channels];
  1.3356 +
  1.3357 +               if (alpha > 0) /* else no change to the output */
  1.3358 +               {
  1.3359 +                  unsigned int c;
  1.3360 +
  1.3361 +                  for (c=0; c<channels; ++c)
  1.3362 +                  {
  1.3363 +                     png_uint_32 component = inrow[c];
  1.3364 +
  1.3365 +                     if (alpha < 255) /* else just use component */
  1.3366 +                     {
  1.3367 +                        /* This is PNG_OPTIMIZED_ALPHA, the component value
  1.3368 +                         * is a linear 8-bit value.  Combine this with the
  1.3369 +                         * current outrow[c] value which is sRGB encoded.
  1.3370 +                         * Arithmetic here is 16-bits to preserve the output
  1.3371 +                         * values correctly.
  1.3372 +                         */
  1.3373 +                        component *= 257*255; /* =65535 */
  1.3374 +                        component += (255-alpha)*png_sRGB_table[outrow[c]];
  1.3375 +
  1.3376 +                        /* So 'component' is scaled by 255*65535 and is
  1.3377 +                         * therefore appropriate for the sRGB to linear
  1.3378 +                         * conversion table.
  1.3379 +                         */
  1.3380 +                        component = PNG_sRGB_FROM_LINEAR(component);
  1.3381 +                     }
  1.3382 +
  1.3383 +                     outrow[c] = (png_byte)component;
  1.3384 +                  }
  1.3385 +               }
  1.3386 +
  1.3387 +               inrow += channels+1; /* components and alpha channel */
  1.3388 +            }
  1.3389 +         }
  1.3390 +      }
  1.3391 +   }
  1.3392 +
  1.3393 +   return 1;
  1.3394 +}
  1.3395 +
  1.3396 +/* The do_local_background case; called when all the following transforms are to
  1.3397 + * be done:
  1.3398 + *
  1.3399 + * PNG_RGB_TO_GRAY
  1.3400 + * PNG_COMPOSITE
  1.3401 + * PNG_GAMMA
  1.3402 + *
  1.3403 + * This is a work-round for the fact that both the PNG_RGB_TO_GRAY and
  1.3404 + * PNG_COMPOSITE code performs gamma correction, so we get double gamma
  1.3405 + * correction.  The fix-up is to prevent the PNG_COMPOSITE operation happening
  1.3406 + * inside libpng, so this routine sees an 8 or 16-bit gray+alpha row and handles
  1.3407 + * the removal or pre-multiplication of the alpha channel.
  1.3408 + */
  1.3409 +static int
  1.3410 +png_image_read_background(png_voidp argument)
  1.3411 +{
  1.3412 +   png_image_read_control *display = png_voidcast(png_image_read_control*,
  1.3413 +      argument);
  1.3414 +   png_imagep image = display->image;
  1.3415 +   png_structrp png_ptr = image->opaque->png_ptr;
  1.3416 +   png_inforp info_ptr = image->opaque->info_ptr;
  1.3417 +   png_uint_32 height = image->height;
  1.3418 +   png_uint_32 width = image->width;
  1.3419 +   int pass, passes;
  1.3420 +
  1.3421 +   /* Double check the convoluted logic below.  We expect to get here with
  1.3422 +    * libpng doing rgb to gray and gamma correction but background processing
  1.3423 +    * left to the png_image_read_background function.  The rows libpng produce
  1.3424 +    * might be 8 or 16-bit but should always have two channels; gray plus alpha.
  1.3425 +    */
  1.3426 +   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
  1.3427 +      png_error(png_ptr, "lost rgb to gray");
  1.3428 +
  1.3429 +   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
  1.3430 +      png_error(png_ptr, "unexpected compose");
  1.3431 +
  1.3432 +   if (png_get_channels(png_ptr, info_ptr) != 2)
  1.3433 +      png_error(png_ptr, "lost/gained channels");
  1.3434 +
  1.3435 +   /* Expect the 8-bit case to always remove the alpha channel */
  1.3436 +   if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
  1.3437 +      (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
  1.3438 +      png_error(png_ptr, "unexpected 8-bit transformation");
  1.3439 +
  1.3440 +   switch (png_ptr->interlaced)
  1.3441 +   {
  1.3442 +      case PNG_INTERLACE_NONE:
  1.3443 +         passes = 1;
  1.3444 +         break;
  1.3445 +
  1.3446 +      case PNG_INTERLACE_ADAM7:
  1.3447 +         passes = PNG_INTERLACE_ADAM7_PASSES;
  1.3448 +         break;
  1.3449 +
  1.3450 +      default:
  1.3451 +         png_error(png_ptr, "unknown interlace type");
  1.3452 +   }
  1.3453 +
  1.3454 +   /* Use direct access to info_ptr here because otherwise the simplified API
  1.3455 +    * would require PNG_EASY_ACCESS_SUPPORTED (just for this.)  Note this is
  1.3456 +    * checking the value after libpng expansions, not the original value in the
  1.3457 +    * PNG.
  1.3458 +    */
  1.3459 +   switch (info_ptr->bit_depth)
  1.3460 +   {
  1.3461 +      default:
  1.3462 +         png_error(png_ptr, "unexpected bit depth");
  1.3463 +         break;
  1.3464 +
  1.3465 +      case 8:
  1.3466 +         /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
  1.3467 +          * to be removed by composing on a background: either the row if
  1.3468 +          * display->background is NULL or display->background->green if not.
  1.3469 +          * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
  1.3470 +          */
  1.3471 +         {
  1.3472 +            png_bytep first_row = png_voidcast(png_bytep, display->first_row);
  1.3473 +            ptrdiff_t step_row = display->row_bytes;
  1.3474 +
  1.3475 +            for (pass = 0; pass < passes; ++pass)
  1.3476 +            {
  1.3477 +               png_bytep        row = png_voidcast(png_bytep,
  1.3478 +                                                   display->first_row);
  1.3479 +               unsigned int     startx, stepx, stepy;
  1.3480 +               png_uint_32      y;
  1.3481 +
  1.3482 +               if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
  1.3483 +               {
  1.3484 +                  /* The row may be empty for a short image: */
  1.3485 +                  if (PNG_PASS_COLS(width, pass) == 0)
  1.3486 +                     continue;
  1.3487 +
  1.3488 +                  startx = PNG_PASS_START_COL(pass);
  1.3489 +                  stepx = PNG_PASS_COL_OFFSET(pass);
  1.3490 +                  y = PNG_PASS_START_ROW(pass);
  1.3491 +                  stepy = PNG_PASS_ROW_OFFSET(pass);
  1.3492 +               }
  1.3493 +
  1.3494 +               else
  1.3495 +               {
  1.3496 +                  y = 0;
  1.3497 +                  startx = 0;
  1.3498 +                  stepx = stepy = 1;
  1.3499 +               }
  1.3500 +
  1.3501 +               if (display->background == NULL)
  1.3502 +               {
  1.3503 +                  for (; y<height; y += stepy)
  1.3504 +                  {
  1.3505 +                     png_bytep inrow = png_voidcast(png_bytep,
  1.3506 +                        display->local_row);
  1.3507 +                     png_bytep outrow = first_row + y * step_row;
  1.3508 +                     png_const_bytep end_row = outrow + width;
  1.3509 +
  1.3510 +                     /* Read the row, which is packed: */
  1.3511 +                     png_read_row(png_ptr, inrow, NULL);
  1.3512 +
  1.3513 +                     /* Now do the composition on each pixel in this row. */
  1.3514 +                     outrow += startx;
  1.3515 +                     for (; outrow < end_row; outrow += stepx)
  1.3516 +                     {
  1.3517 +                        png_byte alpha = inrow[1];
  1.3518 +
  1.3519 +                        if (alpha > 0) /* else no change to the output */
  1.3520 +                        {
  1.3521 +                           png_uint_32 component = inrow[0];
  1.3522 +
  1.3523 +                           if (alpha < 255) /* else just use component */
  1.3524 +                           {
  1.3525 +                              /* Since PNG_OPTIMIZED_ALPHA was not set it is
  1.3526 +                               * necessary to invert the sRGB transfer
  1.3527 +                               * function and multiply the alpha out.
  1.3528 +                               */
  1.3529 +                              component = png_sRGB_table[component] * alpha;
  1.3530 +                              component += png_sRGB_table[outrow[0]] *
  1.3531 +                                 (255-alpha);
  1.3532 +                              component = PNG_sRGB_FROM_LINEAR(component);
  1.3533 +                           }
  1.3534 +
  1.3535 +                           outrow[0] = (png_byte)component;
  1.3536 +                        }
  1.3537 +
  1.3538 +                        inrow += 2; /* gray and alpha channel */
  1.3539 +                     }
  1.3540 +                  }
  1.3541 +               }
  1.3542 +
  1.3543 +               else /* constant background value */
  1.3544 +               {
  1.3545 +                  png_byte background8 = display->background->green;
  1.3546 +                  png_uint_16 background = png_sRGB_table[background8];
  1.3547 +
  1.3548 +                  for (; y<height; y += stepy)
  1.3549 +                  {
  1.3550 +                     png_bytep inrow = png_voidcast(png_bytep,
  1.3551 +                        display->local_row);
  1.3552 +                     png_bytep outrow = first_row + y * step_row;
  1.3553 +                     png_const_bytep end_row = outrow + width;
  1.3554 +
  1.3555 +                     /* Read the row, which is packed: */
  1.3556 +                     png_read_row(png_ptr, inrow, NULL);
  1.3557 +
  1.3558 +                     /* Now do the composition on each pixel in this row. */
  1.3559 +                     outrow += startx;
  1.3560 +                     for (; outrow < end_row; outrow += stepx)
  1.3561 +                     {
  1.3562 +                        png_byte alpha = inrow[1];
  1.3563 +
  1.3564 +                        if (alpha > 0) /* else use background */
  1.3565 +                        {
  1.3566 +                           png_uint_32 component = inrow[0];
  1.3567 +
  1.3568 +                           if (alpha < 255) /* else just use component */
  1.3569 +                           {
  1.3570 +                              component = png_sRGB_table[component] * alpha;
  1.3571 +                              component += background * (255-alpha);
  1.3572 +                              component = PNG_sRGB_FROM_LINEAR(component);
  1.3573 +                           }
  1.3574 +
  1.3575 +                           outrow[0] = (png_byte)component;
  1.3576 +                        }
  1.3577 +
  1.3578 +                        else
  1.3579 +                           outrow[0] = background8;
  1.3580 +
  1.3581 +                        inrow += 2; /* gray and alpha channel */
  1.3582 +                     }
  1.3583 +
  1.3584 +                     row += display->row_bytes;
  1.3585 +                  }
  1.3586 +               }
  1.3587 +            }
  1.3588 +         }
  1.3589 +         break;
  1.3590 +
  1.3591 +      case 16:
  1.3592 +         /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
  1.3593 +          * still be done and, maybe, the alpha channel removed.  This code also
  1.3594 +          * handles the alpha-first option.
  1.3595 +          */
  1.3596 +         {
  1.3597 +            png_uint_16p first_row = png_voidcast(png_uint_16p,
  1.3598 +               display->first_row);
  1.3599 +            /* The division by two is safe because the caller passed in a
  1.3600 +             * stride which was multiplied by 2 (below) to get row_bytes.
  1.3601 +             */
  1.3602 +            ptrdiff_t    step_row = display->row_bytes / 2;
  1.3603 +            int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
  1.3604 +            unsigned int outchannels = 1+preserve_alpha;
  1.3605 +            int swap_alpha = 0;
  1.3606 +
  1.3607 +#           ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
  1.3608 +               if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST))
  1.3609 +                  swap_alpha = 1;
  1.3610 +#           endif
  1.3611 +
  1.3612 +            for (pass = 0; pass < passes; ++pass)
  1.3613 +            {
  1.3614 +               unsigned int     startx, stepx, stepy;
  1.3615 +               png_uint_32      y;
  1.3616 +
  1.3617 +               /* The 'x' start and step are adjusted to output components here.
  1.3618 +                */
  1.3619 +               if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
  1.3620 +               {
  1.3621 +                  /* The row may be empty for a short image: */
  1.3622 +                  if (PNG_PASS_COLS(width, pass) == 0)
  1.3623 +                     continue;
  1.3624 +
  1.3625 +                  startx = PNG_PASS_START_COL(pass) * outchannels;
  1.3626 +                  stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
  1.3627 +                  y = PNG_PASS_START_ROW(pass);
  1.3628 +                  stepy = PNG_PASS_ROW_OFFSET(pass);
  1.3629 +               }
  1.3630 +
  1.3631 +               else
  1.3632 +               {
  1.3633 +                  y = 0;
  1.3634 +                  startx = 0;
  1.3635 +                  stepx = outchannels;
  1.3636 +                  stepy = 1;
  1.3637 +               }
  1.3638 +
  1.3639 +               for (; y<height; y += stepy)
  1.3640 +               {
  1.3641 +                  png_const_uint_16p inrow;
  1.3642 +                  png_uint_16p outrow = first_row + y*step_row;
  1.3643 +                  png_uint_16p end_row = outrow + width * outchannels;
  1.3644 +
  1.3645 +                  /* Read the row, which is packed: */
  1.3646 +                  png_read_row(png_ptr, png_voidcast(png_bytep,
  1.3647 +                     display->local_row), NULL);
  1.3648 +                  inrow = png_voidcast(png_const_uint_16p, display->local_row);
  1.3649 +
  1.3650 +                  /* Now do the pre-multiplication on each pixel in this row.
  1.3651 +                   */
  1.3652 +                  outrow += startx;
  1.3653 +                  for (; outrow < end_row; outrow += stepx)
  1.3654 +                  {
  1.3655 +                     png_uint_32 component = inrow[0];
  1.3656 +                     png_uint_16 alpha = inrow[1];
  1.3657 +
  1.3658 +                     if (alpha > 0) /* else 0 */
  1.3659 +                     {
  1.3660 +                        if (alpha < 65535) /* else just use component */
  1.3661 +                        {
  1.3662 +                           component *= alpha;
  1.3663 +                           component += 32767;
  1.3664 +                           component /= 65535;
  1.3665 +                        }
  1.3666 +                     }
  1.3667 +
  1.3668 +                     else
  1.3669 +                        component = 0;
  1.3670 +
  1.3671 +                     outrow[swap_alpha] = (png_uint_16)component;
  1.3672 +                     if (preserve_alpha)
  1.3673 +                        outrow[1 ^ swap_alpha] = alpha;
  1.3674 +
  1.3675 +                     inrow += 2; /* components and alpha channel */
  1.3676 +                  }
  1.3677 +               }
  1.3678 +            }
  1.3679 +         }
  1.3680 +         break;
  1.3681 +   }
  1.3682 +
  1.3683 +   return 1;
  1.3684 +}
  1.3685 +
  1.3686 +/* The guts of png_image_finish_read as a png_safe_execute callback. */
  1.3687 +static int
  1.3688 +png_image_read_direct(png_voidp argument)
  1.3689 +{
  1.3690 +   png_image_read_control *display = png_voidcast(png_image_read_control*,
  1.3691 +      argument);
  1.3692 +   png_imagep image = display->image;
  1.3693 +   png_structrp png_ptr = image->opaque->png_ptr;
  1.3694 +   png_inforp info_ptr = image->opaque->info_ptr;
  1.3695 +
  1.3696 +   png_uint_32 format = image->format;
  1.3697 +   int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
  1.3698 +   int do_local_compose = 0;
  1.3699 +   int do_local_background = 0; /* to avoid double gamma correction bug */
  1.3700 +   int passes = 0;
  1.3701 +
  1.3702 +   /* Add transforms to ensure the correct output format is produced then check
  1.3703 +    * that the required implementation support is there.  Always expand; always
  1.3704 +    * need 8 bits minimum, no palette and expanded tRNS.
  1.3705 +    */
  1.3706 +   png_set_expand(png_ptr);
  1.3707 +
  1.3708 +   /* Now check the format to see if it was modified. */
  1.3709 +   {
  1.3710 +      png_uint_32 base_format = png_image_format(png_ptr) &
  1.3711 +         ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;
  1.3712 +      png_uint_32 change = format ^ base_format;
  1.3713 +      png_fixed_point output_gamma;
  1.3714 +      int mode; /* alpha mode */
  1.3715 +
  1.3716 +      /* Do this first so that we have a record if rgb to gray is happening. */
  1.3717 +      if (change & PNG_FORMAT_FLAG_COLOR)
  1.3718 +      {
  1.3719 +         /* gray<->color transformation required. */
  1.3720 +         if (format & PNG_FORMAT_FLAG_COLOR)
  1.3721 +            png_set_gray_to_rgb(png_ptr);
  1.3722 +
  1.3723 +         else
  1.3724 +         {
  1.3725 +            /* libpng can't do both rgb to gray and
  1.3726 +             * background/pre-multiplication if there is also significant gamma
  1.3727 +             * correction, because both operations require linear colors and
  1.3728 +             * the code only supports one transform doing the gamma correction.
  1.3729 +             * Handle this by doing the pre-multiplication or background
  1.3730 +             * operation in this code, if necessary.
  1.3731 +             *
  1.3732 +             * TODO: fix this by rewriting pngrtran.c (!)
  1.3733 +             *
  1.3734 +             * For the moment (given that fixing this in pngrtran.c is an
  1.3735 +             * enormous change) 'do_local_background' is used to indicate that
  1.3736 +             * the problem exists.
  1.3737 +             */
  1.3738 +            if (base_format & PNG_FORMAT_FLAG_ALPHA)
  1.3739 +               do_local_background = 1/*maybe*/;
  1.3740 +
  1.3741 +            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
  1.3742 +               PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
  1.3743 +         }
  1.3744 +
  1.3745 +         change &= ~PNG_FORMAT_FLAG_COLOR;
  1.3746 +      }
  1.3747 +
  1.3748 +      /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
  1.3749 +       */
  1.3750 +      {
  1.3751 +         png_fixed_point input_gamma_default;
  1.3752 +
  1.3753 +         if ((base_format & PNG_FORMAT_FLAG_LINEAR) &&
  1.3754 +            (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
  1.3755 +            input_gamma_default = PNG_GAMMA_LINEAR;
  1.3756 +         else
  1.3757 +            input_gamma_default = PNG_DEFAULT_sRGB;
  1.3758 +
  1.3759 +         /* Call png_set_alpha_mode to set the default for the input gamma; the
  1.3760 +          * output gamma is set by a second call below.
  1.3761 +          */
  1.3762 +         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
  1.3763 +      }
  1.3764 +
  1.3765 +      if (linear)
  1.3766 +      {
  1.3767 +         /* If there *is* an alpha channel in the input it must be multiplied
  1.3768 +          * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
  1.3769 +          */
  1.3770 +         if (base_format & PNG_FORMAT_FLAG_ALPHA)
  1.3771 +            mode = PNG_ALPHA_STANDARD; /* associated alpha */
  1.3772 +
  1.3773 +         else
  1.3774 +            mode = PNG_ALPHA_PNG;
  1.3775 +
  1.3776 +         output_gamma = PNG_GAMMA_LINEAR;
  1.3777 +      }
  1.3778 +
  1.3779 +      else
  1.3780 +      {
  1.3781 +         mode = PNG_ALPHA_PNG;
  1.3782 +         output_gamma = PNG_DEFAULT_sRGB;
  1.3783 +      }
  1.3784 +
  1.3785 +      /* If 'do_local_background' is set check for the presence of gamma
  1.3786 +       * correction; this is part of the work-round for the libpng bug
  1.3787 +       * described above.
  1.3788 +       *
  1.3789 +       * TODO: fix libpng and remove this.
  1.3790 +       */
  1.3791 +      if (do_local_background)
  1.3792 +      {
  1.3793 +         png_fixed_point gtest;
  1.3794 +
  1.3795 +         /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
  1.3796 +          * gamma correction, the screen gamma hasn't been set on png_struct
  1.3797 +          * yet; it's set below.  png_struct::gamma, however, is set to the
  1.3798 +          * final value.
  1.3799 +          */
  1.3800 +         if (png_muldiv(&gtest, output_gamma, png_ptr->colorspace.gamma,
  1.3801 +               PNG_FP_1) && !png_gamma_significant(gtest))
  1.3802 +            do_local_background = 0;
  1.3803 +
  1.3804 +         else if (mode == PNG_ALPHA_STANDARD)
  1.3805 +         {
  1.3806 +            do_local_background = 2/*required*/;
  1.3807 +            mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
  1.3808 +         }
  1.3809 +
  1.3810 +         /* else leave as 1 for the checks below */
  1.3811 +      }
  1.3812 +
  1.3813 +      /* If the bit-depth changes then handle that here. */
  1.3814 +      if (change & PNG_FORMAT_FLAG_LINEAR)
  1.3815 +      {
  1.3816 +         if (linear /*16-bit output*/)
  1.3817 +            png_set_expand_16(png_ptr);
  1.3818 +
  1.3819 +         else /* 8-bit output */
  1.3820 +            png_set_scale_16(png_ptr);
  1.3821 +
  1.3822 +         change &= ~PNG_FORMAT_FLAG_LINEAR;
  1.3823 +      }
  1.3824 +
  1.3825 +      /* Now the background/alpha channel changes. */
  1.3826 +      if (change & PNG_FORMAT_FLAG_ALPHA)
  1.3827 +      {
  1.3828 +         /* Removing an alpha channel requires composition for the 8-bit
  1.3829 +          * formats; for the 16-bit it is already done, above, by the
  1.3830 +          * pre-multiplication and the channel just needs to be stripped.
  1.3831 +          */
  1.3832 +         if (base_format & PNG_FORMAT_FLAG_ALPHA)
  1.3833 +         {
  1.3834 +            /* If RGB->gray is happening the alpha channel must be left and the
  1.3835 +             * operation completed locally.
  1.3836 +             *
  1.3837 +             * TODO: fix libpng and remove this.
  1.3838 +             */
  1.3839 +            if (do_local_background)
  1.3840 +               do_local_background = 2/*required*/;
  1.3841 +
  1.3842 +            /* 16-bit output: just remove the channel */
  1.3843 +            else if (linear) /* compose on black (well, pre-multiply) */
  1.3844 +               png_set_strip_alpha(png_ptr);
  1.3845 +
  1.3846 +            /* 8-bit output: do an appropriate compose */
  1.3847 +            else if (display->background != NULL)
  1.3848 +            {
  1.3849 +               png_color_16 c;
  1.3850 +
  1.3851 +               c.index = 0; /*unused*/
  1.3852 +               c.red = display->background->red;
  1.3853 +               c.green = display->background->green;
  1.3854 +               c.blue = display->background->blue;
  1.3855 +               c.gray = display->background->green;
  1.3856 +
  1.3857 +               /* This is always an 8-bit sRGB value, using the 'green' channel
  1.3858 +                * for gray is much better than calculating the luminance here;
  1.3859 +                * we can get off-by-one errors in that calculation relative to
  1.3860 +                * the app expectations and that will show up in transparent
  1.3861 +                * pixels.
  1.3862 +                */
  1.3863 +               png_set_background_fixed(png_ptr, &c,
  1.3864 +                  PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
  1.3865 +                  0/*gamma: not used*/);
  1.3866 +            }
  1.3867 +
  1.3868 +            else /* compose on row: implemented below. */
  1.3869 +            {
  1.3870 +               do_local_compose = 1;
  1.3871 +               /* This leaves the alpha channel in the output, so it has to be
  1.3872 +                * removed by the code below.  Set the encoding to the 'OPTIMIZE'
  1.3873 +                * one so the code only has to hack on the pixels that require
  1.3874 +                * composition.
  1.3875 +                */
  1.3876 +               mode = PNG_ALPHA_OPTIMIZED;
  1.3877 +            }
  1.3878 +         }
  1.3879 +
  1.3880 +         else /* output needs an alpha channel */
  1.3881 +         {
  1.3882 +            /* This is tricky because it happens before the swap operation has
  1.3883 +             * been accomplished; however, the swap does *not* swap the added
  1.3884 +             * alpha channel (weird API), so it must be added in the correct
  1.3885 +             * place.
  1.3886 +             */
  1.3887 +            png_uint_32 filler; /* opaque filler */
  1.3888 +            int where;
  1.3889 +
  1.3890 +            if (linear)
  1.3891 +               filler = 65535;
  1.3892 +
  1.3893 +            else
  1.3894 +               filler = 255;
  1.3895 +
  1.3896 +#           ifdef PNG_FORMAT_AFIRST_SUPPORTED
  1.3897 +               if (format & PNG_FORMAT_FLAG_AFIRST)
  1.3898 +               {
  1.3899 +                  where = PNG_FILLER_BEFORE;
  1.3900 +                  change &= ~PNG_FORMAT_FLAG_AFIRST;
  1.3901 +               }
  1.3902 +
  1.3903 +               else
  1.3904 +#           endif
  1.3905 +               where = PNG_FILLER_AFTER;
  1.3906 +
  1.3907 +            png_set_add_alpha(png_ptr, filler, where);
  1.3908 +         }
  1.3909 +
  1.3910 +         /* This stops the (irrelevant) call to swap_alpha below. */
  1.3911 +         change &= ~PNG_FORMAT_FLAG_ALPHA;
  1.3912 +      }
  1.3913 +
  1.3914 +      /* Now set the alpha mode correctly; this is always done, even if there is
  1.3915 +       * no alpha channel in either the input or the output because it correctly
  1.3916 +       * sets the output gamma.
  1.3917 +       */
  1.3918 +      png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
  1.3919 +
  1.3920 +#     ifdef PNG_FORMAT_BGR_SUPPORTED
  1.3921 +         if (change & PNG_FORMAT_FLAG_BGR)
  1.3922 +         {
  1.3923 +            /* Check only the output format; PNG is never BGR; don't do this if
  1.3924 +             * the output is gray, but fix up the 'format' value in that case.
  1.3925 +             */
  1.3926 +            if (format & PNG_FORMAT_FLAG_COLOR)
  1.3927 +               png_set_bgr(png_ptr);
  1.3928 +
  1.3929 +            else
  1.3930 +               format &= ~PNG_FORMAT_FLAG_BGR;
  1.3931 +
  1.3932 +            change &= ~PNG_FORMAT_FLAG_BGR;
  1.3933 +         }
  1.3934 +#     endif
  1.3935 +
  1.3936 +#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
  1.3937 +         if (change & PNG_FORMAT_FLAG_AFIRST)
  1.3938 +         {
  1.3939 +            /* Only relevant if there is an alpha channel - it's particularly
  1.3940 +             * important to handle this correctly because do_local_compose may
  1.3941 +             * be set above and then libpng will keep the alpha channel for this
  1.3942 +             * code to remove.
  1.3943 +             */
  1.3944 +            if (format & PNG_FORMAT_FLAG_ALPHA)
  1.3945 +            {
  1.3946 +               /* Disable this if doing a local background,
  1.3947 +                * TODO: remove this when local background is no longer required.
  1.3948 +                */
  1.3949 +               if (do_local_background != 2)
  1.3950 +                  png_set_swap_alpha(png_ptr);
  1.3951 +            }
  1.3952 +
  1.3953 +            else
  1.3954 +               format &= ~PNG_FORMAT_FLAG_AFIRST;
  1.3955 +
  1.3956 +            change &= ~PNG_FORMAT_FLAG_AFIRST;
  1.3957 +         }
  1.3958 +#     endif
  1.3959 +
  1.3960 +      /* If the *output* is 16-bit then we need to check for a byte-swap on this
  1.3961 +       * architecture.
  1.3962 +       */
  1.3963 +      if (linear)
  1.3964 +      {
  1.3965 +         PNG_CONST png_uint_16 le = 0x0001;
  1.3966 +
  1.3967 +         if (*(png_const_bytep)&le)
  1.3968 +            png_set_swap(png_ptr);
  1.3969 +      }
  1.3970 +
  1.3971 +      /* If change is not now 0 some transformation is missing - error out. */
  1.3972 +      if (change)
  1.3973 +         png_error(png_ptr, "png_read_image: unsupported transformation");
  1.3974 +   }
  1.3975 +
  1.3976 +   PNG_SKIP_CHUNKS(png_ptr);
  1.3977 +
  1.3978 +   /* Update the 'info' structure and make sure the result is as required; first
  1.3979 +    * make sure to turn on the interlace handling if it will be required
  1.3980 +    * (because it can't be turned on *after* the call to png_read_update_info!)
  1.3981 +    *
  1.3982 +    * TODO: remove the do_local_background fixup below.
  1.3983 +    */
  1.3984 +   if (!do_local_compose && do_local_background != 2)
  1.3985 +      passes = png_set_interlace_handling(png_ptr);
  1.3986 +
  1.3987 +   png_read_update_info(png_ptr, info_ptr);
  1.3988 +
  1.3989 +   {
  1.3990 +      png_uint_32 info_format = 0;
  1.3991 +
  1.3992 +      if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
  1.3993 +         info_format |= PNG_FORMAT_FLAG_COLOR;
  1.3994 +
  1.3995 +      if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
  1.3996 +      {
  1.3997 +         /* do_local_compose removes this channel below. */
  1.3998 +         if (!do_local_compose)
  1.3999 +         {
  1.4000 +            /* do_local_background does the same if required. */
  1.4001 +            if (do_local_background != 2 ||
  1.4002 +               (format & PNG_FORMAT_FLAG_ALPHA) != 0)
  1.4003 +               info_format |= PNG_FORMAT_FLAG_ALPHA;
  1.4004 +         }
  1.4005 +      }
  1.4006 +
  1.4007 +      else if (do_local_compose) /* internal error */
  1.4008 +         png_error(png_ptr, "png_image_read: alpha channel lost");
  1.4009 +
  1.4010 +      if (info_ptr->bit_depth == 16)
  1.4011 +         info_format |= PNG_FORMAT_FLAG_LINEAR;
  1.4012 +
  1.4013 +#     ifdef PNG_FORMAT_BGR_SUPPORTED
  1.4014 +         if (png_ptr->transformations & PNG_BGR)
  1.4015 +            info_format |= PNG_FORMAT_FLAG_BGR;
  1.4016 +#     endif
  1.4017 +
  1.4018 +#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
  1.4019 +         if (do_local_background == 2)
  1.4020 +         {
  1.4021 +            if (format & PNG_FORMAT_FLAG_AFIRST)
  1.4022 +               info_format |= PNG_FORMAT_FLAG_AFIRST;
  1.4023 +         }
  1.4024 +
  1.4025 +         if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
  1.4026 +            ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
  1.4027 +            (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
  1.4028 +         {
  1.4029 +            if (do_local_background == 2)
  1.4030 +               png_error(png_ptr, "unexpected alpha swap transformation");
  1.4031 +
  1.4032 +            info_format |= PNG_FORMAT_FLAG_AFIRST;
  1.4033 +         }
  1.4034 +#     endif
  1.4035 +
  1.4036 +      /* This is actually an internal error. */
  1.4037 +      if (info_format != format)
  1.4038 +         png_error(png_ptr, "png_read_image: invalid transformations");
  1.4039 +   }
  1.4040 +
  1.4041 +   /* Now read the rows.  If do_local_compose is set then it is necessary to use
  1.4042 +    * a local row buffer.  The output will be GA, RGBA or BGRA and must be
  1.4043 +    * converted to G, RGB or BGR as appropriate.  The 'local_row' member of the
  1.4044 +    * display acts as a flag.
  1.4045 +    */
  1.4046 +   {
  1.4047 +      png_voidp first_row = display->buffer;
  1.4048 +      ptrdiff_t row_bytes = display->row_stride;
  1.4049 +
  1.4050 +      if (linear)
  1.4051 +         row_bytes *= 2;
  1.4052 +
  1.4053 +      /* The following expression is designed to work correctly whether it gives
  1.4054 +       * a signed or an unsigned result.
  1.4055 +       */
  1.4056 +      if (row_bytes < 0)
  1.4057 +      {
  1.4058 +         char *ptr = png_voidcast(char*, first_row);
  1.4059 +         ptr += (image->height-1) * (-row_bytes);
  1.4060 +         first_row = png_voidcast(png_voidp, ptr);
  1.4061 +      }
  1.4062 +
  1.4063 +      display->first_row = first_row;
  1.4064 +      display->row_bytes = row_bytes;
  1.4065 +   }
  1.4066 +
  1.4067 +   if (do_local_compose)
  1.4068 +   {
  1.4069 +      int result;
  1.4070 +      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
  1.4071 +
  1.4072 +      display->local_row = row;
  1.4073 +      result = png_safe_execute(image, png_image_read_composite, display);
  1.4074 +      display->local_row = NULL;
  1.4075 +      png_free(png_ptr, row);
  1.4076 +
  1.4077 +      return result;
  1.4078 +   }
  1.4079 +
  1.4080 +   else if (do_local_background == 2)
  1.4081 +   {
  1.4082 +      int result;
  1.4083 +      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
  1.4084 +
  1.4085 +      display->local_row = row;
  1.4086 +      result = png_safe_execute(image, png_image_read_background, display);
  1.4087 +      display->local_row = NULL;
  1.4088 +      png_free(png_ptr, row);
  1.4089 +
  1.4090 +      return result;
  1.4091 +   }
  1.4092 +
  1.4093 +   else
  1.4094 +   {
  1.4095 +      png_alloc_size_t row_bytes = display->row_bytes;
  1.4096 +
  1.4097 +      while (--passes >= 0)
  1.4098 +      {
  1.4099 +         png_uint_32      y = image->height;
  1.4100 +         png_bytep        row = png_voidcast(png_bytep, display->first_row);
  1.4101 +
  1.4102 +         while (y-- > 0)
  1.4103 +         {
  1.4104 +            png_read_row(png_ptr, row, NULL);
  1.4105 +            row += row_bytes;
  1.4106 +         }
  1.4107 +      }
  1.4108 +
  1.4109 +      return 1;
  1.4110 +   }
  1.4111 +}
  1.4112 +
  1.4113 +int PNGAPI
  1.4114 +png_image_finish_read(png_imagep image, png_const_colorp background,
  1.4115 +   void *buffer, png_int_32 row_stride, void *colormap)
  1.4116 +{
  1.4117 +   if (image != NULL && image->version == PNG_IMAGE_VERSION)
  1.4118 +   {
  1.4119 +      png_uint_32 check;
  1.4120 +
  1.4121 +      if (row_stride == 0)
  1.4122 +         row_stride = PNG_IMAGE_ROW_STRIDE(*image);
  1.4123 +
  1.4124 +      if (row_stride < 0)
  1.4125 +         check = -row_stride;
  1.4126 +
  1.4127 +      else
  1.4128 +         check = row_stride;
  1.4129 +
  1.4130 +      if (image->opaque != NULL && buffer != NULL &&
  1.4131 +         check >= PNG_IMAGE_ROW_STRIDE(*image))
  1.4132 +      {
  1.4133 +         if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
  1.4134 +            (image->colormap_entries > 0 && colormap != NULL))
  1.4135 +         {
  1.4136 +            int result;
  1.4137 +            png_image_read_control display;
  1.4138 +
  1.4139 +            memset(&display, 0, (sizeof display));
  1.4140 +            display.image = image;
  1.4141 +            display.buffer = buffer;
  1.4142 +            display.row_stride = row_stride;
  1.4143 +            display.colormap = colormap;
  1.4144 +            display.background = background;
  1.4145 +            display.local_row = NULL;
  1.4146 +
  1.4147 +            /* Choose the correct 'end' routine; for the color-map case all the
  1.4148 +             * setup has already been done.
  1.4149 +             */
  1.4150 +            if (image->format & PNG_FORMAT_FLAG_COLORMAP)
  1.4151 +               result =
  1.4152 +                  png_safe_execute(image, png_image_read_colormap, &display) &&
  1.4153 +                  png_safe_execute(image, png_image_read_colormapped, &display);
  1.4154 +
  1.4155 +            else
  1.4156 +               result =
  1.4157 +                  png_safe_execute(image, png_image_read_direct, &display);
  1.4158 +
  1.4159 +            png_image_free(image);
  1.4160 +            return result;
  1.4161 +         }
  1.4162 +
  1.4163 +         else
  1.4164 +            return png_image_error(image,
  1.4165 +               "png_image_finish_read[color-map]: no color-map");
  1.4166 +      }
  1.4167 +
  1.4168 +      else
  1.4169 +         return png_image_error(image,
  1.4170 +            "png_image_finish_read: invalid argument");
  1.4171 +   }
  1.4172 +
  1.4173 +   else if (image != NULL)
  1.4174 +      return png_image_error(image,
  1.4175 +         "png_image_finish_read: damaged PNG_IMAGE_VERSION");
  1.4176 +
  1.4177 +   return 0;
  1.4178 +}
  1.4179 +
  1.4180 +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
  1.4181 +#endif /* PNG_READ_SUPPORTED */

mercurial