Home | History | Annotate | Download | only in libpng
      1 
      2 /* pngread.c - read a PNG file
      3  *
      4  * Last changed in libpng 1.6.10 [March 6, 2014]
      5  * Copyright (c) 1998-2014 Glenn Randers-Pehrson
      6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
      7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
      8  *
      9  * This code is released under the libpng license.
     10  * For conditions of distribution and use, see the disclaimer
     11  * and license in png.h
     12  *
     13  * This file contains routines that an application calls directly to
     14  * read a PNG file or stream.
     15  */
     16 
     17 #include "pngpriv.h"
     18 #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
     19 #  include <errno.h>
     20 #endif
     21 
     22 #ifdef PNG_READ_SUPPORTED
     23 
     24 /* Create a PNG structure for reading, and allocate any memory needed. */
     25 PNG_FUNCTION(png_structp,PNGAPI
     26 png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
     27     png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
     28 {
     29 #ifndef PNG_USER_MEM_SUPPORTED
     30    png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
     31       error_fn, warn_fn, NULL, NULL, NULL);
     32 #else
     33    return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
     34        warn_fn, NULL, NULL, NULL);
     35 }
     36 
     37 /* Alternate create PNG structure for reading, and allocate any memory
     38  * needed.
     39  */
     40 PNG_FUNCTION(png_structp,PNGAPI
     41 png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
     42     png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
     43     png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
     44 {
     45    png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
     46       error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
     47 #endif /* PNG_USER_MEM_SUPPORTED */
     48 
     49    if (png_ptr != NULL)
     50    {
     51       png_ptr->mode = PNG_IS_READ_STRUCT;
     52 
     53       /* Added in libpng-1.6.0; this can be used to detect a read structure if
     54        * required (it will be zero in a write structure.)
     55        */
     56 #     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
     57          png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
     58 #     endif
     59 
     60 #     ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
     61          png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
     62 
     63          /* In stable builds only warn if an application error can be completely
     64           * handled.
     65           */
     66 #        if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
     67             png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
     68 #        endif
     69 #     endif
     70 
     71       /* TODO: delay this, it can be done in png_init_io (if the app doesn't
     72        * do it itself) avoiding setting the default function if it is not
     73        * required.
     74        */
     75       png_set_read_fn(png_ptr, NULL, NULL);
     76 
     77 #ifdef PNG_INDEX_SUPPORTED
     78       png_ptr->index = NULL;
     79 #endif
     80    }
     81 
     82    return png_ptr;
     83 }
     84 
     85 
     86 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
     87 /* Read the information before the actual image data.  This has been
     88  * changed in v0.90 to allow reading a file that already has the magic
     89  * bytes read from the stream.  You can tell libpng how many bytes have
     90  * been read from the beginning of the stream (up to the maximum of 8)
     91  * via png_set_sig_bytes(), and we will only check the remaining bytes
     92  * here.  The application can then have access to the signature bytes we
     93  * read if it is determined that this isn't a valid PNG file.
     94  */
     95 void PNGAPI
     96 png_read_info(png_structrp png_ptr, png_inforp info_ptr)
     97 {
     98 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
     99    int keep;
    100 #endif
    101 
    102    png_debug(1, "in png_read_info");
    103 
    104    if (png_ptr == NULL || info_ptr == NULL)
    105       return;
    106 
    107    /* Read and check the PNG file signature. */
    108    png_read_sig(png_ptr, info_ptr);
    109 
    110    for (;;)
    111    {
    112       png_uint_32 length = png_read_chunk_header(png_ptr);
    113       png_uint_32 chunk_name = png_ptr->chunk_name;
    114 
    115       /* IDAT logic needs to happen here to simplify getting the two flags
    116        * right.
    117        */
    118       if (chunk_name == png_IDAT)
    119       {
    120          if (!(png_ptr->mode & PNG_HAVE_IHDR))
    121             png_chunk_error(png_ptr, "Missing IHDR before IDAT");
    122 
    123          else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
    124              !(png_ptr->mode & PNG_HAVE_PLTE))
    125             png_chunk_error(png_ptr, "Missing PLTE before IDAT");
    126 
    127          else if (png_ptr->mode & PNG_AFTER_IDAT)
    128             png_chunk_benign_error(png_ptr, "Too many IDATs found");
    129 
    130          png_ptr->mode |= PNG_HAVE_IDAT;
    131       }
    132 
    133       else if (png_ptr->mode & PNG_HAVE_IDAT)
    134          png_ptr->mode |= PNG_AFTER_IDAT;
    135 
    136       /* This should be a binary subdivision search or a hash for
    137        * matching the chunk name rather than a linear search.
    138        */
    139       if (chunk_name == png_IHDR)
    140          png_handle_IHDR(png_ptr, info_ptr, length);
    141 
    142       else if (chunk_name == png_IEND)
    143          png_handle_IEND(png_ptr, info_ptr, length);
    144 
    145 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    146       else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
    147       {
    148          png_handle_unknown(png_ptr, info_ptr, length, keep);
    149 
    150          if (chunk_name == png_PLTE)
    151             png_ptr->mode |= PNG_HAVE_PLTE;
    152 
    153          else if (chunk_name == png_IDAT)
    154          {
    155             png_ptr->idat_size = 0; /* It has been consumed */
    156             break;
    157          }
    158       }
    159 #endif
    160       else if (chunk_name == png_PLTE)
    161          png_handle_PLTE(png_ptr, info_ptr, length);
    162 
    163       else if (chunk_name == png_IDAT)
    164       {
    165          png_ptr->idat_size = length;
    166          break;
    167       }
    168 
    169 #ifdef PNG_READ_bKGD_SUPPORTED
    170       else if (chunk_name == png_bKGD)
    171          png_handle_bKGD(png_ptr, info_ptr, length);
    172 #endif
    173 
    174 #ifdef PNG_READ_cHRM_SUPPORTED
    175       else if (chunk_name == png_cHRM)
    176          png_handle_cHRM(png_ptr, info_ptr, length);
    177 #endif
    178 
    179 #ifdef PNG_READ_gAMA_SUPPORTED
    180       else if (chunk_name == png_gAMA)
    181          png_handle_gAMA(png_ptr, info_ptr, length);
    182 #endif
    183 
    184 #ifdef PNG_READ_hIST_SUPPORTED
    185       else if (chunk_name == png_hIST)
    186          png_handle_hIST(png_ptr, info_ptr, length);
    187 #endif
    188 
    189 #ifdef PNG_READ_oFFs_SUPPORTED
    190       else if (chunk_name == png_oFFs)
    191          png_handle_oFFs(png_ptr, info_ptr, length);
    192 #endif
    193 
    194 #ifdef PNG_READ_pCAL_SUPPORTED
    195       else if (chunk_name == png_pCAL)
    196          png_handle_pCAL(png_ptr, info_ptr, length);
    197 #endif
    198 
    199 #ifdef PNG_READ_sCAL_SUPPORTED
    200       else if (chunk_name == png_sCAL)
    201          png_handle_sCAL(png_ptr, info_ptr, length);
    202 #endif
    203 
    204 #ifdef PNG_READ_pHYs_SUPPORTED
    205       else if (chunk_name == png_pHYs)
    206          png_handle_pHYs(png_ptr, info_ptr, length);
    207 #endif
    208 
    209 #ifdef PNG_READ_sBIT_SUPPORTED
    210       else if (chunk_name == png_sBIT)
    211          png_handle_sBIT(png_ptr, info_ptr, length);
    212 #endif
    213 
    214 #ifdef PNG_READ_sRGB_SUPPORTED
    215       else if (chunk_name == png_sRGB)
    216          png_handle_sRGB(png_ptr, info_ptr, length);
    217 #endif
    218 
    219 #ifdef PNG_READ_iCCP_SUPPORTED
    220       else if (chunk_name == png_iCCP)
    221          png_handle_iCCP(png_ptr, info_ptr, length);
    222 #endif
    223 
    224 #ifdef PNG_READ_sPLT_SUPPORTED
    225       else if (chunk_name == png_sPLT)
    226          png_handle_sPLT(png_ptr, info_ptr, length);
    227 #endif
    228 
    229 #ifdef PNG_READ_tEXt_SUPPORTED
    230       else if (chunk_name == png_tEXt)
    231          png_handle_tEXt(png_ptr, info_ptr, length);
    232 #endif
    233 
    234 #ifdef PNG_READ_tIME_SUPPORTED
    235       else if (chunk_name == png_tIME)
    236          png_handle_tIME(png_ptr, info_ptr, length);
    237 #endif
    238 
    239 #ifdef PNG_READ_tRNS_SUPPORTED
    240       else if (chunk_name == png_tRNS)
    241          png_handle_tRNS(png_ptr, info_ptr, length);
    242 #endif
    243 
    244 #ifdef PNG_READ_zTXt_SUPPORTED
    245       else if (chunk_name == png_zTXt)
    246          png_handle_zTXt(png_ptr, info_ptr, length);
    247 #endif
    248 
    249 #ifdef PNG_READ_iTXt_SUPPORTED
    250       else if (chunk_name == png_iTXt)
    251          png_handle_iTXt(png_ptr, info_ptr, length);
    252 #endif
    253 
    254       else
    255          png_handle_unknown(png_ptr, info_ptr, length,
    256             PNG_HANDLE_CHUNK_AS_DEFAULT);
    257    }
    258 }
    259 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
    260 
    261 /* Optional call to update the users info_ptr structure */
    262 void PNGAPI
    263 png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
    264 {
    265    png_debug(1, "in png_read_update_info");
    266 
    267    if (png_ptr != NULL)
    268    {
    269 #ifdef PNG_INDEX_SUPPORTED
    270       if (png_ptr->index) {
    271          png_read_start_row(png_ptr);
    272       }
    273 #endif
    274       if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
    275       {
    276          png_read_start_row(png_ptr);
    277 
    278 #        ifdef PNG_READ_TRANSFORMS_SUPPORTED
    279             png_read_transform_info(png_ptr, info_ptr);
    280 #        else
    281             PNG_UNUSED(info_ptr)
    282 #        endif
    283       }
    284 #ifndef PNG_INDEX_SUPPORTED
    285       /* New in 1.6.0 this avoids the bug of doing the initializations twice */
    286       else
    287          png_app_error(png_ptr,
    288             "png_read_update_info/png_start_read_image: duplicate call");
    289 #endif
    290    }
    291 }
    292 
    293 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    294 /* Initialize palette, background, etc, after transformations
    295  * are set, but before any reading takes place.  This allows
    296  * the user to obtain a gamma-corrected palette, for example.
    297  * If the user doesn't call this, we will do it ourselves.
    298  */
    299 void PNGAPI
    300 png_start_read_image(png_structrp png_ptr)
    301 {
    302    png_debug(1, "in png_start_read_image");
    303 
    304    if (png_ptr != NULL)
    305    {
    306       if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
    307          png_read_start_row(png_ptr);
    308 
    309       /* New in 1.6.0 this avoids the bug of doing the initializations twice */
    310       else
    311          png_app_error(png_ptr,
    312             "png_start_read_image/png_read_update_info: duplicate call");
    313    }
    314 }
    315 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
    316 
    317 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    318 #ifdef PNG_MNG_FEATURES_SUPPORTED
    319 /* Undoes intrapixel differencing,
    320  * NOTE: this is apparently only supported in the 'sequential' reader.
    321  */
    322 static void
    323 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
    324 {
    325    png_debug(1, "in png_do_read_intrapixel");
    326 
    327    if (
    328        (row_info->color_type & PNG_COLOR_MASK_COLOR))
    329    {
    330       int bytes_per_pixel;
    331       png_uint_32 row_width = row_info->width;
    332 
    333       if (row_info->bit_depth == 8)
    334       {
    335          png_bytep rp;
    336          png_uint_32 i;
    337 
    338          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
    339             bytes_per_pixel = 3;
    340 
    341          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    342             bytes_per_pixel = 4;
    343 
    344          else
    345             return;
    346 
    347          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
    348          {
    349             *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
    350             *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
    351          }
    352       }
    353       else if (row_info->bit_depth == 16)
    354       {
    355          png_bytep rp;
    356          png_uint_32 i;
    357 
    358          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
    359             bytes_per_pixel = 6;
    360 
    361          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    362             bytes_per_pixel = 8;
    363 
    364          else
    365             return;
    366 
    367          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
    368          {
    369             png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
    370             png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
    371             png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
    372             png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
    373             png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
    374             *(rp    ) = (png_byte)((red >> 8) & 0xff);
    375             *(rp + 1) = (png_byte)(red & 0xff);
    376             *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
    377             *(rp + 5) = (png_byte)(blue & 0xff);
    378          }
    379       }
    380    }
    381 }
    382 #endif /* PNG_MNG_FEATURES_SUPPORTED */
    383 
    384 void PNGAPI
    385 png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
    386 {
    387    png_row_info row_info;
    388 
    389    if (png_ptr == NULL)
    390       return;
    391 
    392    png_debug2(1, "in png_read_row (row %lu, pass %d)",
    393        (unsigned long)png_ptr->row_number, png_ptr->pass);
    394 
    395    /* png_read_start_row sets the information (in particular iwidth) for this
    396     * interlace pass.
    397     */
    398    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
    399       png_read_start_row(png_ptr);
    400 
    401    /* 1.5.6: row_info moved out of png_struct to a local here. */
    402    row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
    403    row_info.color_type = png_ptr->color_type;
    404    row_info.bit_depth = png_ptr->bit_depth;
    405    row_info.channels = png_ptr->channels;
    406    row_info.pixel_depth = png_ptr->pixel_depth;
    407    row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
    408 
    409    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
    410    {
    411    /* Check for transforms that have been set but were defined out */
    412 #if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
    413    if (png_ptr->transformations & PNG_INVERT_MONO)
    414       png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
    415 #endif
    416 
    417 #if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
    418    if (png_ptr->transformations & PNG_FILLER)
    419       png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
    420 #endif
    421 
    422 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
    423     !defined(PNG_READ_PACKSWAP_SUPPORTED)
    424    if (png_ptr->transformations & PNG_PACKSWAP)
    425       png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
    426 #endif
    427 
    428 #if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
    429    if (png_ptr->transformations & PNG_PACK)
    430       png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
    431 #endif
    432 
    433 #if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
    434    if (png_ptr->transformations & PNG_SHIFT)
    435       png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
    436 #endif
    437 
    438 #if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
    439    if (png_ptr->transformations & PNG_BGR)
    440       png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
    441 #endif
    442 
    443 #if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
    444    if (png_ptr->transformations & PNG_SWAP_BYTES)
    445       png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
    446 #endif
    447    }
    448 
    449 #ifdef PNG_READ_INTERLACING_SUPPORTED
    450    /* If interlaced and we do not need a new row, combine row and return.
    451     * Notice that the pixels we have from previous rows have been transformed
    452     * already; we can only combine like with like (transformed or
    453     * untransformed) and, because of the libpng API for interlaced images, this
    454     * means we must transform before de-interlacing.
    455     */
    456    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
    457    {
    458       switch (png_ptr->pass)
    459       {
    460          case 0:
    461             if (png_ptr->row_number & 0x07)
    462             {
    463                if (dsp_row != NULL)
    464                   png_combine_row(png_ptr, dsp_row, 1/*display*/);
    465                png_read_finish_row(png_ptr);
    466                return;
    467             }
    468             break;
    469 
    470          case 1:
    471             if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
    472             {
    473                if (dsp_row != NULL)
    474                   png_combine_row(png_ptr, dsp_row, 1/*display*/);
    475 
    476                png_read_finish_row(png_ptr);
    477                return;
    478             }
    479             break;
    480 
    481          case 2:
    482             if ((png_ptr->row_number & 0x07) != 4)
    483             {
    484                if (dsp_row != NULL && (png_ptr->row_number & 4))
    485                   png_combine_row(png_ptr, dsp_row, 1/*display*/);
    486 
    487                png_read_finish_row(png_ptr);
    488                return;
    489             }
    490             break;
    491 
    492          case 3:
    493             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
    494             {
    495                if (dsp_row != NULL)
    496                   png_combine_row(png_ptr, dsp_row, 1/*display*/);
    497 
    498                png_read_finish_row(png_ptr);
    499                return;
    500             }
    501             break;
    502 
    503          case 4:
    504             if ((png_ptr->row_number & 3) != 2)
    505             {
    506                if (dsp_row != NULL && (png_ptr->row_number & 2))
    507                   png_combine_row(png_ptr, dsp_row, 1/*display*/);
    508 
    509                png_read_finish_row(png_ptr);
    510                return;
    511             }
    512             break;
    513 
    514          case 5:
    515             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
    516             {
    517                if (dsp_row != NULL)
    518                   png_combine_row(png_ptr, dsp_row, 1/*display*/);
    519 
    520                png_read_finish_row(png_ptr);
    521                return;
    522             }
    523             break;
    524 
    525          default:
    526          case 6:
    527             if (!(png_ptr->row_number & 1))
    528             {
    529                png_read_finish_row(png_ptr);
    530                return;
    531             }
    532             break;
    533       }
    534    }
    535 #endif
    536 
    537    if (!(png_ptr->mode & PNG_HAVE_IDAT))
    538       png_error(png_ptr, "Invalid attempt to read row data");
    539 
    540    /* Fill the row with IDAT data: */
    541    png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
    542 
    543    if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
    544    {
    545       if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
    546          png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
    547             png_ptr->prev_row + 1, png_ptr->row_buf[0]);
    548       else
    549          png_error(png_ptr, "bad adaptive filter value");
    550    }
    551 
    552    /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
    553     * 1.5.6, while the buffer really is this big in current versions of libpng
    554     * it may not be in the future, so this was changed just to copy the
    555     * interlaced count:
    556     */
    557    memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
    558 
    559 #ifdef PNG_MNG_FEATURES_SUPPORTED
    560    if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
    561        (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
    562    {
    563       /* Intrapixel differencing */
    564       png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
    565    }
    566 #endif
    567 
    568 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
    569    if (png_ptr->transformations)
    570       png_do_read_transformations(png_ptr, &row_info);
    571 #endif
    572 
    573    /* The transformed pixel depth should match the depth now in row_info. */
    574    if (png_ptr->transformed_pixel_depth == 0)
    575    {
    576       png_ptr->transformed_pixel_depth = row_info.pixel_depth;
    577       if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
    578          png_error(png_ptr, "sequential row overflow");
    579    }
    580 
    581    else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
    582       png_error(png_ptr, "internal sequential row size calculation error");
    583 
    584 #ifdef PNG_READ_INTERLACING_SUPPORTED
    585    /* Blow up interlaced rows to full size */
    586    if (png_ptr->interlaced &&
    587       (png_ptr->transformations & PNG_INTERLACE))
    588    {
    589       if (png_ptr->pass < 6)
    590          png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
    591             png_ptr->transformations);
    592 
    593       if (dsp_row != NULL)
    594          png_combine_row(png_ptr, dsp_row, 1/*display*/);
    595 
    596       if (row != NULL)
    597          png_combine_row(png_ptr, row, 0/*row*/);
    598    }
    599 
    600    else
    601 #endif
    602    {
    603       if (row != NULL)
    604          png_combine_row(png_ptr, row, -1/*ignored*/);
    605 
    606       if (dsp_row != NULL)
    607          png_combine_row(png_ptr, dsp_row, -1/*ignored*/);
    608    }
    609    png_read_finish_row(png_ptr);
    610 
    611    if (png_ptr->read_row_fn != NULL)
    612       (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
    613 
    614 }
    615 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
    616 
    617 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    618 /* Read one or more rows of image data.  If the image is interlaced,
    619  * and png_set_interlace_handling() has been called, the rows need to
    620  * contain the contents of the rows from the previous pass.  If the
    621  * image has alpha or transparency, and png_handle_alpha()[*] has been
    622  * called, the rows contents must be initialized to the contents of the
    623  * screen.
    624  *
    625  * "row" holds the actual image, and pixels are placed in it
    626  * as they arrive.  If the image is displayed after each pass, it will
    627  * appear to "sparkle" in.  "display_row" can be used to display a
    628  * "chunky" progressive image, with finer detail added as it becomes
    629  * available.  If you do not want this "chunky" display, you may pass
    630  * NULL for display_row.  If you do not want the sparkle display, and
    631  * you have not called png_handle_alpha(), you may pass NULL for rows.
    632  * If you have called png_handle_alpha(), and the image has either an
    633  * alpha channel or a transparency chunk, you must provide a buffer for
    634  * rows.  In this case, you do not have to provide a display_row buffer
    635  * also, but you may.  If the image is not interlaced, or if you have
    636  * not called png_set_interlace_handling(), the display_row buffer will
    637  * be ignored, so pass NULL to it.
    638  *
    639  * [*] png_handle_alpha() does not exist yet, as of this version of libpng
    640  */
    641 
    642 void PNGAPI
    643 png_read_rows(png_structrp png_ptr, png_bytepp row,
    644     png_bytepp display_row, png_uint_32 num_rows)
    645 {
    646    png_uint_32 i;
    647    png_bytepp rp;
    648    png_bytepp dp;
    649 
    650    png_debug(1, "in png_read_rows");
    651 
    652    if (png_ptr == NULL)
    653       return;
    654 
    655    rp = row;
    656    dp = display_row;
    657    if (rp != NULL && dp != NULL)
    658       for (i = 0; i < num_rows; i++)
    659       {
    660          png_bytep rptr = *rp++;
    661          png_bytep dptr = *dp++;
    662 
    663          png_read_row(png_ptr, rptr, dptr);
    664       }
    665 
    666    else if (rp != NULL)
    667       for (i = 0; i < num_rows; i++)
    668       {
    669          png_bytep rptr = *rp;
    670          png_read_row(png_ptr, rptr, NULL);
    671          rp++;
    672       }
    673 
    674    else if (dp != NULL)
    675       for (i = 0; i < num_rows; i++)
    676       {
    677          png_bytep dptr = *dp;
    678          png_read_row(png_ptr, NULL, dptr);
    679          dp++;
    680       }
    681 }
    682 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
    683 
    684 #ifdef PNG_INDEX_SUPPORTED
    685 #define IDAT_HEADER_SIZE 8
    686 
    687 /* Set the png read position to a new position based on idat_position and
    688  * offset.
    689  */
    690 void
    691 png_set_read_offset(png_structp png_ptr,
    692       png_uint_32 idat_position, png_uint_32 bytes_left)
    693 {
    694    png_seek_data(png_ptr, idat_position);
    695    png_ptr->idat_size = png_read_chunk_header(png_ptr);
    696 
    697    // We need to add back IDAT_HEADER_SIZE because in zlib's perspective,
    698    // IDAT_HEADER in PNG is already stripped out.
    699    png_seek_data(png_ptr, idat_position + IDAT_HEADER_SIZE + png_ptr->idat_size - bytes_left);
    700    png_ptr->idat_size = bytes_left;
    701 }
    702 
    703 /* Configure png decoder to decode the pass starting from *row.
    704  * The requested row may be adjusted to align with an indexing row.
    705  * The actual row for the decoder to start its decoding will be returned in
    706  * *row.
    707  */
    708 void PNGAPI
    709 png_configure_decoder(png_structp png_ptr, int *row, int pass)
    710 {
    711    png_indexp index = png_ptr->index;
    712    int n = *row / index->step[pass];
    713    png_line_indexp line_index = index->pass_line_index[pass][n];
    714 
    715    // Adjust row to an indexing row.
    716    *row = n * index->step[pass];
    717    png_ptr->row_number = *row;
    718 
    719 #ifdef PNG_READ_INTERLACING_SUPPORTED
    720    if (png_ptr->interlaced)
    721       png_set_interlaced_pass(png_ptr, pass);
    722 #endif
    723 
    724    long row_byte_length =
    725       PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
    726 
    727    inflateEnd(&png_ptr->zstream);
    728    inflateCopy(&png_ptr->zstream, line_index->z_state);
    729 
    730    // Set the png read position to line_index.
    731    png_set_read_offset(png_ptr, line_index->stream_idat_position,
    732          line_index->bytes_left_in_idat);
    733    memcpy(png_ptr->prev_row, line_index->prev_row, row_byte_length);
    734    png_ptr->zstream.avail_in = 0;
    735 }
    736 
    737 /* Build the line index and store the index in png_ptr->index.
    738  */
    739 void PNGAPI
    740 png_build_index(png_structp png_ptr)
    741 {
    742    // number of rows in a 8x8 block for each interlaced pass.
    743    int number_rows_in_pass[7] = {1, 1, 1, 2, 2, 4, 4};
    744 
    745    int ret;
    746    png_uint_32 i, j;
    747    png_bytep rp;
    748    int p, pass_number = 1;
    749 
    750 #ifdef PNG_READ_INTERLACING_SUPPORTED
    751    pass_number = png_set_interlace_handling(png_ptr);
    752 #endif
    753 
    754    if (png_ptr == NULL)
    755       return;
    756 
    757    png_read_start_row(png_ptr);
    758 
    759 #ifdef PNG_READ_INTERLACING_SUPPORTED
    760    if (!png_ptr->interlaced)
    761 #endif
    762    {
    763       number_rows_in_pass[0] = 8;
    764    }
    765 
    766    rp = png_malloc(png_ptr, png_ptr->rowbytes);
    767 
    768    png_indexp index = png_malloc(png_ptr, sizeof(png_index));
    769    png_ptr->index = index;
    770 
    771    index->stream_idat_position = png_ptr->total_data_read - IDAT_HEADER_SIZE;
    772 
    773    // Set the default size of index in each pass to 0,
    774    // so that we can free index correctly in png_destroy_read_struct.
    775    for (p = 0; p < 7; p++)
    776       index->size[p] = 0;
    777 
    778    for (p = 0; p < pass_number; p++)
    779    {
    780       // We adjust the index step in each pass to make sure each pass
    781       // has roughly the same size of index.
    782       // This way, we won't consume to much memory in recording index.
    783       index->step[p] = INDEX_SAMPLE_SIZE * (8 / number_rows_in_pass[p]);
    784       const int temp_size =
    785          (png_ptr->height + index->step[p] - 1) / index->step[p];
    786       index->pass_line_index[p] =
    787          png_malloc(png_ptr, temp_size * sizeof(png_line_indexp));
    788 
    789       // Get the row_byte_length seen by the filter. This value may be
    790       // different from the row_byte_length of a bitmap in the case of
    791       // color palette mode.
    792       int row_byte_length =
    793          PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
    794 
    795       // Now, we record index for each indexing row.
    796       for (i = 0; i < temp_size; i++)
    797       {
    798          png_line_indexp line_index = png_malloc(png_ptr, sizeof(png_line_index));
    799          index->pass_line_index[p][i] = line_index;
    800 
    801          line_index->z_state = png_malloc(png_ptr, sizeof(z_stream));
    802          inflateCopy(line_index->z_state, &png_ptr->zstream);
    803          line_index->prev_row = png_malloc(png_ptr, row_byte_length);
    804          memcpy(line_index->prev_row, png_ptr->prev_row, row_byte_length);
    805          line_index->stream_idat_position = index->stream_idat_position;
    806          line_index->bytes_left_in_idat = png_ptr->idat_size + png_ptr->zstream.avail_in;
    807 
    808          // increment the size now that we have the backing data structures.
    809          // This prevents a crash in the event that png_read_row fails and
    810          // we need to cleanup the partially constructed png_index_struct;
    811          index->size[p] += 1;
    812 
    813          // Skip the "step" number of rows to the next indexing row.
    814          for (j = 0; j < index->step[p] &&
    815                i * index->step[p] + j < png_ptr->height; j++)
    816          {
    817             png_read_row(png_ptr, rp, NULL);
    818          }
    819       }
    820    }
    821    png_free(png_ptr, rp);
    822 }
    823 #endif
    824 
    825 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    826 /* Read the entire image.  If the image has an alpha channel or a tRNS
    827  * chunk, and you have called png_handle_alpha()[*], you will need to
    828  * initialize the image to the current image that PNG will be overlaying.
    829  * We set the num_rows again here, in case it was incorrectly set in
    830  * png_read_start_row() by a call to png_read_update_info() or
    831  * png_start_read_image() if png_set_interlace_handling() wasn't called
    832  * prior to either of these functions like it should have been.  You can
    833  * only call this function once.  If you desire to have an image for
    834  * each pass of a interlaced image, use png_read_rows() instead.
    835  *
    836  * [*] png_handle_alpha() does not exist yet, as of this version of libpng
    837  */
    838 void PNGAPI
    839 png_read_image(png_structrp png_ptr, png_bytepp image)
    840 {
    841    png_uint_32 i, image_height;
    842    int pass, j;
    843    png_bytepp rp;
    844 
    845    png_debug(1, "in png_read_image");
    846 
    847    if (png_ptr == NULL)
    848       return;
    849 
    850 #ifdef PNG_READ_INTERLACING_SUPPORTED
    851    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
    852    {
    853       pass = png_set_interlace_handling(png_ptr);
    854       /* And make sure transforms are initialized. */
    855       png_start_read_image(png_ptr);
    856    }
    857    else
    858    {
    859       if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
    860       {
    861          /* Caller called png_start_read_image or png_read_update_info without
    862           * first turning on the PNG_INTERLACE transform.  We can fix this here,
    863           * but the caller should do it!
    864           */
    865          png_warning(png_ptr, "Interlace handling should be turned on when "
    866             "using png_read_image");
    867          /* Make sure this is set correctly */
    868          png_ptr->num_rows = png_ptr->height;
    869       }
    870 
    871       /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
    872        * the above error case.
    873        */
    874       pass = png_set_interlace_handling(png_ptr);
    875    }
    876 #else
    877    if (png_ptr->interlaced)
    878       png_error(png_ptr,
    879           "Cannot read interlaced image -- interlace handler disabled");
    880 
    881    pass = 1;
    882 #endif
    883 
    884    image_height=png_ptr->height;
    885 
    886    for (j = 0; j < pass; j++)
    887    {
    888       rp = image;
    889       for (i = 0; i < image_height; i++)
    890       {
    891          png_read_row(png_ptr, *rp, NULL);
    892          rp++;
    893       }
    894    }
    895 }
    896 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
    897 
    898 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
    899 /* Read the end of the PNG file.  Will not read past the end of the
    900  * file, will verify the end is accurate, and will read any comments
    901  * or time information at the end of the file, if info is not NULL.
    902  */
    903 void PNGAPI
    904 png_read_end(png_structrp png_ptr, png_inforp info_ptr)
    905 {
    906 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    907    int keep;
    908 #endif
    909 
    910    png_debug(1, "in png_read_end");
    911 
    912    if (png_ptr == NULL)
    913       return;
    914 
    915    /* If png_read_end is called in the middle of reading the rows there may
    916     * still be pending IDAT data and an owned zstream.  Deal with this here.
    917     */
    918 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    919    if (!png_chunk_unknown_handling(png_ptr, png_IDAT))
    920 #endif
    921       png_read_finish_IDAT(png_ptr);
    922 
    923 #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
    924    /* Report invalid palette index; added at libng-1.5.10 */
    925    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
    926       png_ptr->num_palette_max > png_ptr->num_palette)
    927      png_benign_error(png_ptr, "Read palette index exceeding num_palette");
    928 #endif
    929 
    930    do
    931    {
    932       png_uint_32 length = png_read_chunk_header(png_ptr);
    933       png_uint_32 chunk_name = png_ptr->chunk_name;
    934 
    935       if (chunk_name == png_IEND)
    936          png_handle_IEND(png_ptr, info_ptr, length);
    937 
    938       else if (chunk_name == png_IHDR)
    939          png_handle_IHDR(png_ptr, info_ptr, length);
    940 
    941       else if (info_ptr == NULL)
    942          png_crc_finish(png_ptr, length);
    943 
    944 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    945       else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
    946       {
    947          if (chunk_name == png_IDAT)
    948          {
    949             if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
    950                png_benign_error(png_ptr, "Too many IDATs found");
    951          }
    952          png_handle_unknown(png_ptr, info_ptr, length, keep);
    953          if (chunk_name == png_PLTE)
    954             png_ptr->mode |= PNG_HAVE_PLTE;
    955       }
    956 #endif
    957 
    958       else if (chunk_name == png_IDAT)
    959       {
    960          /* Zero length IDATs are legal after the last IDAT has been
    961           * read, but not after other chunks have been read.
    962           */
    963          if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
    964             png_benign_error(png_ptr, "Too many IDATs found");
    965 
    966          png_crc_finish(png_ptr, length);
    967       }
    968       else if (chunk_name == png_PLTE)
    969          png_handle_PLTE(png_ptr, info_ptr, length);
    970 
    971 #ifdef PNG_READ_bKGD_SUPPORTED
    972       else if (chunk_name == png_bKGD)
    973          png_handle_bKGD(png_ptr, info_ptr, length);
    974 #endif
    975 
    976 #ifdef PNG_READ_cHRM_SUPPORTED
    977       else if (chunk_name == png_cHRM)
    978          png_handle_cHRM(png_ptr, info_ptr, length);
    979 #endif
    980 
    981 #ifdef PNG_READ_gAMA_SUPPORTED
    982       else if (chunk_name == png_gAMA)
    983          png_handle_gAMA(png_ptr, info_ptr, length);
    984 #endif
    985 
    986 #ifdef PNG_READ_hIST_SUPPORTED
    987       else if (chunk_name == png_hIST)
    988          png_handle_hIST(png_ptr, info_ptr, length);
    989 #endif
    990 
    991 #ifdef PNG_READ_oFFs_SUPPORTED
    992       else if (chunk_name == png_oFFs)
    993          png_handle_oFFs(png_ptr, info_ptr, length);
    994 #endif
    995 
    996 #ifdef PNG_READ_pCAL_SUPPORTED
    997       else if (chunk_name == png_pCAL)
    998          png_handle_pCAL(png_ptr, info_ptr, length);
    999 #endif
   1000 
   1001 #ifdef PNG_READ_sCAL_SUPPORTED
   1002       else if (chunk_name == png_sCAL)
   1003          png_handle_sCAL(png_ptr, info_ptr, length);
   1004 #endif
   1005 
   1006 #ifdef PNG_READ_pHYs_SUPPORTED
   1007       else if (chunk_name == png_pHYs)
   1008          png_handle_pHYs(png_ptr, info_ptr, length);
   1009 #endif
   1010 
   1011 #ifdef PNG_READ_sBIT_SUPPORTED
   1012       else if (chunk_name == png_sBIT)
   1013          png_handle_sBIT(png_ptr, info_ptr, length);
   1014 #endif
   1015 
   1016 #ifdef PNG_READ_sRGB_SUPPORTED
   1017       else if (chunk_name == png_sRGB)
   1018          png_handle_sRGB(png_ptr, info_ptr, length);
   1019 #endif
   1020 
   1021 #ifdef PNG_READ_iCCP_SUPPORTED
   1022       else if (chunk_name == png_iCCP)
   1023          png_handle_iCCP(png_ptr, info_ptr, length);
   1024 #endif
   1025 
   1026 #ifdef PNG_READ_sPLT_SUPPORTED
   1027       else if (chunk_name == png_sPLT)
   1028          png_handle_sPLT(png_ptr, info_ptr, length);
   1029 #endif
   1030 
   1031 #ifdef PNG_READ_tEXt_SUPPORTED
   1032       else if (chunk_name == png_tEXt)
   1033          png_handle_tEXt(png_ptr, info_ptr, length);
   1034 #endif
   1035 
   1036 #ifdef PNG_READ_tIME_SUPPORTED
   1037       else if (chunk_name == png_tIME)
   1038          png_handle_tIME(png_ptr, info_ptr, length);
   1039 #endif
   1040 
   1041 #ifdef PNG_READ_tRNS_SUPPORTED
   1042       else if (chunk_name == png_tRNS)
   1043          png_handle_tRNS(png_ptr, info_ptr, length);
   1044 #endif
   1045 
   1046 #ifdef PNG_READ_zTXt_SUPPORTED
   1047       else if (chunk_name == png_zTXt)
   1048          png_handle_zTXt(png_ptr, info_ptr, length);
   1049 #endif
   1050 
   1051 #ifdef PNG_READ_iTXt_SUPPORTED
   1052       else if (chunk_name == png_iTXt)
   1053          png_handle_iTXt(png_ptr, info_ptr, length);
   1054 #endif
   1055 
   1056       else
   1057          png_handle_unknown(png_ptr, info_ptr, length,
   1058             PNG_HANDLE_CHUNK_AS_DEFAULT);
   1059    } while (!(png_ptr->mode & PNG_HAVE_IEND));
   1060 }
   1061 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1062 
   1063 /* Free all memory used in the read struct */
   1064 static void
   1065 png_read_destroy(png_structrp png_ptr)
   1066 {
   1067    png_debug(1, "in png_read_destroy");
   1068 
   1069 #ifdef PNG_READ_GAMMA_SUPPORTED
   1070    png_destroy_gamma_table(png_ptr);
   1071 #endif
   1072 
   1073    png_free(png_ptr, png_ptr->big_row_buf);
   1074    png_free(png_ptr, png_ptr->big_prev_row);
   1075    png_free(png_ptr, png_ptr->read_buffer);
   1076 
   1077 #ifdef PNG_READ_QUANTIZE_SUPPORTED
   1078    png_free(png_ptr, png_ptr->palette_lookup);
   1079    png_free(png_ptr, png_ptr->quantize_index);
   1080 #endif
   1081 
   1082    if (png_ptr->free_me & PNG_FREE_PLTE)
   1083       png_zfree(png_ptr, png_ptr->palette);
   1084    png_ptr->free_me &= ~PNG_FREE_PLTE;
   1085 
   1086 #if defined(PNG_tRNS_SUPPORTED) || \
   1087     defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
   1088    if (png_ptr->free_me & PNG_FREE_TRNS)
   1089       png_free(png_ptr, png_ptr->trans_alpha);
   1090    png_ptr->free_me &= ~PNG_FREE_TRNS;
   1091 #endif
   1092 
   1093    inflateEnd(&png_ptr->zstream);
   1094 
   1095 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
   1096    png_free(png_ptr, png_ptr->save_buffer);
   1097 #endif
   1098 
   1099 #if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\
   1100    defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
   1101    png_free(png_ptr, png_ptr->unknown_chunk.data);
   1102 #endif
   1103 
   1104 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
   1105    png_free(png_ptr, png_ptr->chunk_list);
   1106 #endif
   1107 
   1108 #ifdef PNG_INDEX_SUPPORTED
   1109    if (png_ptr->index) {
   1110       unsigned int i, p;
   1111       png_indexp index = png_ptr->index;
   1112       for (p = 0; p < 7; p++) {
   1113          for (i = 0; i < index->size[p]; i++) {
   1114             inflateEnd(index->pass_line_index[p][i]->z_state);
   1115             png_free(png_ptr, index->pass_line_index[p][i]->z_state);
   1116             png_free(png_ptr, index->pass_line_index[p][i]->prev_row);
   1117             png_free(png_ptr, index->pass_line_index[p][i]);
   1118          }
   1119          if (index->size[p] != 0) {
   1120             png_free(png_ptr, index->pass_line_index[p]);
   1121          }
   1122       }
   1123       png_free(png_ptr, index);
   1124    }
   1125 #endif
   1126 
   1127    /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
   1128     * callbacks are still set at this point.  They are required to complete the
   1129     * destruction of the png_struct itself.
   1130     */
   1131 }
   1132 
   1133 /* Free all memory used by the read */
   1134 void PNGAPI
   1135 png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
   1136     png_infopp end_info_ptr_ptr)
   1137 {
   1138    png_structrp png_ptr = NULL;
   1139 
   1140    png_debug(1, "in png_destroy_read_struct");
   1141 
   1142    if (png_ptr_ptr != NULL)
   1143       png_ptr = *png_ptr_ptr;
   1144 
   1145    if (png_ptr == NULL)
   1146       return;
   1147 
   1148    /* libpng 1.6.0: use the API to destroy info structs to ensure consistent
   1149     * behavior.  Prior to 1.6.0 libpng did extra 'info' destruction in this API.
   1150     * The extra was, apparently, unnecessary yet this hides memory leak bugs.
   1151     */
   1152    png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
   1153    png_destroy_info_struct(png_ptr, info_ptr_ptr);
   1154 
   1155    *png_ptr_ptr = NULL;
   1156    png_read_destroy(png_ptr);
   1157    png_destroy_png_struct(png_ptr);
   1158 }
   1159 
   1160 void PNGAPI
   1161 png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
   1162 {
   1163    if (png_ptr == NULL)
   1164       return;
   1165 
   1166    png_ptr->read_row_fn = read_row_fn;
   1167 }
   1168 
   1169 
   1170 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
   1171 #ifdef PNG_INFO_IMAGE_SUPPORTED
   1172 void PNGAPI
   1173 png_read_png(png_structrp png_ptr, png_inforp info_ptr,
   1174                            int transforms,
   1175                            voidp params)
   1176 {
   1177    if (png_ptr == NULL || info_ptr == NULL)
   1178       return;
   1179 
   1180    /* png_read_info() gives us all of the information from the
   1181     * PNG file before the first IDAT (image data chunk).
   1182     */
   1183    png_read_info(png_ptr, info_ptr);
   1184    if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
   1185       png_error(png_ptr, "Image is too high to process with png_read_png()");
   1186 
   1187    /* -------------- image transformations start here ------------------- */
   1188    /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
   1189     * is not implemented.  This will only happen in de-configured (non-default)
   1190     * libpng builds.  The results can be unexpected - png_read_png may return
   1191     * short or mal-formed rows because the transform is skipped.
   1192     */
   1193 
   1194    /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
   1195     */
   1196    if (transforms & PNG_TRANSFORM_SCALE_16)
   1197      /* Added at libpng-1.5.4. "strip_16" produces the same result that it
   1198       * did in earlier versions, while "scale_16" is now more accurate.
   1199       */
   1200 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
   1201       png_set_scale_16(png_ptr);
   1202 #else
   1203       png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
   1204 #endif
   1205 
   1206    /* If both SCALE and STRIP are required pngrtran will effectively cancel the
   1207     * latter by doing SCALE first.  This is ok and allows apps not to check for
   1208     * which is supported to get the right answer.
   1209     */
   1210    if (transforms & PNG_TRANSFORM_STRIP_16)
   1211 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
   1212       png_set_strip_16(png_ptr);
   1213 #else
   1214       png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
   1215 #endif
   1216 
   1217    /* Strip alpha bytes from the input data without combining with
   1218     * the background (not recommended).
   1219     */
   1220    if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
   1221 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
   1222       png_set_strip_alpha(png_ptr);
   1223 #else
   1224       png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
   1225 #endif
   1226 
   1227    /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
   1228     * byte into separate bytes (useful for paletted and grayscale images).
   1229     */
   1230    if (transforms & PNG_TRANSFORM_PACKING)
   1231 #ifdef PNG_READ_PACK_SUPPORTED
   1232       png_set_packing(png_ptr);
   1233 #else
   1234       png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
   1235 #endif
   1236 
   1237    /* Change the order of packed pixels to least significant bit first
   1238     * (not useful if you are using png_set_packing).
   1239     */
   1240    if (transforms & PNG_TRANSFORM_PACKSWAP)
   1241 #ifdef PNG_READ_PACKSWAP_SUPPORTED
   1242       png_set_packswap(png_ptr);
   1243 #else
   1244       png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
   1245 #endif
   1246 
   1247    /* Expand paletted colors into true RGB triplets
   1248     * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
   1249     * Expand paletted or RGB images with transparency to full alpha
   1250     * channels so the data will be available as RGBA quartets.
   1251     */
   1252    if (transforms & PNG_TRANSFORM_EXPAND)
   1253 #ifdef PNG_READ_EXPAND_SUPPORTED
   1254       png_set_expand(png_ptr);
   1255 #else
   1256       png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
   1257 #endif
   1258 
   1259    /* We don't handle background color or gamma transformation or quantizing.
   1260     */
   1261 
   1262    /* Invert monochrome files to have 0 as white and 1 as black
   1263     */
   1264    if (transforms & PNG_TRANSFORM_INVERT_MONO)
   1265 #ifdef PNG_READ_INVERT_SUPPORTED
   1266       png_set_invert_mono(png_ptr);
   1267 #else
   1268       png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
   1269 #endif
   1270 
   1271    /* If you want to shift the pixel values from the range [0,255] or
   1272     * [0,65535] to the original [0,7] or [0,31], or whatever range the
   1273     * colors were originally in:
   1274     */
   1275    if (transforms & PNG_TRANSFORM_SHIFT)
   1276 #ifdef PNG_READ_SHIFT_SUPPORTED
   1277       if (info_ptr->valid & PNG_INFO_sBIT)
   1278          png_set_shift(png_ptr, &info_ptr->sig_bit);
   1279 #else
   1280       png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
   1281 #endif
   1282 
   1283    /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
   1284    if (transforms & PNG_TRANSFORM_BGR)
   1285 #ifdef PNG_READ_BGR_SUPPORTED
   1286       png_set_bgr(png_ptr);
   1287 #else
   1288       png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
   1289 #endif
   1290 
   1291    /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
   1292    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
   1293 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
   1294       png_set_swap_alpha(png_ptr);
   1295 #else
   1296       png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
   1297 #endif
   1298 
   1299    /* Swap bytes of 16-bit files to least significant byte first */
   1300    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
   1301 #ifdef PNG_READ_SWAP_SUPPORTED
   1302       png_set_swap(png_ptr);
   1303 #else
   1304       png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
   1305 #endif
   1306 
   1307 /* Added at libpng-1.2.41 */
   1308    /* Invert the alpha channel from opacity to transparency */
   1309    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
   1310 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
   1311       png_set_invert_alpha(png_ptr);
   1312 #else
   1313       png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
   1314 #endif
   1315 
   1316 /* Added at libpng-1.2.41 */
   1317    /* Expand grayscale image to RGB */
   1318    if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
   1319 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
   1320       png_set_gray_to_rgb(png_ptr);
   1321 #else
   1322       png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
   1323 #endif
   1324 
   1325 /* Added at libpng-1.5.4 */
   1326    if (transforms & PNG_TRANSFORM_EXPAND_16)
   1327 #ifdef PNG_READ_EXPAND_16_SUPPORTED
   1328       png_set_expand_16(png_ptr);
   1329 #else
   1330       png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
   1331 #endif
   1332 
   1333    /* We don't handle adding filler bytes */
   1334 
   1335    /* We use png_read_image and rely on that for interlace handling, but we also
   1336     * call png_read_update_info therefore must turn on interlace handling now:
   1337     */
   1338    (void)png_set_interlace_handling(png_ptr);
   1339 
   1340    /* Optional call to gamma correct and add the background to the palette
   1341     * and update info structure.  REQUIRED if you are expecting libpng to
   1342     * update the palette for you (i.e., you selected such a transform above).
   1343     */
   1344    png_read_update_info(png_ptr, info_ptr);
   1345 
   1346    /* -------------- image transformations end here ------------------- */
   1347 
   1348    png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
   1349    if (info_ptr->row_pointers == NULL)
   1350    {
   1351       png_uint_32 iptr;
   1352 
   1353       info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
   1354           info_ptr->height * (sizeof (png_bytep))));
   1355 
   1356       for (iptr=0; iptr<info_ptr->height; iptr++)
   1357          info_ptr->row_pointers[iptr] = NULL;
   1358 
   1359       info_ptr->free_me |= PNG_FREE_ROWS;
   1360 
   1361       for (iptr = 0; iptr < info_ptr->height; iptr++)
   1362          info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
   1363             png_malloc(png_ptr, info_ptr->rowbytes));
   1364    }
   1365 
   1366    png_read_image(png_ptr, info_ptr->row_pointers);
   1367    info_ptr->valid |= PNG_INFO_IDAT;
   1368 
   1369    /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
   1370    png_read_end(png_ptr, info_ptr);
   1371 
   1372    PNG_UNUSED(params)
   1373 }
   1374 #endif /* PNG_INFO_IMAGE_SUPPORTED */
   1375 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
   1376 
   1377 #ifdef PNG_SIMPLIFIED_READ_SUPPORTED
   1378 /* SIMPLIFIED READ
   1379  *
   1380  * This code currently relies on the sequential reader, though it could easily
   1381  * be made to work with the progressive one.
   1382  */
   1383 /* Arguments to png_image_finish_read: */
   1384 
   1385 /* Encoding of PNG data (used by the color-map code) */
   1386 #  define P_NOTSET  0 /* File encoding not yet known */
   1387 #  define P_sRGB    1 /* 8-bit encoded to sRGB gamma */
   1388 #  define P_LINEAR  2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
   1389 #  define P_FILE    3 /* 8-bit encoded to file gamma, not sRGB or linear */
   1390 #  define P_LINEAR8 4 /* 8-bit linear: only from a file value */
   1391 
   1392 /* Color-map processing: after libpng has run on the PNG image further
   1393  * processing may be needed to conver the data to color-map indicies.
   1394  */
   1395 #define PNG_CMAP_NONE      0
   1396 #define PNG_CMAP_GA        1 /* Process GA data to a color-map with alpha */
   1397 #define PNG_CMAP_TRANS     2 /* Process GA data to a background index */
   1398 #define PNG_CMAP_RGB       3 /* Process RGB data */
   1399 #define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */
   1400 
   1401 /* The following document where the background is for each processing case. */
   1402 #define PNG_CMAP_NONE_BACKGROUND      256
   1403 #define PNG_CMAP_GA_BACKGROUND        231
   1404 #define PNG_CMAP_TRANS_BACKGROUND     254
   1405 #define PNG_CMAP_RGB_BACKGROUND       256
   1406 #define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
   1407 
   1408 typedef struct
   1409 {
   1410    /* Arguments: */
   1411    png_imagep image;
   1412    png_voidp  buffer;
   1413    png_int_32 row_stride;
   1414    png_voidp  colormap;
   1415    png_const_colorp background;
   1416    /* Local variables: */
   1417    png_voidp       local_row;
   1418    png_voidp       first_row;
   1419    ptrdiff_t       row_bytes;           /* step between rows */
   1420    int             file_encoding;       /* E_ values above */
   1421    png_fixed_point gamma_to_linear;     /* For P_FILE, reciprocal of gamma */
   1422    int             colormap_processing; /* PNG_CMAP_ values above */
   1423 } png_image_read_control;
   1424 
   1425 /* Do all the *safe* initialization - 'safe' means that png_error won't be
   1426  * called, so setting up the jmp_buf is not required.  This means that anything
   1427  * called from here must *not* call png_malloc - it has to call png_malloc_warn
   1428  * instead so that control is returned safely back to this routine.
   1429  */
   1430 static int
   1431 png_image_read_init(png_imagep image)
   1432 {
   1433    if (image->opaque == NULL)
   1434    {
   1435       png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
   1436           png_safe_error, png_safe_warning);
   1437 
   1438       /* And set the rest of the structure to NULL to ensure that the various
   1439        * fields are consistent.
   1440        */
   1441       memset(image, 0, (sizeof *image));
   1442       image->version = PNG_IMAGE_VERSION;
   1443 
   1444       if (png_ptr != NULL)
   1445       {
   1446          png_infop info_ptr = png_create_info_struct(png_ptr);
   1447 
   1448          if (info_ptr != NULL)
   1449          {
   1450             png_controlp control = png_voidcast(png_controlp,
   1451                png_malloc_warn(png_ptr, (sizeof *control)));
   1452 
   1453             if (control != NULL)
   1454             {
   1455                memset(control, 0, (sizeof *control));
   1456 
   1457                control->png_ptr = png_ptr;
   1458                control->info_ptr = info_ptr;
   1459                control->for_write = 0;
   1460 
   1461                image->opaque = control;
   1462                return 1;
   1463             }
   1464 
   1465             /* Error clean up */
   1466             png_destroy_info_struct(png_ptr, &info_ptr);
   1467          }
   1468 
   1469          png_destroy_read_struct(&png_ptr, NULL, NULL);
   1470       }
   1471 
   1472       return png_image_error(image, "png_image_read: out of memory");
   1473    }
   1474 
   1475    return png_image_error(image, "png_image_read: opaque pointer not NULL");
   1476 }
   1477 
   1478 /* Utility to find the base format of a PNG file from a png_struct. */
   1479 static png_uint_32
   1480 png_image_format(png_structrp png_ptr)
   1481 {
   1482    png_uint_32 format = 0;
   1483 
   1484    if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
   1485       format |= PNG_FORMAT_FLAG_COLOR;
   1486 
   1487    if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)
   1488       format |= PNG_FORMAT_FLAG_ALPHA;
   1489 
   1490    /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS
   1491     * sets the png_struct fields; that's all we are interested in here.  The
   1492     * precise interaction with an app call to png_set_tRNS and PNG file reading
   1493     * is unclear.
   1494     */
   1495    else if (png_ptr->num_trans > 0)
   1496       format |= PNG_FORMAT_FLAG_ALPHA;
   1497 
   1498    if (png_ptr->bit_depth == 16)
   1499       format |= PNG_FORMAT_FLAG_LINEAR;
   1500 
   1501    if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE)
   1502       format |= PNG_FORMAT_FLAG_COLORMAP;
   1503 
   1504    return format;
   1505 }
   1506 
   1507 /* Is the given gamma significantly different from sRGB?  The test is the same
   1508  * one used in pngrtran.c when deciding whether to do gamma correction.  The
   1509  * arithmetic optimizes the division by using the fact that the inverse of the
   1510  * file sRGB gamma is 2.2
   1511  */
   1512 static int
   1513 png_gamma_not_sRGB(png_fixed_point g)
   1514 {
   1515    if (g < PNG_FP_1)
   1516    {
   1517       /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
   1518       if (g == 0)
   1519          return 0;
   1520 
   1521       return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
   1522    }
   1523 
   1524    return 1;
   1525 }
   1526 
   1527 /* Do the main body of a 'png_image_begin_read' function; read the PNG file
   1528  * header and fill in all the information.  This is executed in a safe context,
   1529  * unlike the init routine above.
   1530  */
   1531 static int
   1532 png_image_read_header(png_voidp argument)
   1533 {
   1534    png_imagep image = png_voidcast(png_imagep, argument);
   1535    png_structrp png_ptr = image->opaque->png_ptr;
   1536    png_inforp info_ptr = image->opaque->info_ptr;
   1537 
   1538    png_set_benign_errors(png_ptr, 1/*warn*/);
   1539    png_read_info(png_ptr, info_ptr);
   1540 
   1541    /* Do this the fast way; just read directly out of png_struct. */
   1542    image->width = png_ptr->width;
   1543    image->height = png_ptr->height;
   1544 
   1545    {
   1546       png_uint_32 format = png_image_format(png_ptr);
   1547 
   1548       image->format = format;
   1549 
   1550 #ifdef PNG_COLORSPACE_SUPPORTED
   1551       /* Does the colorspace match sRGB?  If there is no color endpoint
   1552        * (colorant) information assume yes, otherwise require the
   1553        * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set.  If the
   1554        * colorspace has been determined to be invalid ignore it.
   1555        */
   1556       if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
   1557          & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
   1558             PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
   1559          image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
   1560 #endif
   1561    }
   1562 
   1563    /* We need the maximum number of entries regardless of the format the
   1564     * application sets here.
   1565     */
   1566    {
   1567       png_uint_32 cmap_entries;
   1568 
   1569       switch (png_ptr->color_type)
   1570       {
   1571          case PNG_COLOR_TYPE_GRAY:
   1572             cmap_entries = 1U << png_ptr->bit_depth;
   1573             break;
   1574 
   1575          case PNG_COLOR_TYPE_PALETTE:
   1576             cmap_entries = png_ptr->num_palette;
   1577             break;
   1578 
   1579          default:
   1580             cmap_entries = 256;
   1581             break;
   1582       }
   1583 
   1584       if (cmap_entries > 256)
   1585          cmap_entries = 256;
   1586 
   1587       image->colormap_entries = cmap_entries;
   1588    }
   1589 
   1590    return 1;
   1591 }
   1592 
   1593 #ifdef PNG_STDIO_SUPPORTED
   1594 int PNGAPI
   1595 png_image_begin_read_from_stdio(png_imagep image, FILE* file)
   1596 {
   1597    if (image != NULL && image->version == PNG_IMAGE_VERSION)
   1598    {
   1599       if (file != NULL)
   1600       {
   1601          if (png_image_read_init(image))
   1602          {
   1603             /* This is slightly evil, but png_init_io doesn't do anything other
   1604              * than this and we haven't changed the standard IO functions so
   1605              * this saves a 'safe' function.
   1606              */
   1607             image->opaque->png_ptr->io_ptr = file;
   1608             return png_safe_execute(image, png_image_read_header, image);
   1609          }
   1610       }
   1611 
   1612       else
   1613          return png_image_error(image,
   1614             "png_image_begin_read_from_stdio: invalid argument");
   1615    }
   1616 
   1617    else if (image != NULL)
   1618       return png_image_error(image,
   1619          "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
   1620 
   1621    return 0;
   1622 }
   1623 
   1624 int PNGAPI
   1625 png_image_begin_read_from_file(png_imagep image, const char *file_name)
   1626 {
   1627    if (image != NULL && image->version == PNG_IMAGE_VERSION)
   1628    {
   1629       if (file_name != NULL)
   1630       {
   1631          FILE *fp = fopen(file_name, "rb");
   1632 
   1633          if (fp != NULL)
   1634          {
   1635             if (png_image_read_init(image))
   1636             {
   1637                image->opaque->png_ptr->io_ptr = fp;
   1638                image->opaque->owned_file = 1;
   1639                return png_safe_execute(image, png_image_read_header, image);
   1640             }
   1641 
   1642             /* Clean up: just the opened file. */
   1643             (void)fclose(fp);
   1644          }
   1645 
   1646          else
   1647             return png_image_error(image, strerror(errno));
   1648       }
   1649 
   1650       else
   1651          return png_image_error(image,
   1652             "png_image_begin_read_from_file: invalid argument");
   1653    }
   1654 
   1655    else if (image != NULL)
   1656       return png_image_error(image,
   1657          "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
   1658 
   1659    return 0;
   1660 }
   1661 #endif /* PNG_STDIO_SUPPORTED */
   1662 
   1663 static void PNGCBAPI
   1664 png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
   1665 {
   1666    if (png_ptr != NULL)
   1667    {
   1668       png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
   1669       if (image != NULL)
   1670       {
   1671          png_controlp cp = image->opaque;
   1672          if (cp != NULL)
   1673          {
   1674             png_const_bytep memory = cp->memory;
   1675             png_size_t size = cp->size;
   1676 
   1677             if (memory != NULL && size >= need)
   1678             {
   1679                memcpy(out, memory, need);
   1680                cp->memory = memory + need;
   1681                cp->size = size - need;
   1682                return;
   1683             }
   1684 
   1685             png_error(png_ptr, "read beyond end of data");
   1686          }
   1687       }
   1688 
   1689       png_error(png_ptr, "invalid memory read");
   1690    }
   1691 }
   1692 
   1693 int PNGAPI png_image_begin_read_from_memory(png_imagep image,
   1694    png_const_voidp memory, png_size_t size)
   1695 {
   1696    if (image != NULL && image->version == PNG_IMAGE_VERSION)
   1697    {
   1698       if (memory != NULL && size > 0)
   1699       {
   1700          if (png_image_read_init(image))
   1701          {
   1702             /* Now set the IO functions to read from the memory buffer and
   1703              * store it into io_ptr.  Again do this in-place to avoid calling a
   1704              * libpng function that requires error handling.
   1705              */
   1706             image->opaque->memory = png_voidcast(png_const_bytep, memory);
   1707             image->opaque->size = size;
   1708             image->opaque->png_ptr->io_ptr = image;
   1709             image->opaque->png_ptr->read_data_fn = png_image_memory_read;
   1710 
   1711             return png_safe_execute(image, png_image_read_header, image);
   1712          }
   1713       }
   1714 
   1715       else
   1716          return png_image_error(image,
   1717             "png_image_begin_read_from_memory: invalid argument");
   1718    }
   1719 
   1720    else if (image != NULL)
   1721       return png_image_error(image,
   1722          "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
   1723 
   1724    return 0;
   1725 }
   1726 
   1727 /* Utility function to skip chunks that are not used by the simplified image
   1728  * read functions and an appropriate macro to call it.
   1729  */
   1730 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
   1731 static void
   1732 png_image_skip_unused_chunks(png_structrp png_ptr)
   1733 {
   1734    /* Prepare the reader to ignore all recognized chunks whose data will not
   1735     * be used, i.e., all chunks recognized by libpng except for those
   1736     * involved in basic image reading:
   1737     *
   1738     *    IHDR, PLTE, IDAT, IEND
   1739     *
   1740     * Or image data handling:
   1741     *
   1742     *    tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
   1743     *
   1744     * This provides a small performance improvement and eliminates any
   1745     * potential vulnerability to security problems in the unused chunks.
   1746     *
   1747     * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
   1748     * too.  This allows the simplified API to be compiled without iCCP support,
   1749     * however if the support is there the chunk is still checked to detect
   1750     * errors (which are unfortunately quite common.)
   1751     */
   1752    {
   1753          static PNG_CONST png_byte chunks_to_process[] = {
   1754             98,  75,  71,  68, '\0',  /* bKGD */
   1755             99,  72,  82,  77, '\0',  /* cHRM */
   1756            103,  65,  77,  65, '\0',  /* gAMA */
   1757 #        ifdef PNG_READ_iCCP_SUPPORTED
   1758            105,  67,  67,  80, '\0',  /* iCCP */
   1759 #        endif
   1760            115,  66,  73,  84, '\0',  /* sBIT */
   1761            115,  82,  71,  66, '\0',  /* sRGB */
   1762            };
   1763 
   1764        /* Ignore unknown chunks and all other chunks except for the
   1765         * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
   1766         */
   1767        png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
   1768          NULL, -1);
   1769 
   1770        /* But do not ignore image data handling chunks */
   1771        png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
   1772          chunks_to_process, (sizeof chunks_to_process)/5);
   1773     }
   1774 }
   1775 
   1776 #  define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
   1777 #else
   1778 #  define PNG_SKIP_CHUNKS(p) ((void)0)
   1779 #endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */
   1780 
   1781 /* The following macro gives the exact rounded answer for all values in the
   1782  * range 0..255 (it actually divides by 51.2, but the rounding still generates
   1783  * the correct numbers 0..5
   1784  */
   1785 #define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
   1786 
   1787 /* Utility functions to make particular color-maps */
   1788 static void
   1789 set_file_encoding(png_image_read_control *display)
   1790 {
   1791    png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
   1792    if (png_gamma_significant(g))
   1793    {
   1794       if (png_gamma_not_sRGB(g))
   1795       {
   1796          display->file_encoding = P_FILE;
   1797          display->gamma_to_linear = png_reciprocal(g);
   1798       }
   1799 
   1800       else
   1801          display->file_encoding = P_sRGB;
   1802    }
   1803 
   1804    else
   1805       display->file_encoding = P_LINEAR8;
   1806 }
   1807 
   1808 static unsigned int
   1809 decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
   1810 {
   1811    if (encoding == P_FILE) /* double check */
   1812       encoding = display->file_encoding;
   1813 
   1814    if (encoding == P_NOTSET) /* must be the file encoding */
   1815    {
   1816       set_file_encoding(display);
   1817       encoding = display->file_encoding;
   1818    }
   1819 
   1820    switch (encoding)
   1821    {
   1822       case P_FILE:
   1823          value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
   1824          break;
   1825 
   1826       case P_sRGB:
   1827          value = png_sRGB_table[value];
   1828          break;
   1829 
   1830       case P_LINEAR:
   1831          break;
   1832 
   1833       case P_LINEAR8:
   1834          value *= 257;
   1835          break;
   1836 
   1837       default:
   1838          png_error(display->image->opaque->png_ptr,
   1839             "unexpected encoding (internal error)");
   1840          break;
   1841    }
   1842 
   1843    return value;
   1844 }
   1845 
   1846 static png_uint_32
   1847 png_colormap_compose(png_image_read_control *display,
   1848    png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
   1849    png_uint_32 background, int encoding)
   1850 {
   1851    /* The file value is composed on the background, the background has the given
   1852     * encoding and so does the result, the file is encoded with P_FILE and the
   1853     * file and alpha are 8-bit values.  The (output) encoding will always be
   1854     * P_LINEAR or P_sRGB.
   1855     */
   1856    png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
   1857    png_uint_32 b = decode_gamma(display, background, encoding);
   1858 
   1859    /* The alpha is always an 8-bit value (it comes from the palette), the value
   1860     * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.
   1861     */
   1862    f = f * alpha + b * (255-alpha);
   1863 
   1864    if (encoding == P_LINEAR)
   1865    {
   1866       /* Scale to 65535; divide by 255, approximately (in fact this is extremely
   1867        * accurate, it divides by 255.00000005937181414556, with no overflow.)
   1868        */
   1869       f *= 257; /* Now scaled by 65535 */
   1870       f += f >> 16;
   1871       f = (f+32768) >> 16;
   1872    }
   1873 
   1874    else /* P_sRGB */
   1875       f = PNG_sRGB_FROM_LINEAR(f);
   1876 
   1877    return f;
   1878 }
   1879 
   1880 /* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
   1881  * be 8-bit.
   1882  */
   1883 static void
   1884 png_create_colormap_entry(png_image_read_control *display,
   1885    png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
   1886    png_uint_32 alpha, int encoding)
   1887 {
   1888    png_imagep image = display->image;
   1889    const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ?
   1890       P_LINEAR : P_sRGB;
   1891    const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
   1892       (red != green || green != blue);
   1893 
   1894    if (ip > 255)
   1895       png_error(image->opaque->png_ptr, "color-map index out of range");
   1896 
   1897    /* Update the cache with whether the file gamma is significantly different
   1898     * from sRGB.
   1899     */
   1900    if (encoding == P_FILE)
   1901    {
   1902       if (display->file_encoding == P_NOTSET)
   1903          set_file_encoding(display);
   1904 
   1905       /* Note that the cached value may be P_FILE too, but if it is then the
   1906        * gamma_to_linear member has been set.
   1907        */
   1908       encoding = display->file_encoding;
   1909    }
   1910 
   1911    if (encoding == P_FILE)
   1912    {
   1913       png_fixed_point g = display->gamma_to_linear;
   1914 
   1915       red = png_gamma_16bit_correct(red*257, g);
   1916       green = png_gamma_16bit_correct(green*257, g);
   1917       blue = png_gamma_16bit_correct(blue*257, g);
   1918 
   1919       if (convert_to_Y || output_encoding == P_LINEAR)
   1920       {
   1921          alpha *= 257;
   1922          encoding = P_LINEAR;
   1923       }
   1924 
   1925       else
   1926       {
   1927          red = PNG_sRGB_FROM_LINEAR(red * 255);
   1928          green = PNG_sRGB_FROM_LINEAR(green * 255);
   1929          blue = PNG_sRGB_FROM_LINEAR(blue * 255);
   1930          encoding = P_sRGB;
   1931       }
   1932    }
   1933 
   1934    else if (encoding == P_LINEAR8)
   1935    {
   1936       /* This encoding occurs quite frequently in test cases because PngSuite
   1937        * includes a gAMA 1.0 chunk with most images.
   1938        */
   1939       red *= 257;
   1940       green *= 257;
   1941       blue *= 257;
   1942       alpha *= 257;
   1943       encoding = P_LINEAR;
   1944    }
   1945 
   1946    else if (encoding == P_sRGB && (convert_to_Y || output_encoding == P_LINEAR))
   1947    {
   1948       /* The values are 8-bit sRGB values, but must be converted to 16-bit
   1949        * linear.
   1950        */
   1951       red = png_sRGB_table[red];
   1952       green = png_sRGB_table[green];
   1953       blue = png_sRGB_table[blue];
   1954       alpha *= 257;
   1955       encoding = P_LINEAR;
   1956    }
   1957 
   1958    /* This is set if the color isn't gray but the output is. */
   1959    if (encoding == P_LINEAR)
   1960    {
   1961       if (convert_to_Y)
   1962       {
   1963          /* NOTE: these values are copied from png_do_rgb_to_gray */
   1964          png_uint_32 y = (png_uint_32)6968 * red  + (png_uint_32)23434 * green +
   1965             (png_uint_32)2366 * blue;
   1966 
   1967          if (output_encoding == P_LINEAR)
   1968             y = (y + 16384) >> 15;
   1969 
   1970          else
   1971          {
   1972             /* y is scaled by 32768, we need it scaled by 255: */
   1973             y = (y + 128) >> 8;
   1974             y *= 255;
   1975             y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
   1976             encoding = P_sRGB;
   1977          }
   1978 
   1979          blue = red = green = y;
   1980       }
   1981 
   1982       else if (output_encoding == P_sRGB)
   1983       {
   1984          red = PNG_sRGB_FROM_LINEAR(red * 255);
   1985          green = PNG_sRGB_FROM_LINEAR(green * 255);
   1986          blue = PNG_sRGB_FROM_LINEAR(blue * 255);
   1987          alpha = PNG_DIV257(alpha);
   1988          encoding = P_sRGB;
   1989       }
   1990    }
   1991 
   1992    if (encoding != output_encoding)
   1993       png_error(image->opaque->png_ptr, "bad encoding (internal error)");
   1994 
   1995    /* Store the value. */
   1996    {
   1997 #     ifdef PNG_FORMAT_AFIRST_SUPPORTED
   1998          const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
   1999             (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
   2000 #     else
   2001 #        define afirst 0
   2002 #     endif
   2003 #     ifdef PNG_FORMAT_BGR_SUPPORTED
   2004          const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0;
   2005 #     else
   2006 #        define bgr 0
   2007 #     endif
   2008 
   2009       if (output_encoding == P_LINEAR)
   2010       {
   2011          png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
   2012 
   2013          entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
   2014 
   2015          /* The linear 16-bit values must be pre-multiplied by the alpha channel
   2016           * value, if less than 65535 (this is, effectively, composite on black
   2017           * if the alpha channel is removed.)
   2018           */
   2019          switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
   2020          {
   2021             case 4:
   2022                entry[afirst ? 0 : 3] = (png_uint_16)alpha;
   2023                /* FALL THROUGH */
   2024 
   2025             case 3:
   2026                if (alpha < 65535)
   2027                {
   2028                   if (alpha > 0)
   2029                   {
   2030                      blue = (blue * alpha + 32767U)/65535U;
   2031                      green = (green * alpha + 32767U)/65535U;
   2032                      red = (red * alpha + 32767U)/65535U;
   2033                   }
   2034 
   2035                   else
   2036                      red = green = blue = 0;
   2037                }
   2038                entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
   2039                entry[afirst + 1] = (png_uint_16)green;
   2040                entry[afirst + bgr] = (png_uint_16)red;
   2041                break;
   2042 
   2043             case 2:
   2044                entry[1 ^ afirst] = (png_uint_16)alpha;
   2045                /* FALL THROUGH */
   2046 
   2047             case 1:
   2048                if (alpha < 65535)
   2049                {
   2050                   if (alpha > 0)
   2051                      green = (green * alpha + 32767U)/65535U;
   2052 
   2053                   else
   2054                      green = 0;
   2055                }
   2056                entry[afirst] = (png_uint_16)green;
   2057                break;
   2058 
   2059             default:
   2060                break;
   2061          }
   2062       }
   2063 
   2064       else /* output encoding is P_sRGB */
   2065       {
   2066          png_bytep entry = png_voidcast(png_bytep, display->colormap);
   2067 
   2068          entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
   2069 
   2070          switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
   2071          {
   2072             case 4:
   2073                entry[afirst ? 0 : 3] = (png_byte)alpha;
   2074             case 3:
   2075                entry[afirst + (2 ^ bgr)] = (png_byte)blue;
   2076                entry[afirst + 1] = (png_byte)green;
   2077                entry[afirst + bgr] = (png_byte)red;
   2078                break;
   2079 
   2080             case 2:
   2081                entry[1 ^ afirst] = (png_byte)alpha;
   2082             case 1:
   2083                entry[afirst] = (png_byte)green;
   2084                break;
   2085 
   2086             default:
   2087                break;
   2088          }
   2089       }
   2090 
   2091 #     ifdef afirst
   2092 #        undef afirst
   2093 #     endif
   2094 #     ifdef bgr
   2095 #        undef bgr
   2096 #     endif
   2097    }
   2098 }
   2099 
   2100 static int
   2101 make_gray_file_colormap(png_image_read_control *display)
   2102 {
   2103    unsigned int i;
   2104 
   2105    for (i=0; i<256; ++i)
   2106       png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
   2107 
   2108    return i;
   2109 }
   2110 
   2111 static int
   2112 make_gray_colormap(png_image_read_control *display)
   2113 {
   2114    unsigned int i;
   2115 
   2116    for (i=0; i<256; ++i)
   2117       png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
   2118 
   2119    return i;
   2120 }
   2121 #define PNG_GRAY_COLORMAP_ENTRIES 256
   2122 
   2123 static int
   2124 make_ga_colormap(png_image_read_control *display)
   2125 {
   2126    unsigned int i, a;
   2127 
   2128    /* Alpha is retained, the output will be a color-map with entries
   2129     * selected by six levels of alpha.  One transparent entry, 6 gray
   2130     * levels for all the intermediate alpha values, leaving 230 entries
   2131     * for the opaque grays.  The color-map entries are the six values
   2132     * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the
   2133     * relevant entry.
   2134     *
   2135     * if (alpha > 229) // opaque
   2136     * {
   2137     *    // The 231 entries are selected to make the math below work:
   2138     *    base = 0;
   2139     *    entry = (231 * gray + 128) >> 8;
   2140     * }
   2141     * else if (alpha < 26) // transparent
   2142     * {
   2143     *    base = 231;
   2144     *    entry = 0;
   2145     * }
   2146     * else // partially opaque
   2147     * {
   2148     *    base = 226 + 6 * PNG_DIV51(alpha);
   2149     *    entry = PNG_DIV51(gray);
   2150     * }
   2151     */
   2152    i = 0;
   2153    while (i < 231)
   2154    {
   2155       unsigned int gray = (i * 256 + 115) / 231;
   2156       png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
   2157    }
   2158 
   2159    /* 255 is used here for the component values for consistency with the code
   2160     * that undoes premultiplication in pngwrite.c.
   2161     */
   2162    png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
   2163 
   2164    for (a=1; a<5; ++a)
   2165    {
   2166       unsigned int g;
   2167 
   2168       for (g=0; g<6; ++g)
   2169          png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
   2170             P_sRGB);
   2171    }
   2172 
   2173    return i;
   2174 }
   2175 
   2176 #define PNG_GA_COLORMAP_ENTRIES 256
   2177 
   2178 static int
   2179 make_rgb_colormap(png_image_read_control *display)
   2180 {
   2181    unsigned int i, r;
   2182 
   2183    /* Build a 6x6x6 opaque RGB cube */
   2184    for (i=r=0; r<6; ++r)
   2185    {
   2186       unsigned int g;
   2187 
   2188       for (g=0; g<6; ++g)
   2189       {
   2190          unsigned int b;
   2191 
   2192          for (b=0; b<6; ++b)
   2193             png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
   2194                P_sRGB);
   2195       }
   2196    }
   2197 
   2198    return i;
   2199 }
   2200 
   2201 #define PNG_RGB_COLORMAP_ENTRIES 216
   2202 
   2203 /* Return a palette index to the above palette given three 8-bit sRGB values. */
   2204 #define PNG_RGB_INDEX(r,g,b) \
   2205    ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
   2206 
   2207 static int
   2208 png_image_read_colormap(png_voidp argument)
   2209 {
   2210    png_image_read_control *display =
   2211       png_voidcast(png_image_read_control*, argument);
   2212    const png_imagep image = display->image;
   2213 
   2214    const png_structrp png_ptr = image->opaque->png_ptr;
   2215    const png_uint_32 output_format = image->format;
   2216    const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ?
   2217       P_LINEAR : P_sRGB;
   2218 
   2219    unsigned int cmap_entries;
   2220    unsigned int output_processing;        /* Output processing option */
   2221    unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
   2222 
   2223    /* Background information; the background color and the index of this color
   2224     * in the color-map if it exists (else 256).
   2225     */
   2226    unsigned int background_index = 256;
   2227    png_uint_32 back_r, back_g, back_b;
   2228 
   2229    /* Flags to accumulate things that need to be done to the input. */
   2230    int expand_tRNS = 0;
   2231 
   2232    /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is
   2233     * very difficult to do, the results look awful, and it is difficult to see
   2234     * what possible use it is because the application can't control the
   2235     * color-map.
   2236     */
   2237    if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
   2238          png_ptr->num_trans > 0) /* alpha in input */ &&
   2239       ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
   2240    {
   2241       if (output_encoding == P_LINEAR) /* compose on black */
   2242          back_b = back_g = back_r = 0;
   2243 
   2244       else if (display->background == NULL /* no way to remove it */)
   2245          png_error(png_ptr,
   2246             "a background color must be supplied to remove alpha/transparency");
   2247 
   2248       /* Get a copy of the background color (this avoids repeating the checks
   2249        * below.)  The encoding is 8-bit sRGB or 16-bit linear, depending on the
   2250        * output format.
   2251        */
   2252       else
   2253       {
   2254          back_g = display->background->green;
   2255          if (output_format & PNG_FORMAT_FLAG_COLOR)
   2256          {
   2257             back_r = display->background->red;
   2258             back_b = display->background->blue;
   2259          }
   2260          else
   2261             back_b = back_r = back_g;
   2262       }
   2263    }
   2264 
   2265    else if (output_encoding == P_LINEAR)
   2266       back_b = back_r = back_g = 65535;
   2267 
   2268    else
   2269       back_b = back_r = back_g = 255;
   2270 
   2271    /* Default the input file gamma if required - this is necessary because
   2272     * libpng assumes that if no gamma information is present the data is in the
   2273     * output format, but the simplified API deduces the gamma from the input
   2274     * format.
   2275     */
   2276    if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
   2277    {
   2278       /* Do this directly, not using the png_colorspace functions, to ensure
   2279        * that it happens even if the colorspace is invalid (though probably if
   2280        * it is the setting will be ignored)  Note that the same thing can be
   2281        * achieved at the application interface with png_set_gAMA.
   2282        */
   2283       if (png_ptr->bit_depth == 16 &&
   2284          (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
   2285          png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
   2286 
   2287       else
   2288          png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
   2289 
   2290       png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
   2291    }
   2292 
   2293    /* Decide what to do based on the PNG color type of the input data.  The
   2294     * utility function png_create_colormap_entry deals with most aspects of the
   2295     * output transformations; this code works out how to produce bytes of
   2296     * color-map entries from the original format.
   2297     */
   2298    switch (png_ptr->color_type)
   2299    {
   2300       case PNG_COLOR_TYPE_GRAY:
   2301          if (png_ptr->bit_depth <= 8)
   2302          {
   2303             /* There at most 256 colors in the output, regardless of
   2304              * transparency.
   2305              */
   2306             unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;
   2307 
   2308             cmap_entries = 1U << png_ptr->bit_depth;
   2309             if (cmap_entries > image->colormap_entries)
   2310                png_error(png_ptr, "gray[8] color-map: too few entries");
   2311 
   2312             step = 255 / (cmap_entries - 1);
   2313             output_processing = PNG_CMAP_NONE;
   2314 
   2315             /* If there is a tRNS chunk then this either selects a transparent
   2316              * value or, if the output has no alpha, the background color.
   2317              */
   2318             if (png_ptr->num_trans > 0)
   2319             {
   2320                trans = png_ptr->trans_color.gray;
   2321 
   2322                if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
   2323                   back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
   2324             }
   2325 
   2326             /* png_create_colormap_entry just takes an RGBA and writes the
   2327              * corresponding color-map entry using the format from 'image',
   2328              * including the required conversion to sRGB or linear as
   2329              * appropriate.  The input values are always either sRGB (if the
   2330              * gamma correction flag is 0) or 0..255 scaled file encoded values
   2331              * (if the function must gamma correct them).
   2332              */
   2333             for (i=val=0; i<cmap_entries; ++i, val += step)
   2334             {
   2335                /* 'i' is a file value.  While this will result in duplicated
   2336                 * entries for 8-bit non-sRGB encoded files it is necessary to
   2337                 * have non-gamma corrected values to do tRNS handling.
   2338                 */
   2339                if (i != trans)
   2340                   png_create_colormap_entry(display, i, val, val, val, 255,
   2341                      P_FILE/*8-bit with file gamma*/);
   2342 
   2343                /* Else this entry is transparent.  The colors don't matter if
   2344                 * there is an alpha channel (back_alpha == 0), but it does no
   2345                 * harm to pass them in; the values are not set above so this
   2346                 * passes in white.
   2347                 *
   2348                 * NOTE: this preserves the full precision of the application
   2349                 * supplied background color when it is used.
   2350                 */
   2351                else
   2352                   png_create_colormap_entry(display, i, back_r, back_g, back_b,
   2353                      back_alpha, output_encoding);
   2354             }
   2355 
   2356             /* We need libpng to preserve the original encoding. */
   2357             data_encoding = P_FILE;
   2358 
   2359             /* The rows from libpng, while technically gray values, are now also
   2360              * color-map indicies; however, they may need to be expanded to 1
   2361              * byte per pixel.  This is what png_set_packing does (i.e., it
   2362              * unpacks the bit values into bytes.)
   2363              */
   2364             if (png_ptr->bit_depth < 8)
   2365                png_set_packing(png_ptr);
   2366          }
   2367 
   2368          else /* bit depth is 16 */
   2369          {
   2370             /* The 16-bit input values can be converted directly to 8-bit gamma
   2371              * encoded values; however, if a tRNS chunk is present 257 color-map
   2372              * entries are required.  This means that the extra entry requires
   2373              * special processing; add an alpha channel, sacrifice gray level
   2374              * 254 and convert transparent (alpha==0) entries to that.
   2375              *
   2376              * Use libpng to chop the data to 8 bits.  Convert it to sRGB at the
   2377              * same time to minimize quality loss.  If a tRNS chunk is present
   2378              * this means libpng must handle it too; otherwise it is impossible
   2379              * to do the exact match on the 16-bit value.
   2380              *
   2381              * If the output has no alpha channel *and* the background color is
   2382              * gray then it is possible to let libpng handle the substitution by
   2383              * ensuring that the corresponding gray level matches the background
   2384              * color exactly.
   2385              */
   2386             data_encoding = P_sRGB;
   2387 
   2388             if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
   2389                png_error(png_ptr, "gray[16] color-map: too few entries");
   2390 
   2391             cmap_entries = make_gray_colormap(display);
   2392 
   2393             if (png_ptr->num_trans > 0)
   2394             {
   2395                unsigned int back_alpha;
   2396 
   2397                if (output_format & PNG_FORMAT_FLAG_ALPHA)
   2398                   back_alpha = 0;
   2399 
   2400                else
   2401                {
   2402                   if (back_r == back_g && back_g == back_b)
   2403                   {
   2404                      /* Background is gray; no special processing will be
   2405                       * required.
   2406                       */
   2407                      png_color_16 c;
   2408                      png_uint_32 gray = back_g;
   2409 
   2410                      if (output_encoding == P_LINEAR)
   2411                      {
   2412                         gray = PNG_sRGB_FROM_LINEAR(gray * 255);
   2413 
   2414                         /* And make sure the corresponding palette entry
   2415                          * matches.
   2416                          */
   2417                         png_create_colormap_entry(display, gray, back_g, back_g,
   2418                            back_g, 65535, P_LINEAR);
   2419                      }
   2420 
   2421                      /* The background passed to libpng, however, must be the
   2422                       * sRGB value.
   2423                       */
   2424                      c.index = 0; /*unused*/
   2425                      c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
   2426 
   2427                      /* NOTE: does this work without expanding tRNS to alpha?
   2428                       * It should be the color->gray case below apparently
   2429                       * doesn't.
   2430                       */
   2431                      png_set_background_fixed(png_ptr, &c,
   2432                         PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
   2433                         0/*gamma: not used*/);
   2434 
   2435                      output_processing = PNG_CMAP_NONE;
   2436                      break;
   2437                   }
   2438 
   2439                   back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
   2440                }
   2441 
   2442                /* output_processing means that the libpng-processed row will be
   2443                 * 8-bit GA and it has to be processing to single byte color-map
   2444                 * values.  Entry 254 is replaced by either a completely
   2445                 * transparent entry or by the background color at full
   2446                 * precision (and the background color is not a simple gray leve
   2447                 * in this case.)
   2448                 */
   2449                expand_tRNS = 1;
   2450                output_processing = PNG_CMAP_TRANS;
   2451                background_index = 254;
   2452 
   2453                /* And set (overwrite) color-map entry 254 to the actual
   2454                 * background color at full precision.
   2455                 */
   2456                png_create_colormap_entry(display, 254, back_r, back_g, back_b,
   2457                   back_alpha, output_encoding);
   2458             }
   2459 
   2460             else
   2461                output_processing = PNG_CMAP_NONE;
   2462          }
   2463          break;
   2464 
   2465       case PNG_COLOR_TYPE_GRAY_ALPHA:
   2466          /* 8-bit or 16-bit PNG with two channels - gray and alpha.  A minimum
   2467           * of 65536 combinations.  If, however, the alpha channel is to be
   2468           * removed there are only 256 possibilities if the background is gray.
   2469           * (Otherwise there is a subset of the 65536 possibilities defined by
   2470           * the triangle between black, white and the background color.)
   2471           *
   2472           * Reduce 16-bit files to 8-bit and sRGB encode the result.  No need to
   2473           * worry about tRNS matching - tRNS is ignored if there is an alpha
   2474           * channel.
   2475           */
   2476          data_encoding = P_sRGB;
   2477 
   2478          if (output_format & PNG_FORMAT_FLAG_ALPHA)
   2479          {
   2480             if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
   2481                png_error(png_ptr, "gray+alpha color-map: too few entries");
   2482 
   2483             cmap_entries = make_ga_colormap(display);
   2484 
   2485             background_index = PNG_CMAP_GA_BACKGROUND;
   2486             output_processing = PNG_CMAP_GA;
   2487          }
   2488 
   2489          else /* alpha is removed */
   2490          {
   2491             /* Alpha must be removed as the PNG data is processed when the
   2492              * background is a color because the G and A channels are
   2493              * independent and the vector addition (non-parallel vectors) is a
   2494              * 2-D problem.
   2495              *
   2496              * This can be reduced to the same algorithm as above by making a
   2497              * colormap containing gray levels (for the opaque grays), a
   2498              * background entry (for a transparent pixel) and a set of four six
   2499              * level color values, one set for each intermediate alpha value.
   2500              * See the comments in make_ga_colormap for how this works in the
   2501              * per-pixel processing.
   2502              *
   2503              * If the background is gray, however, we only need a 256 entry gray
   2504              * level color map.  It is sufficient to make the entry generated
   2505              * for the background color be exactly the color specified.
   2506              */
   2507             if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
   2508                (back_r == back_g && back_g == back_b))
   2509             {
   2510                /* Background is gray; no special processing will be required. */
   2511                png_color_16 c;
   2512                png_uint_32 gray = back_g;
   2513 
   2514                if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
   2515                   png_error(png_ptr, "gray-alpha color-map: too few entries");
   2516 
   2517                cmap_entries = make_gray_colormap(display);
   2518 
   2519                if (output_encoding == P_LINEAR)
   2520                {
   2521                   gray = PNG_sRGB_FROM_LINEAR(gray * 255);
   2522 
   2523                   /* And make sure the corresponding palette entry matches. */
   2524                   png_create_colormap_entry(display, gray, back_g, back_g,
   2525                      back_g, 65535, P_LINEAR);
   2526                }
   2527 
   2528                /* The background passed to libpng, however, must be the sRGB
   2529                 * value.
   2530                 */
   2531                c.index = 0; /*unused*/
   2532                c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
   2533 
   2534                png_set_background_fixed(png_ptr, &c,
   2535                   PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
   2536                   0/*gamma: not used*/);
   2537 
   2538                output_processing = PNG_CMAP_NONE;
   2539             }
   2540 
   2541             else
   2542             {
   2543                png_uint_32 i, a;
   2544 
   2545                /* This is the same as png_make_ga_colormap, above, except that
   2546                 * the entries are all opaque.
   2547                 */
   2548                if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
   2549                   png_error(png_ptr, "ga-alpha color-map: too few entries");
   2550 
   2551                i = 0;
   2552                while (i < 231)
   2553                {
   2554                   png_uint_32 gray = (i * 256 + 115) / 231;
   2555                   png_create_colormap_entry(display, i++, gray, gray, gray,
   2556                      255, P_sRGB);
   2557                }
   2558 
   2559                /* NOTE: this preserves the full precision of the application
   2560                 * background color.
   2561                 */
   2562                background_index = i;
   2563                png_create_colormap_entry(display, i++, back_r, back_g, back_b,
   2564                   output_encoding == P_LINEAR ? 65535U : 255U, output_encoding);
   2565 
   2566                /* For non-opaque input composite on the sRGB background - this
   2567                 * requires inverting the encoding for each component.  The input
   2568                 * is still converted to the sRGB encoding because this is a
   2569                 * reasonable approximate to the logarithmic curve of human
   2570                 * visual sensitivity, at least over the narrow range which PNG
   2571                 * represents.  Consequently 'G' is always sRGB encoded, while
   2572                 * 'A' is linear.  We need the linear background colors.
   2573                 */
   2574                if (output_encoding == P_sRGB) /* else already linear */
   2575                {
   2576                   /* This may produce a value not exactly matching the
   2577                    * background, but that's ok because these numbers are only
   2578                    * used when alpha != 0
   2579                    */
   2580                   back_r = png_sRGB_table[back_r];
   2581                   back_g = png_sRGB_table[back_g];
   2582                   back_b = png_sRGB_table[back_b];
   2583                }
   2584 
   2585                for (a=1; a<5; ++a)
   2586                {
   2587                   unsigned int g;
   2588 
   2589                   /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled
   2590                    * by an 8-bit alpha value (0..255).
   2591                    */
   2592                   png_uint_32 alpha = 51 * a;
   2593                   png_uint_32 back_rx = (255-alpha) * back_r;
   2594                   png_uint_32 back_gx = (255-alpha) * back_g;
   2595                   png_uint_32 back_bx = (255-alpha) * back_b;
   2596 
   2597                   for (g=0; g<6; ++g)
   2598                   {
   2599                      png_uint_32 gray = png_sRGB_table[g*51] * alpha;
   2600 
   2601                      png_create_colormap_entry(display, i++,
   2602                         PNG_sRGB_FROM_LINEAR(gray + back_rx),
   2603                         PNG_sRGB_FROM_LINEAR(gray + back_gx),
   2604                         PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
   2605                   }
   2606                }
   2607 
   2608                cmap_entries = i;
   2609                output_processing = PNG_CMAP_GA;
   2610             }
   2611          }
   2612          break;
   2613 
   2614       case PNG_COLOR_TYPE_RGB:
   2615       case PNG_COLOR_TYPE_RGB_ALPHA:
   2616          /* Exclude the case where the output is gray; we can always handle this
   2617           * with the cases above.
   2618           */
   2619          if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
   2620          {
   2621             /* The color-map will be grayscale, so we may as well convert the
   2622              * input RGB values to a simple grayscale and use the grayscale
   2623              * code above.
   2624              *
   2625              * NOTE: calling this apparently damages the recognition of the
   2626              * transparent color in background color handling; call
   2627              * png_set_tRNS_to_alpha before png_set_background_fixed.
   2628              */
   2629             png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
   2630                -1);
   2631             data_encoding = P_sRGB;
   2632 
   2633             /* The output will now be one or two 8-bit gray or gray+alpha
   2634              * channels.  The more complex case arises when the input has alpha.
   2635              */
   2636             if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
   2637                png_ptr->num_trans > 0) &&
   2638                (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
   2639             {
   2640                /* Both input and output have an alpha channel, so no background
   2641                 * processing is required; just map the GA bytes to the right
   2642                 * color-map entry.
   2643                 */
   2644                expand_tRNS = 1;
   2645 
   2646                if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
   2647                   png_error(png_ptr, "rgb[ga] color-map: too few entries");
   2648 
   2649                cmap_entries = make_ga_colormap(display);
   2650                background_index = PNG_CMAP_GA_BACKGROUND;
   2651                output_processing = PNG_CMAP_GA;
   2652             }
   2653 
   2654             else
   2655             {
   2656                /* Either the input or the output has no alpha channel, so there
   2657                 * will be no non-opaque pixels in the color-map; it will just be
   2658                 * grayscale.
   2659                 */
   2660                if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
   2661                   png_error(png_ptr, "rgb[gray] color-map: too few entries");
   2662 
   2663                /* Ideally this code would use libpng to do the gamma correction,
   2664                 * but if an input alpha channel is to be removed we will hit the
   2665                 * libpng bug in gamma+compose+rgb-to-gray (the double gamma
   2666                 * correction bug).  Fix this by dropping the gamma correction in
   2667                 * this case and doing it in the palette; this will result in
   2668                 * duplicate palette entries, but that's better than the
   2669                 * alternative of double gamma correction.
   2670                 */
   2671                if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
   2672                   png_ptr->num_trans > 0) &&
   2673                   png_gamma_not_sRGB(png_ptr->colorspace.gamma))
   2674                {
   2675                   cmap_entries = make_gray_file_colormap(display);
   2676                   data_encoding = P_FILE;
   2677                }
   2678 
   2679                else
   2680                   cmap_entries = make_gray_colormap(display);
   2681 
   2682                /* But if the input has alpha or transparency it must be removed
   2683                 */
   2684                if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
   2685                   png_ptr->num_trans > 0)
   2686                {
   2687                   png_color_16 c;
   2688                   png_uint_32 gray = back_g;
   2689 
   2690                   /* We need to ensure that the application background exists in
   2691                    * the colormap and that completely transparent pixels map to
   2692                    * it.  Achieve this simply by ensuring that the entry
   2693                    * selected for the background really is the background color.
   2694                    */
   2695                   if (data_encoding == P_FILE) /* from the fixup above */
   2696                   {
   2697                      /* The app supplied a gray which is in output_encoding, we
   2698                       * need to convert it to a value of the input (P_FILE)
   2699                       * encoding then set this palette entry to the required
   2700                       * output encoding.
   2701                       */
   2702                      if (output_encoding == P_sRGB)
   2703                         gray = png_sRGB_table[gray]; /* now P_LINEAR */
   2704 
   2705                      gray = PNG_DIV257(png_gamma_16bit_correct(gray,
   2706                         png_ptr->colorspace.gamma)); /* now P_FILE */
   2707 
   2708                      /* And make sure the corresponding palette entry contains
   2709                       * exactly the required sRGB value.
   2710                       */
   2711                      png_create_colormap_entry(display, gray, back_g, back_g,
   2712                         back_g, 0/*unused*/, output_encoding);
   2713                   }
   2714 
   2715                   else if (output_encoding == P_LINEAR)
   2716                   {
   2717                      gray = PNG_sRGB_FROM_LINEAR(gray * 255);
   2718 
   2719                      /* And make sure the corresponding palette entry matches.
   2720                       */
   2721                      png_create_colormap_entry(display, gray, back_g, back_g,
   2722                         back_g, 0/*unused*/, P_LINEAR);
   2723                   }
   2724 
   2725                   /* The background passed to libpng, however, must be the
   2726                    * output (normally sRGB) value.
   2727                    */
   2728                   c.index = 0; /*unused*/
   2729                   c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
   2730 
   2731                   /* NOTE: the following is apparently a bug in libpng. Without
   2732                    * it the transparent color recognition in
   2733                    * png_set_background_fixed seems to go wrong.
   2734                    */
   2735                   expand_tRNS = 1;
   2736                   png_set_background_fixed(png_ptr, &c,
   2737                      PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
   2738                      0/*gamma: not used*/);
   2739                }
   2740 
   2741                output_processing = PNG_CMAP_NONE;
   2742             }
   2743          }
   2744 
   2745          else /* output is color */
   2746          {
   2747             /* We could use png_quantize here so long as there is no transparent
   2748              * color or alpha; png_quantize ignores alpha.  Easier overall just
   2749              * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
   2750              * Consequently we always want libpng to produce sRGB data.
   2751              */
   2752             data_encoding = P_sRGB;
   2753 
   2754             /* Is there any transparency or alpha? */
   2755             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
   2756                png_ptr->num_trans > 0)
   2757             {
   2758                /* Is there alpha in the output too?  If so all four channels are
   2759                 * processed into a special RGB cube with alpha support.
   2760                 */
   2761                if (output_format & PNG_FORMAT_FLAG_ALPHA)
   2762                {
   2763                   png_uint_32 r;
   2764 
   2765                   if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
   2766                      png_error(png_ptr, "rgb+alpha color-map: too few entries");
   2767 
   2768                   cmap_entries = make_rgb_colormap(display);
   2769 
   2770                   /* Add a transparent entry. */
   2771                   png_create_colormap_entry(display, cmap_entries, 255, 255,
   2772                      255, 0, P_sRGB);
   2773 
   2774                   /* This is stored as the background index for the processing
   2775                    * algorithm.
   2776                    */
   2777                   background_index = cmap_entries++;
   2778 
   2779                   /* Add 27 r,g,b entries each with alpha 0.5. */
   2780                   for (r=0; r<256; r = (r << 1) | 0x7f)
   2781                   {
   2782                      png_uint_32 g;
   2783 
   2784                      for (g=0; g<256; g = (g << 1) | 0x7f)
   2785                      {
   2786                         png_uint_32 b;
   2787 
   2788                         /* This generates components with the values 0, 127 and
   2789                          * 255
   2790                          */
   2791                         for (b=0; b<256; b = (b << 1) | 0x7f)
   2792                            png_create_colormap_entry(display, cmap_entries++,
   2793                               r, g, b, 128, P_sRGB);
   2794                      }
   2795                   }
   2796 
   2797                   expand_tRNS = 1;
   2798                   output_processing = PNG_CMAP_RGB_ALPHA;
   2799                }
   2800 
   2801                else
   2802                {
   2803                   /* Alpha/transparency must be removed.  The background must
   2804                    * exist in the color map (achieved by setting adding it after
   2805                    * the 666 color-map).  If the standard processing code will
   2806                    * pick up this entry automatically that's all that is
   2807                    * required; libpng can be called to do the background
   2808                    * processing.
   2809                    */
   2810                   unsigned int sample_size =
   2811                      PNG_IMAGE_SAMPLE_SIZE(output_format);
   2812                   png_uint_32 r, g, b; /* sRGB background */
   2813 
   2814                   if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
   2815                      png_error(png_ptr, "rgb-alpha color-map: too few entries");
   2816 
   2817                   cmap_entries = make_rgb_colormap(display);
   2818 
   2819                   png_create_colormap_entry(display, cmap_entries, back_r,
   2820                         back_g, back_b, 0/*unused*/, output_encoding);
   2821 
   2822                   if (output_encoding == P_LINEAR)
   2823                   {
   2824                      r = PNG_sRGB_FROM_LINEAR(back_r * 255);
   2825                      g = PNG_sRGB_FROM_LINEAR(back_g * 255);
   2826                      b = PNG_sRGB_FROM_LINEAR(back_b * 255);
   2827                   }
   2828 
   2829                   else
   2830                   {
   2831                      r = back_r;
   2832                      g = back_g;
   2833                      b = back_g;
   2834                   }
   2835 
   2836                   /* Compare the newly-created color-map entry with the one the
   2837                    * PNG_CMAP_RGB algorithm will use.  If the two entries don't
   2838                    * match, add the new one and set this as the background
   2839                    * index.
   2840                    */
   2841                   if (memcmp((png_const_bytep)display->colormap +
   2842                         sample_size * cmap_entries,
   2843                      (png_const_bytep)display->colormap +
   2844                         sample_size * PNG_RGB_INDEX(r,g,b),
   2845                      sample_size) != 0)
   2846                   {
   2847                      /* The background color must be added. */
   2848                      background_index = cmap_entries++;
   2849 
   2850                      /* Add 27 r,g,b entries each with created by composing with
   2851                       * the background at alpha 0.5.
   2852                       */
   2853                      for (r=0; r<256; r = (r << 1) | 0x7f)
   2854                      {
   2855                         for (g=0; g<256; g = (g << 1) | 0x7f)
   2856                         {
   2857                            /* This generates components with the values 0, 127
   2858                             * and 255
   2859                             */
   2860                            for (b=0; b<256; b = (b << 1) | 0x7f)
   2861                               png_create_colormap_entry(display, cmap_entries++,
   2862                                  png_colormap_compose(display, r, P_sRGB, 128,
   2863                                     back_r, output_encoding),
   2864                                  png_colormap_compose(display, g, P_sRGB, 128,
   2865                                     back_g, output_encoding),
   2866                                  png_colormap_compose(display, b, P_sRGB, 128,
   2867                                     back_b, output_encoding),
   2868                                  0/*unused*/, output_encoding);
   2869                         }
   2870                      }
   2871 
   2872                      expand_tRNS = 1;
   2873                      output_processing = PNG_CMAP_RGB_ALPHA;
   2874                   }
   2875 
   2876                   else /* background color is in the standard color-map */
   2877                   {
   2878                      png_color_16 c;
   2879 
   2880                      c.index = 0; /*unused*/
   2881                      c.red = (png_uint_16)back_r;
   2882                      c.gray = c.green = (png_uint_16)back_g;
   2883                      c.blue = (png_uint_16)back_b;
   2884 
   2885                      png_set_background_fixed(png_ptr, &c,
   2886                         PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
   2887                         0/*gamma: not used*/);
   2888 
   2889                      output_processing = PNG_CMAP_RGB;
   2890                   }
   2891                }
   2892             }
   2893 
   2894             else /* no alpha or transparency in the input */
   2895             {
   2896                /* Alpha in the output is irrelevant, simply map the opaque input
   2897                 * pixels to the 6x6x6 color-map.
   2898                 */
   2899                if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
   2900                   png_error(png_ptr, "rgb color-map: too few entries");
   2901 
   2902                cmap_entries = make_rgb_colormap(display);
   2903                output_processing = PNG_CMAP_RGB;
   2904             }
   2905          }
   2906          break;
   2907 
   2908       case PNG_COLOR_TYPE_PALETTE:
   2909          /* It's already got a color-map.  It may be necessary to eliminate the
   2910           * tRNS entries though.
   2911           */
   2912          {
   2913             unsigned int num_trans = png_ptr->num_trans;
   2914             png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
   2915             png_const_colorp colormap = png_ptr->palette;
   2916             const int do_background = trans != NULL &&
   2917                (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
   2918             unsigned int i;
   2919 
   2920             /* Just in case: */
   2921             if (trans == NULL)
   2922                num_trans = 0;
   2923 
   2924             output_processing = PNG_CMAP_NONE;
   2925             data_encoding = P_FILE; /* Don't change from color-map indicies */
   2926             cmap_entries = png_ptr->num_palette;
   2927             if (cmap_entries > 256)
   2928                cmap_entries = 256;
   2929 
   2930             if (cmap_entries > image->colormap_entries)
   2931                png_error(png_ptr, "palette color-map: too few entries");
   2932 
   2933             for (i=0; i < cmap_entries; ++i)
   2934             {
   2935                if (do_background && i < num_trans && trans[i] < 255)
   2936                {
   2937                   if (trans[i] == 0)
   2938                      png_create_colormap_entry(display, i, back_r, back_g,
   2939                         back_b, 0, output_encoding);
   2940 
   2941                   else
   2942                   {
   2943                      /* Must compose the PNG file color in the color-map entry
   2944                       * on the sRGB color in 'back'.
   2945                       */
   2946                      png_create_colormap_entry(display, i,
   2947                         png_colormap_compose(display, colormap[i].red, P_FILE,
   2948                            trans[i], back_r, output_encoding),
   2949                         png_colormap_compose(display, colormap[i].green, P_FILE,
   2950                            trans[i], back_g, output_encoding),
   2951                         png_colormap_compose(display, colormap[i].blue, P_FILE,
   2952                            trans[i], back_b, output_encoding),
   2953                         output_encoding == P_LINEAR ? trans[i] * 257U :
   2954                            trans[i],
   2955                         output_encoding);
   2956                   }
   2957                }
   2958 
   2959                else
   2960                   png_create_colormap_entry(display, i, colormap[i].red,
   2961                      colormap[i].green, colormap[i].blue,
   2962                      i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
   2963             }
   2964 
   2965             /* The PNG data may have indicies packed in fewer than 8 bits, it
   2966              * must be expanded if so.
   2967              */
   2968             if (png_ptr->bit_depth < 8)
   2969                png_set_packing(png_ptr);
   2970          }
   2971          break;
   2972 
   2973       default:
   2974          png_error(png_ptr, "invalid PNG color type");
   2975          /*NOT REACHED*/
   2976          break;
   2977    }
   2978 
   2979    /* Now deal with the output processing */
   2980    if (expand_tRNS && png_ptr->num_trans > 0 &&
   2981       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
   2982       png_set_tRNS_to_alpha(png_ptr);
   2983 
   2984    switch (data_encoding)
   2985    {
   2986       default:
   2987          png_error(png_ptr, "bad data option (internal error)");
   2988          break;
   2989 
   2990       case P_sRGB:
   2991          /* Change to 8-bit sRGB */
   2992          png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
   2993          /* FALL THROUGH */
   2994 
   2995       case P_FILE:
   2996          if (png_ptr->bit_depth > 8)
   2997             png_set_scale_16(png_ptr);
   2998          break;
   2999    }
   3000 
   3001    if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
   3002       png_error(png_ptr, "color map overflow (BAD internal error)");
   3003 
   3004    image->colormap_entries = cmap_entries;
   3005 
   3006    /* Double check using the recorded background index */
   3007    switch (output_processing)
   3008    {
   3009       case PNG_CMAP_NONE:
   3010          if (background_index != PNG_CMAP_NONE_BACKGROUND)
   3011             goto bad_background;
   3012          break;
   3013 
   3014       case PNG_CMAP_GA:
   3015          if (background_index != PNG_CMAP_GA_BACKGROUND)
   3016             goto bad_background;
   3017          break;
   3018 
   3019       case PNG_CMAP_TRANS:
   3020          if (background_index >= cmap_entries ||
   3021             background_index != PNG_CMAP_TRANS_BACKGROUND)
   3022             goto bad_background;
   3023          break;
   3024 
   3025       case PNG_CMAP_RGB:
   3026          if (background_index != PNG_CMAP_RGB_BACKGROUND)
   3027             goto bad_background;
   3028          break;
   3029 
   3030       case PNG_CMAP_RGB_ALPHA:
   3031          if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
   3032             goto bad_background;
   3033          break;
   3034 
   3035       default:
   3036          png_error(png_ptr, "bad processing option (internal error)");
   3037 
   3038       bad_background:
   3039          png_error(png_ptr, "bad background index (internal error)");
   3040    }
   3041 
   3042    display->colormap_processing = output_processing;
   3043 
   3044    return 1/*ok*/;
   3045 }
   3046 
   3047 /* The final part of the color-map read called from png_image_finish_read. */
   3048 static int
   3049 png_image_read_and_map(png_voidp argument)
   3050 {
   3051    png_image_read_control *display = png_voidcast(png_image_read_control*,
   3052       argument);
   3053    png_imagep image = display->image;
   3054    png_structrp png_ptr = image->opaque->png_ptr;
   3055    int passes;
   3056 
   3057    /* Called when the libpng data must be transformed into the color-mapped
   3058     * form.  There is a local row buffer in display->local and this routine must
   3059     * do the interlace handling.
   3060     */
   3061    switch (png_ptr->interlaced)
   3062    {
   3063       case PNG_INTERLACE_NONE:
   3064          passes = 1;
   3065          break;
   3066 
   3067       case PNG_INTERLACE_ADAM7:
   3068          passes = PNG_INTERLACE_ADAM7_PASSES;
   3069          break;
   3070 
   3071       default:
   3072          png_error(png_ptr, "unknown interlace type");
   3073    }
   3074 
   3075    {
   3076       png_uint_32  height = image->height;
   3077       png_uint_32  width = image->width;
   3078       int          proc = display->colormap_processing;
   3079       png_bytep    first_row = png_voidcast(png_bytep, display->first_row);
   3080       ptrdiff_t    step_row = display->row_bytes;
   3081       int pass;
   3082 
   3083       for (pass = 0; pass < passes; ++pass)
   3084       {
   3085          unsigned int     startx, stepx, stepy;
   3086          png_uint_32      y;
   3087 
   3088          if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
   3089          {
   3090             /* The row may be empty for a short image: */
   3091             if (PNG_PASS_COLS(width, pass) == 0)
   3092                continue;
   3093 
   3094             startx = PNG_PASS_START_COL(pass);
   3095             stepx = PNG_PASS_COL_OFFSET(pass);
   3096             y = PNG_PASS_START_ROW(pass);
   3097             stepy = PNG_PASS_ROW_OFFSET(pass);
   3098          }
   3099 
   3100          else
   3101          {
   3102             y = 0;
   3103             startx = 0;
   3104             stepx = stepy = 1;
   3105          }
   3106 
   3107          for (; y<height; y += stepy)
   3108          {
   3109             png_bytep inrow = png_voidcast(png_bytep, display->local_row);
   3110             png_bytep outrow = first_row + y * step_row;
   3111             png_const_bytep end_row = outrow + width;
   3112 
   3113             /* Read read the libpng data into the temporary buffer. */
   3114             png_read_row(png_ptr, inrow, NULL);
   3115 
   3116             /* Now process the row according to the processing option, note
   3117              * that the caller verifies that the format of the libpng output
   3118              * data is as required.
   3119              */
   3120             outrow += startx;
   3121             switch (proc)
   3122             {
   3123                case PNG_CMAP_GA:
   3124                   for (; outrow < end_row; outrow += stepx)
   3125                   {
   3126                      /* The data is always in the PNG order */
   3127                      unsigned int gray = *inrow++;
   3128                      unsigned int alpha = *inrow++;
   3129                      unsigned int entry;
   3130 
   3131                      /* NOTE: this code is copied as a comment in
   3132                       * make_ga_colormap above.  Please update the
   3133                       * comment if you change this code!
   3134                       */
   3135                      if (alpha > 229) /* opaque */
   3136                      {
   3137                         entry = (231 * gray + 128) >> 8;
   3138                      }
   3139                      else if (alpha < 26) /* transparent */
   3140                      {
   3141                         entry = 231;
   3142                      }
   3143                      else /* partially opaque */
   3144                      {
   3145                         entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
   3146                      }
   3147 
   3148                      *outrow = (png_byte)entry;
   3149                   }
   3150                   break;
   3151 
   3152                case PNG_CMAP_TRANS:
   3153                   for (; outrow < end_row; outrow += stepx)
   3154                   {
   3155                      png_byte gray = *inrow++;
   3156                      png_byte alpha = *inrow++;
   3157 
   3158                      if (alpha == 0)
   3159                         *outrow = PNG_CMAP_TRANS_BACKGROUND;
   3160 
   3161                      else if (gray != PNG_CMAP_TRANS_BACKGROUND)
   3162                         *outrow = gray;
   3163 
   3164                      else
   3165                         *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
   3166                   }
   3167                   break;
   3168 
   3169                case PNG_CMAP_RGB:
   3170                   for (; outrow < end_row; outrow += stepx)
   3171                   {
   3172                      *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
   3173                      inrow += 3;
   3174                   }
   3175                   break;
   3176 
   3177                case PNG_CMAP_RGB_ALPHA:
   3178                   for (; outrow < end_row; outrow += stepx)
   3179                   {
   3180                      unsigned int alpha = inrow[3];
   3181 
   3182                      /* Because the alpha entries only hold alpha==0.5 values
   3183                       * split the processing at alpha==0.25 (64) and 0.75
   3184                       * (196).
   3185                       */
   3186 
   3187                      if (alpha >= 196)
   3188                         *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
   3189                            inrow[2]);
   3190 
   3191                      else if (alpha < 64)
   3192                         *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
   3193 
   3194                      else
   3195                      {
   3196                         /* Likewise there are three entries for each of r, g
   3197                          * and b.  We could select the entry by popcount on
   3198                          * the top two bits on those architectures that
   3199                          * support it, this is what the code below does,
   3200                          * crudely.
   3201                          */
   3202                         unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
   3203 
   3204                         /* Here are how the values map:
   3205                          *
   3206                          * 0x00 .. 0x3f -> 0
   3207                          * 0x40 .. 0xbf -> 1
   3208                          * 0xc0 .. 0xff -> 2
   3209                          *
   3210                          * So, as above with the explicit alpha checks, the
   3211                          * breakpoints are at 64 and 196.
   3212                          */
   3213                         if (inrow[0] & 0x80) back_i += 9; /* red */
   3214                         if (inrow[0] & 0x40) back_i += 9;
   3215                         if (inrow[0] & 0x80) back_i += 3; /* green */
   3216                         if (inrow[0] & 0x40) back_i += 3;
   3217                         if (inrow[0] & 0x80) back_i += 1; /* blue */
   3218                         if (inrow[0] & 0x40) back_i += 1;
   3219 
   3220                         *outrow = (png_byte)back_i;
   3221                      }
   3222 
   3223                      inrow += 4;
   3224                   }
   3225                   break;
   3226 
   3227                default:
   3228                   break;
   3229             }
   3230          }
   3231       }
   3232    }
   3233 
   3234    return 1;
   3235 }
   3236 
   3237 static int
   3238 png_image_read_colormapped(png_voidp argument)
   3239 {
   3240    png_image_read_control *display = png_voidcast(png_image_read_control*,
   3241       argument);
   3242    png_imagep image = display->image;
   3243    png_controlp control = image->opaque;
   3244    png_structrp png_ptr = control->png_ptr;
   3245    png_inforp info_ptr = control->info_ptr;
   3246 
   3247    int passes = 0; /* As a flag */
   3248 
   3249    PNG_SKIP_CHUNKS(png_ptr);
   3250 
   3251    /* Update the 'info' structure and make sure the result is as required; first
   3252     * make sure to turn on the interlace handling if it will be required
   3253     * (because it can't be turned on *after* the call to png_read_update_info!)
   3254     */
   3255    if (display->colormap_processing == PNG_CMAP_NONE)
   3256       passes = png_set_interlace_handling(png_ptr);
   3257 
   3258    png_read_update_info(png_ptr, info_ptr);
   3259 
   3260    /* The expected output can be deduced from the colormap_processing option. */
   3261    switch (display->colormap_processing)
   3262    {
   3263       case PNG_CMAP_NONE:
   3264          /* Output must be one channel and one byte per pixel, the output
   3265           * encoding can be anything.
   3266           */
   3267          if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
   3268             info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
   3269             info_ptr->bit_depth == 8)
   3270             break;
   3271 
   3272          goto bad_output;
   3273 
   3274       case PNG_CMAP_TRANS:
   3275       case PNG_CMAP_GA:
   3276          /* Output must be two channels and the 'G' one must be sRGB, the latter
   3277           * can be checked with an exact number because it should have been set
   3278           * to this number above!
   3279           */
   3280          if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
   3281             info_ptr->bit_depth == 8 &&
   3282             png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
   3283             image->colormap_entries == 256)
   3284             break;
   3285 
   3286          goto bad_output;
   3287 
   3288       case PNG_CMAP_RGB:
   3289          /* Output must be 8-bit sRGB encoded RGB */
   3290          if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
   3291             info_ptr->bit_depth == 8 &&
   3292             png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
   3293             image->colormap_entries == 216)
   3294             break;
   3295 
   3296          goto bad_output;
   3297 
   3298       case PNG_CMAP_RGB_ALPHA:
   3299          /* Output must be 8-bit sRGB encoded RGBA */
   3300          if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
   3301             info_ptr->bit_depth == 8 &&
   3302             png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
   3303             image->colormap_entries == 244 /* 216 + 1 + 27 */)
   3304             break;
   3305 
   3306          /* goto bad_output; */
   3307          /* FALL THROUGH */
   3308 
   3309       default:
   3310       bad_output:
   3311          png_error(png_ptr, "bad color-map processing (internal error)");
   3312    }
   3313 
   3314    /* Now read the rows.  Do this here if it is possible to read directly into
   3315     * the output buffer, otherwise allocate a local row buffer of the maximum
   3316     * size libpng requires and call the relevant processing routine safely.
   3317     */
   3318    {
   3319       png_voidp first_row = display->buffer;
   3320       ptrdiff_t row_bytes = display->row_stride;
   3321 
   3322       /* The following expression is designed to work correctly whether it gives
   3323        * a signed or an unsigned result.
   3324        */
   3325       if (row_bytes < 0)
   3326       {
   3327          char *ptr = png_voidcast(char*, first_row);
   3328          ptr += (image->height-1) * (-row_bytes);
   3329          first_row = png_voidcast(png_voidp, ptr);
   3330       }
   3331 
   3332       display->first_row = first_row;
   3333       display->row_bytes = row_bytes;
   3334    }
   3335 
   3336    if (passes == 0)
   3337    {
   3338       int result;
   3339       png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
   3340 
   3341       display->local_row = row;
   3342       result = png_safe_execute(image, png_image_read_and_map, display);
   3343       display->local_row = NULL;
   3344       png_free(png_ptr, row);
   3345 
   3346       return result;
   3347    }
   3348 
   3349    else
   3350    {
   3351       png_alloc_size_t row_bytes = display->row_bytes;
   3352 
   3353       while (--passes >= 0)
   3354       {
   3355          png_uint_32      y = image->height;
   3356          png_bytep        row = png_voidcast(png_bytep, display->first_row);
   3357 
   3358          while (y-- > 0)
   3359          {
   3360             png_read_row(png_ptr, row, NULL);
   3361             row += row_bytes;
   3362          }
   3363       }
   3364 
   3365       return 1;
   3366    }
   3367 }
   3368 
   3369 /* Just the row reading part of png_image_read. */
   3370 static int
   3371 png_image_read_composite(png_voidp argument)
   3372 {
   3373    png_image_read_control *display = png_voidcast(png_image_read_control*,
   3374       argument);
   3375    png_imagep image = display->image;
   3376    png_structrp png_ptr = image->opaque->png_ptr;
   3377    int passes;
   3378 
   3379    switch (png_ptr->interlaced)
   3380    {
   3381       case PNG_INTERLACE_NONE:
   3382          passes = 1;
   3383          break;
   3384 
   3385       case PNG_INTERLACE_ADAM7:
   3386          passes = PNG_INTERLACE_ADAM7_PASSES;
   3387          break;
   3388 
   3389       default:
   3390          png_error(png_ptr, "unknown interlace type");
   3391    }
   3392 
   3393    {
   3394       png_uint_32  height = image->height;
   3395       png_uint_32  width = image->width;
   3396       ptrdiff_t    step_row = display->row_bytes;
   3397       unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
   3398       int pass;
   3399 
   3400       for (pass = 0; pass < passes; ++pass)
   3401       {
   3402          unsigned int     startx, stepx, stepy;
   3403          png_uint_32      y;
   3404 
   3405          if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
   3406          {
   3407             /* The row may be empty for a short image: */
   3408             if (PNG_PASS_COLS(width, pass) == 0)
   3409                continue;
   3410 
   3411             startx = PNG_PASS_START_COL(pass) * channels;
   3412             stepx = PNG_PASS_COL_OFFSET(pass) * channels;
   3413             y = PNG_PASS_START_ROW(pass);
   3414             stepy = PNG_PASS_ROW_OFFSET(pass);
   3415          }
   3416 
   3417          else
   3418          {
   3419             y = 0;
   3420             startx = 0;
   3421             stepx = channels;
   3422             stepy = 1;
   3423          }
   3424 
   3425          for (; y<height; y += stepy)
   3426          {
   3427             png_bytep inrow = png_voidcast(png_bytep, display->local_row);
   3428             png_bytep outrow;
   3429             png_const_bytep end_row;
   3430 
   3431             /* Read the row, which is packed: */
   3432             png_read_row(png_ptr, inrow, NULL);
   3433 
   3434             outrow = png_voidcast(png_bytep, display->first_row);
   3435             outrow += y * step_row;
   3436             end_row = outrow + width * channels;
   3437 
   3438             /* Now do the composition on each pixel in this row. */
   3439             outrow += startx;
   3440             for (; outrow < end_row; outrow += stepx)
   3441             {
   3442                png_byte alpha = inrow[channels];
   3443 
   3444                if (alpha > 0) /* else no change to the output */
   3445                {
   3446                   unsigned int c;
   3447 
   3448                   for (c=0; c<channels; ++c)
   3449                   {
   3450                      png_uint_32 component = inrow[c];
   3451 
   3452                      if (alpha < 255) /* else just use component */
   3453                      {
   3454                         /* This is PNG_OPTIMIZED_ALPHA, the component value
   3455                          * is a linear 8-bit value.  Combine this with the
   3456                          * current outrow[c] value which is sRGB encoded.
   3457                          * Arithmetic here is 16-bits to preserve the output
   3458                          * values correctly.
   3459                          */
   3460                         component *= 257*255; /* =65535 */
   3461                         component += (255-alpha)*png_sRGB_table[outrow[c]];
   3462 
   3463                         /* So 'component' is scaled by 255*65535 and is
   3464                          * therefore appropriate for the sRGB to linear
   3465                          * conversion table.
   3466                          */
   3467                         component = PNG_sRGB_FROM_LINEAR(component);
   3468                      }
   3469 
   3470                      outrow[c] = (png_byte)component;
   3471                   }
   3472                }
   3473 
   3474                inrow += channels+1; /* components and alpha channel */
   3475             }
   3476          }
   3477       }
   3478    }
   3479 
   3480    return 1;
   3481 }
   3482 
   3483 /* The do_local_background case; called when all the following transforms are to
   3484  * be done:
   3485  *
   3486  * PNG_RGB_TO_GRAY
   3487  * PNG_COMPOSITE
   3488  * PNG_GAMMA
   3489  *
   3490  * This is a work-round for the fact that both the PNG_RGB_TO_GRAY and
   3491  * PNG_COMPOSITE code performs gamma correction, so we get double gamma
   3492  * correction.  The fix-up is to prevent the PNG_COMPOSITE operation happening
   3493  * inside libpng, so this routine sees an 8 or 16-bit gray+alpha row and handles
   3494  * the removal or pre-multiplication of the alpha channel.
   3495  */
   3496 static int
   3497 png_image_read_background(png_voidp argument)
   3498 {
   3499    png_image_read_control *display = png_voidcast(png_image_read_control*,
   3500       argument);
   3501    png_imagep image = display->image;
   3502    png_structrp png_ptr = image->opaque->png_ptr;
   3503    png_inforp info_ptr = image->opaque->info_ptr;
   3504    png_uint_32 height = image->height;
   3505    png_uint_32 width = image->width;
   3506    int pass, passes;
   3507 
   3508    /* Double check the convoluted logic below.  We expect to get here with
   3509     * libpng doing rgb to gray and gamma correction but background processing
   3510     * left to the png_image_read_background function.  The rows libpng produce
   3511     * might be 8 or 16-bit but should always have two channels; gray plus alpha.
   3512     */
   3513    if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
   3514       png_error(png_ptr, "lost rgb to gray");
   3515 
   3516    if ((png_ptr->transformations & PNG_COMPOSE) != 0)
   3517       png_error(png_ptr, "unexpected compose");
   3518 
   3519    if (png_get_channels(png_ptr, info_ptr) != 2)
   3520       png_error(png_ptr, "lost/gained channels");
   3521 
   3522    /* Expect the 8-bit case to always remove the alpha channel */
   3523    if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
   3524       (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
   3525       png_error(png_ptr, "unexpected 8-bit transformation");
   3526 
   3527    switch (png_ptr->interlaced)
   3528    {
   3529       case PNG_INTERLACE_NONE:
   3530          passes = 1;
   3531          break;
   3532 
   3533       case PNG_INTERLACE_ADAM7:
   3534          passes = PNG_INTERLACE_ADAM7_PASSES;
   3535          break;
   3536 
   3537       default:
   3538          png_error(png_ptr, "unknown interlace type");
   3539    }
   3540 
   3541    /* Use direct access to info_ptr here because otherwise the simplified API
   3542     * would require PNG_EASY_ACCESS_SUPPORTED (just for this.)  Note this is
   3543     * checking the value after libpng expansions, not the original value in the
   3544     * PNG.
   3545     */
   3546    switch (info_ptr->bit_depth)
   3547    {
   3548       default:
   3549          png_error(png_ptr, "unexpected bit depth");
   3550          break;
   3551 
   3552       case 8:
   3553          /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
   3554           * to be removed by composing on a background: either the row if
   3555           * display->background is NULL or display->background->green if not.
   3556           * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
   3557           */
   3558          {
   3559             png_bytep first_row = png_voidcast(png_bytep, display->first_row);
   3560             ptrdiff_t step_row = display->row_bytes;
   3561 
   3562             for (pass = 0; pass < passes; ++pass)
   3563             {
   3564                png_bytep        row = png_voidcast(png_bytep,
   3565                                                    display->first_row);
   3566                unsigned int     startx, stepx, stepy;
   3567                png_uint_32      y;
   3568 
   3569                if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
   3570                {
   3571                   /* The row may be empty for a short image: */
   3572                   if (PNG_PASS_COLS(width, pass) == 0)
   3573                      continue;
   3574 
   3575                   startx = PNG_PASS_START_COL(pass);
   3576                   stepx = PNG_PASS_COL_OFFSET(pass);
   3577                   y = PNG_PASS_START_ROW(pass);
   3578                   stepy = PNG_PASS_ROW_OFFSET(pass);
   3579                }
   3580 
   3581                else
   3582                {
   3583                   y = 0;
   3584                   startx = 0;
   3585                   stepx = stepy = 1;
   3586                }
   3587 
   3588                if (display->background == NULL)
   3589                {
   3590                   for (; y<height; y += stepy)
   3591                   {
   3592                      png_bytep inrow = png_voidcast(png_bytep,
   3593                         display->local_row);
   3594                      png_bytep outrow = first_row + y * step_row;
   3595                      png_const_bytep end_row = outrow + width;
   3596 
   3597                      /* Read the row, which is packed: */
   3598                      png_read_row(png_ptr, inrow, NULL);
   3599 
   3600                      /* Now do the composition on each pixel in this row. */
   3601                      outrow += startx;
   3602                      for (; outrow < end_row; outrow += stepx)
   3603                      {
   3604                         png_byte alpha = inrow[1];
   3605 
   3606                         if (alpha > 0) /* else no change to the output */
   3607                         {
   3608                            png_uint_32 component = inrow[0];
   3609 
   3610                            if (alpha < 255) /* else just use component */
   3611                            {
   3612                               /* Since PNG_OPTIMIZED_ALPHA was not set it is
   3613                                * necessary to invert the sRGB transfer
   3614                                * function and multiply the alpha out.
   3615                                */
   3616                               component = png_sRGB_table[component] * alpha;
   3617                               component += png_sRGB_table[outrow[0]] *
   3618                                  (255-alpha);
   3619                               component = PNG_sRGB_FROM_LINEAR(component);
   3620                            }
   3621 
   3622                            outrow[0] = (png_byte)component;
   3623                         }
   3624 
   3625                         inrow += 2; /* gray and alpha channel */
   3626                      }
   3627                   }
   3628                }
   3629 
   3630                else /* constant background value */
   3631                {
   3632                   png_byte background8 = display->background->green;
   3633                   png_uint_16 background = png_sRGB_table[background8];
   3634 
   3635                   for (; y<height; y += stepy)
   3636                   {
   3637                      png_bytep inrow = png_voidcast(png_bytep,
   3638                         display->local_row);
   3639                      png_bytep outrow = first_row + y * step_row;
   3640                      png_const_bytep end_row = outrow + width;
   3641 
   3642                      /* Read the row, which is packed: */
   3643                      png_read_row(png_ptr, inrow, NULL);
   3644 
   3645                      /* Now do the composition on each pixel in this row. */
   3646                      outrow += startx;
   3647                      for (; outrow < end_row; outrow += stepx)
   3648                      {
   3649                         png_byte alpha = inrow[1];
   3650 
   3651                         if (alpha > 0) /* else use background */
   3652                         {
   3653                            png_uint_32 component = inrow[0];
   3654 
   3655                            if (alpha < 255) /* else just use component */
   3656                            {
   3657                               component = png_sRGB_table[component] * alpha;
   3658                               component += background * (255-alpha);
   3659                               component = PNG_sRGB_FROM_LINEAR(component);
   3660                            }
   3661 
   3662                            outrow[0] = (png_byte)component;
   3663                         }
   3664 
   3665                         else
   3666                            outrow[0] = background8;
   3667 
   3668                         inrow += 2; /* gray and alpha channel */
   3669                      }
   3670 
   3671                      row += display->row_bytes;
   3672                   }
   3673                }
   3674             }
   3675          }
   3676          break;
   3677 
   3678       case 16:
   3679          /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
   3680           * still be done and, maybe, the alpha channel removed.  This code also
   3681           * handles the alpha-first option.
   3682           */
   3683          {
   3684             png_uint_16p first_row = png_voidcast(png_uint_16p,
   3685                display->first_row);
   3686             /* The division by two is safe because the caller passed in a
   3687              * stride which was multiplied by 2 (below) to get row_bytes.
   3688              */
   3689             ptrdiff_t    step_row = display->row_bytes / 2;
   3690             int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
   3691             unsigned int outchannels = 1+preserve_alpha;
   3692             int swap_alpha = 0;
   3693 
   3694 #           ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
   3695                if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST))
   3696                   swap_alpha = 1;
   3697 #           endif
   3698 
   3699             for (pass = 0; pass < passes; ++pass)
   3700             {
   3701                unsigned int     startx, stepx, stepy;
   3702                png_uint_32      y;
   3703 
   3704                /* The 'x' start and step are adjusted to output components here.
   3705                 */
   3706                if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
   3707                {
   3708                   /* The row may be empty for a short image: */
   3709                   if (PNG_PASS_COLS(width, pass) == 0)
   3710                      continue;
   3711 
   3712                   startx = PNG_PASS_START_COL(pass) * outchannels;
   3713                   stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
   3714                   y = PNG_PASS_START_ROW(pass);
   3715                   stepy = PNG_PASS_ROW_OFFSET(pass);
   3716                }
   3717 
   3718                else
   3719                {
   3720                   y = 0;
   3721                   startx = 0;
   3722                   stepx = outchannels;
   3723                   stepy = 1;
   3724                }
   3725 
   3726                for (; y<height; y += stepy)
   3727                {
   3728                   png_const_uint_16p inrow;
   3729                   png_uint_16p outrow = first_row + y*step_row;
   3730                   png_uint_16p end_row = outrow + width * outchannels;
   3731 
   3732                   /* Read the row, which is packed: */
   3733                   png_read_row(png_ptr, png_voidcast(png_bytep,
   3734                      display->local_row), NULL);
   3735                   inrow = png_voidcast(png_const_uint_16p, display->local_row);
   3736 
   3737                   /* Now do the pre-multiplication on each pixel in this row.
   3738                    */
   3739                   outrow += startx;
   3740                   for (; outrow < end_row; outrow += stepx)
   3741                   {
   3742                      png_uint_32 component = inrow[0];
   3743                      png_uint_16 alpha = inrow[1];
   3744 
   3745                      if (alpha > 0) /* else 0 */
   3746                      {
   3747                         if (alpha < 65535) /* else just use component */
   3748                         {
   3749                            component *= alpha;
   3750                            component += 32767;
   3751                            component /= 65535;
   3752                         }
   3753                      }
   3754 
   3755                      else
   3756                         component = 0;
   3757 
   3758                      outrow[swap_alpha] = (png_uint_16)component;
   3759                      if (preserve_alpha)
   3760                         outrow[1 ^ swap_alpha] = alpha;
   3761 
   3762                      inrow += 2; /* components and alpha channel */
   3763                   }
   3764                }
   3765             }
   3766          }
   3767          break;
   3768    }
   3769 
   3770    return 1;
   3771 }
   3772 
   3773 /* The guts of png_image_finish_read as a png_safe_execute callback. */
   3774 static int
   3775 png_image_read_direct(png_voidp argument)
   3776 {
   3777    png_image_read_control *display = png_voidcast(png_image_read_control*,
   3778       argument);
   3779    png_imagep image = display->image;
   3780    png_structrp png_ptr = image->opaque->png_ptr;
   3781    png_inforp info_ptr = image->opaque->info_ptr;
   3782 
   3783    png_uint_32 format = image->format;
   3784    int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
   3785    int do_local_compose = 0;
   3786    int do_local_background = 0; /* to avoid double gamma correction bug */
   3787    int passes = 0;
   3788 
   3789    /* Add transforms to ensure the correct output format is produced then check
   3790     * that the required implementation support is there.  Always expand; always
   3791     * need 8 bits minimum, no palette and expanded tRNS.
   3792     */
   3793    png_set_expand(png_ptr);
   3794 
   3795    /* Now check the format to see if it was modified. */
   3796    {
   3797       png_uint_32 base_format = png_image_format(png_ptr) &
   3798          ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;
   3799       png_uint_32 change = format ^ base_format;
   3800       png_fixed_point output_gamma;
   3801       int mode; /* alpha mode */
   3802 
   3803       /* Do this first so that we have a record if rgb to gray is happening. */
   3804       if (change & PNG_FORMAT_FLAG_COLOR)
   3805       {
   3806          /* gray<->color transformation required. */
   3807          if (format & PNG_FORMAT_FLAG_COLOR)
   3808             png_set_gray_to_rgb(png_ptr);
   3809 
   3810          else
   3811          {
   3812             /* libpng can't do both rgb to gray and
   3813              * background/pre-multiplication if there is also significant gamma
   3814              * correction, because both operations require linear colors and
   3815              * the code only supports one transform doing the gamma correction.
   3816              * Handle this by doing the pre-multiplication or background
   3817              * operation in this code, if necessary.
   3818              *
   3819              * TODO: fix this by rewriting pngrtran.c (!)
   3820              *
   3821              * For the moment (given that fixing this in pngrtran.c is an
   3822              * enormous change) 'do_local_background' is used to indicate that
   3823              * the problem exists.
   3824              */
   3825             if (base_format & PNG_FORMAT_FLAG_ALPHA)
   3826                do_local_background = 1/*maybe*/;
   3827 
   3828             png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
   3829                PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
   3830          }
   3831 
   3832          change &= ~PNG_FORMAT_FLAG_COLOR;
   3833       }
   3834 
   3835       /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
   3836        */
   3837       {
   3838          png_fixed_point input_gamma_default;
   3839 
   3840          if ((base_format & PNG_FORMAT_FLAG_LINEAR) &&
   3841             (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
   3842             input_gamma_default = PNG_GAMMA_LINEAR;
   3843          else
   3844             input_gamma_default = PNG_DEFAULT_sRGB;
   3845 
   3846          /* Call png_set_alpha_mode to set the default for the input gamma; the
   3847           * output gamma is set by a second call below.
   3848           */
   3849          png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
   3850       }
   3851 
   3852       if (linear)
   3853       {
   3854          /* If there *is* an alpha channel in the input it must be multiplied
   3855           * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
   3856           */
   3857          if (base_format & PNG_FORMAT_FLAG_ALPHA)
   3858             mode = PNG_ALPHA_STANDARD; /* associated alpha */
   3859 
   3860          else
   3861             mode = PNG_ALPHA_PNG;
   3862 
   3863          output_gamma = PNG_GAMMA_LINEAR;
   3864       }
   3865 
   3866       else
   3867       {
   3868          mode = PNG_ALPHA_PNG;
   3869          output_gamma = PNG_DEFAULT_sRGB;
   3870       }
   3871 
   3872       /* If 'do_local_background' is set check for the presence of gamma
   3873        * correction; this is part of the work-round for the libpng bug
   3874        * described above.
   3875        *
   3876        * TODO: fix libpng and remove this.
   3877        */
   3878       if (do_local_background)
   3879       {
   3880          png_fixed_point gtest;
   3881 
   3882          /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
   3883           * gamma correction, the screen gamma hasn't been set on png_struct
   3884           * yet; it's set below.  png_struct::gamma, however, is set to the
   3885           * final value.
   3886           */
   3887          if (png_muldiv(&gtest, output_gamma, png_ptr->colorspace.gamma,
   3888                PNG_FP_1) && !png_gamma_significant(gtest))
   3889             do_local_background = 0;
   3890 
   3891          else if (mode == PNG_ALPHA_STANDARD)
   3892          {
   3893             do_local_background = 2/*required*/;
   3894             mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
   3895          }
   3896 
   3897          /* else leave as 1 for the checks below */
   3898       }
   3899 
   3900       /* If the bit-depth changes then handle that here. */
   3901       if (change & PNG_FORMAT_FLAG_LINEAR)
   3902       {
   3903          if (linear /*16-bit output*/)
   3904             png_set_expand_16(png_ptr);
   3905 
   3906          else /* 8-bit output */
   3907             png_set_scale_16(png_ptr);
   3908 
   3909          change &= ~PNG_FORMAT_FLAG_LINEAR;
   3910       }
   3911 
   3912       /* Now the background/alpha channel changes. */
   3913       if (change & PNG_FORMAT_FLAG_ALPHA)
   3914       {
   3915          /* Removing an alpha channel requires composition for the 8-bit
   3916           * formats; for the 16-bit it is already done, above, by the
   3917           * pre-multiplication and the channel just needs to be stripped.
   3918           */
   3919          if (base_format & PNG_FORMAT_FLAG_ALPHA)
   3920          {
   3921             /* If RGB->gray is happening the alpha channel must be left and the
   3922              * operation completed locally.
   3923              *
   3924              * TODO: fix libpng and remove this.
   3925              */
   3926             if (do_local_background)
   3927                do_local_background = 2/*required*/;
   3928 
   3929             /* 16-bit output: just remove the channel */
   3930             else if (linear) /* compose on black (well, pre-multiply) */
   3931                png_set_strip_alpha(png_ptr);
   3932 
   3933             /* 8-bit output: do an appropriate compose */
   3934             else if (display->background != NULL)
   3935             {
   3936                png_color_16 c;
   3937 
   3938                c.index = 0; /*unused*/
   3939                c.red = display->background->red;
   3940                c.green = display->background->green;
   3941                c.blue = display->background->blue;
   3942                c.gray = display->background->green;
   3943 
   3944                /* This is always an 8-bit sRGB value, using the 'green' channel
   3945                 * for gray is much better than calculating the luminance here;
   3946                 * we can get off-by-one errors in that calculation relative to
   3947                 * the app expectations and that will show up in transparent
   3948                 * pixels.
   3949                 */
   3950                png_set_background_fixed(png_ptr, &c,
   3951                   PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
   3952                   0/*gamma: not used*/);
   3953             }
   3954 
   3955             else /* compose on row: implemented below. */
   3956             {
   3957                do_local_compose = 1;
   3958                /* This leaves the alpha channel in the output, so it has to be
   3959                 * removed by the code below.  Set the encoding to the 'OPTIMIZE'
   3960                 * one so the code only has to hack on the pixels that require
   3961                 * composition.
   3962                 */
   3963                mode = PNG_ALPHA_OPTIMIZED;
   3964             }
   3965          }
   3966 
   3967          else /* output needs an alpha channel */
   3968          {
   3969             /* This is tricky because it happens before the swap operation has
   3970              * been accomplished; however, the swap does *not* swap the added
   3971              * alpha channel (weird API), so it must be added in the correct
   3972              * place.
   3973              */
   3974             png_uint_32 filler; /* opaque filler */
   3975             int where;
   3976 
   3977             if (linear)
   3978                filler = 65535;
   3979 
   3980             else
   3981                filler = 255;
   3982 
   3983 #           ifdef PNG_FORMAT_AFIRST_SUPPORTED
   3984                if (format & PNG_FORMAT_FLAG_AFIRST)
   3985                {
   3986                   where = PNG_FILLER_BEFORE;
   3987                   change &= ~PNG_FORMAT_FLAG_AFIRST;
   3988                }
   3989 
   3990                else
   3991 #           endif
   3992                where = PNG_FILLER_AFTER;
   3993 
   3994             png_set_add_alpha(png_ptr, filler, where);
   3995          }
   3996 
   3997          /* This stops the (irrelevant) call to swap_alpha below. */
   3998          change &= ~PNG_FORMAT_FLAG_ALPHA;
   3999       }
   4000 
   4001       /* Now set the alpha mode correctly; this is always done, even if there is
   4002        * no alpha channel in either the input or the output because it correctly
   4003        * sets the output gamma.
   4004        */
   4005       png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
   4006 
   4007 #     ifdef PNG_FORMAT_BGR_SUPPORTED
   4008          if (change & PNG_FORMAT_FLAG_BGR)
   4009          {
   4010             /* Check only the output format; PNG is never BGR; don't do this if
   4011              * the output is gray, but fix up the 'format' value in that case.
   4012              */
   4013             if (format & PNG_FORMAT_FLAG_COLOR)
   4014                png_set_bgr(png_ptr);
   4015 
   4016             else
   4017                format &= ~PNG_FORMAT_FLAG_BGR;
   4018 
   4019             change &= ~PNG_FORMAT_FLAG_BGR;
   4020          }
   4021 #     endif
   4022 
   4023 #     ifdef PNG_FORMAT_AFIRST_SUPPORTED
   4024          if (change & PNG_FORMAT_FLAG_AFIRST)
   4025          {
   4026             /* Only relevant if there is an alpha channel - it's particularly
   4027              * important to handle this correctly because do_local_compose may
   4028              * be set above and then libpng will keep the alpha channel for this
   4029              * code to remove.
   4030              */
   4031             if (format & PNG_FORMAT_FLAG_ALPHA)
   4032             {
   4033                /* Disable this if doing a local background,
   4034                 * TODO: remove this when local background is no longer required.
   4035                 */
   4036                if (do_local_background != 2)
   4037                   png_set_swap_alpha(png_ptr);
   4038             }
   4039 
   4040             else
   4041                format &= ~PNG_FORMAT_FLAG_AFIRST;
   4042 
   4043             change &= ~PNG_FORMAT_FLAG_AFIRST;
   4044          }
   4045 #     endif
   4046 
   4047       /* If the *output* is 16-bit then we need to check for a byte-swap on this
   4048        * architecture.
   4049        */
   4050       if (linear)
   4051       {
   4052          PNG_CONST png_uint_16 le = 0x0001;
   4053 
   4054          if (*(png_const_bytep)&le)
   4055             png_set_swap(png_ptr);
   4056       }
   4057 
   4058       /* If change is not now 0 some transformation is missing - error out. */
   4059       if (change)
   4060          png_error(png_ptr, "png_read_image: unsupported transformation");
   4061    }
   4062 
   4063    PNG_SKIP_CHUNKS(png_ptr);
   4064 
   4065    /* Update the 'info' structure and make sure the result is as required; first
   4066     * make sure to turn on the interlace handling if it will be required
   4067     * (because it can't be turned on *after* the call to png_read_update_info!)
   4068     *
   4069     * TODO: remove the do_local_background fixup below.
   4070     */
   4071    if (!do_local_compose && do_local_background != 2)
   4072       passes = png_set_interlace_handling(png_ptr);
   4073 
   4074    png_read_update_info(png_ptr, info_ptr);
   4075 
   4076    {
   4077       png_uint_32 info_format = 0;
   4078 
   4079       if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
   4080          info_format |= PNG_FORMAT_FLAG_COLOR;
   4081 
   4082       if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
   4083       {
   4084          /* do_local_compose removes this channel below. */
   4085          if (!do_local_compose)
   4086          {
   4087             /* do_local_background does the same if required. */
   4088             if (do_local_background != 2 ||
   4089                (format & PNG_FORMAT_FLAG_ALPHA) != 0)
   4090                info_format |= PNG_FORMAT_FLAG_ALPHA;
   4091          }
   4092       }
   4093 
   4094       else if (do_local_compose) /* internal error */
   4095          png_error(png_ptr, "png_image_read: alpha channel lost");
   4096 
   4097       if (info_ptr->bit_depth == 16)
   4098          info_format |= PNG_FORMAT_FLAG_LINEAR;
   4099 
   4100 #     ifdef PNG_FORMAT_BGR_SUPPORTED
   4101          if (png_ptr->transformations & PNG_BGR)
   4102             info_format |= PNG_FORMAT_FLAG_BGR;
   4103 #     endif
   4104 
   4105 #     ifdef PNG_FORMAT_AFIRST_SUPPORTED
   4106          if (do_local_background == 2)
   4107          {
   4108             if (format & PNG_FORMAT_FLAG_AFIRST)
   4109                info_format |= PNG_FORMAT_FLAG_AFIRST;
   4110          }
   4111 
   4112          if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
   4113             ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
   4114             (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
   4115          {
   4116             if (do_local_background == 2)
   4117                png_error(png_ptr, "unexpected alpha swap transformation");
   4118 
   4119             info_format |= PNG_FORMAT_FLAG_AFIRST;
   4120          }
   4121 #     endif
   4122 
   4123       /* This is actually an internal error. */
   4124       if (info_format != format)
   4125          png_error(png_ptr, "png_read_image: invalid transformations");
   4126    }
   4127 
   4128    /* Now read the rows.  If do_local_compose is set then it is necessary to use
   4129     * a local row buffer.  The output will be GA, RGBA or BGRA and must be
   4130     * converted to G, RGB or BGR as appropriate.  The 'local_row' member of the
   4131     * display acts as a flag.
   4132     */
   4133    {
   4134       png_voidp first_row = display->buffer;
   4135       ptrdiff_t row_bytes = display->row_stride;
   4136 
   4137       if (linear)
   4138          row_bytes *= 2;
   4139 
   4140       /* The following expression is designed to work correctly whether it gives
   4141        * a signed or an unsigned result.
   4142        */
   4143       if (row_bytes < 0)
   4144       {
   4145          char *ptr = png_voidcast(char*, first_row);
   4146          ptr += (image->height-1) * (-row_bytes);
   4147          first_row = png_voidcast(png_voidp, ptr);
   4148       }
   4149 
   4150       display->first_row = first_row;
   4151       display->row_bytes = row_bytes;
   4152    }
   4153 
   4154    if (do_local_compose)
   4155    {
   4156       int result;
   4157       png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
   4158 
   4159       display->local_row = row;
   4160       result = png_safe_execute(image, png_image_read_composite, display);
   4161       display->local_row = NULL;
   4162       png_free(png_ptr, row);
   4163 
   4164       return result;
   4165    }
   4166 
   4167    else if (do_local_background == 2)
   4168    {
   4169       int result;
   4170       png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
   4171 
   4172       display->local_row = row;
   4173       result = png_safe_execute(image, png_image_read_background, display);
   4174       display->local_row = NULL;
   4175       png_free(png_ptr, row);
   4176 
   4177       return result;
   4178    }
   4179 
   4180    else
   4181    {
   4182       png_alloc_size_t row_bytes = display->row_bytes;
   4183 
   4184       while (--passes >= 0)
   4185       {
   4186          png_uint_32      y = image->height;
   4187          png_bytep        row = png_voidcast(png_bytep, display->first_row);
   4188 
   4189          while (y-- > 0)
   4190          {
   4191             png_read_row(png_ptr, row, NULL);
   4192             row += row_bytes;
   4193          }
   4194       }
   4195 
   4196       return 1;
   4197    }
   4198 }
   4199 
   4200 int PNGAPI
   4201 png_image_finish_read(png_imagep image, png_const_colorp background,
   4202    void *buffer, png_int_32 row_stride, void *colormap)
   4203 {
   4204    if (image != NULL && image->version == PNG_IMAGE_VERSION)
   4205    {
   4206       png_uint_32 check;
   4207 
   4208       if (row_stride == 0)
   4209          row_stride = PNG_IMAGE_ROW_STRIDE(*image);
   4210 
   4211       if (row_stride < 0)
   4212          check = -row_stride;
   4213 
   4214       else
   4215          check = row_stride;
   4216 
   4217       if (image->opaque != NULL && buffer != NULL &&
   4218          check >= PNG_IMAGE_ROW_STRIDE(*image))
   4219       {
   4220          if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
   4221             (image->colormap_entries > 0 && colormap != NULL))
   4222          {
   4223             int result;
   4224             png_image_read_control display;
   4225 
   4226             memset(&display, 0, (sizeof display));
   4227             display.image = image;
   4228             display.buffer = buffer;
   4229             display.row_stride = row_stride;
   4230             display.colormap = colormap;
   4231             display.background = background;
   4232             display.local_row = NULL;
   4233 
   4234             /* Choose the correct 'end' routine; for the color-map case all the
   4235              * setup has already been done.
   4236              */
   4237             if (image->format & PNG_FORMAT_FLAG_COLORMAP)
   4238                result =
   4239                   png_safe_execute(image, png_image_read_colormap, &display) &&
   4240                   png_safe_execute(image, png_image_read_colormapped, &display);
   4241 
   4242             else
   4243                result =
   4244                   png_safe_execute(image, png_image_read_direct, &display);
   4245 
   4246             png_image_free(image);
   4247             return result;
   4248          }
   4249 
   4250          else
   4251             return png_image_error(image,
   4252                "png_image_finish_read[color-map]: no color-map");
   4253       }
   4254 
   4255       else
   4256          return png_image_error(image,
   4257             "png_image_finish_read: invalid argument");
   4258    }
   4259 
   4260    else if (image != NULL)
   4261       return png_image_error(image,
   4262          "png_image_finish_read: damaged PNG_IMAGE_VERSION");
   4263 
   4264    return 0;
   4265 }
   4266 
   4267 #endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
   4268 #endif /* PNG_READ_SUPPORTED */
   4269