Home | History | Annotate | Download | only in lpng_v163
      1 
      2 /* pngwrite.c - general routines to write a PNG file
      3  *
      4  * Last changed in libpng 1.6.2 [April 25, 2013]
      5  * Copyright (c) 1998-2013 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 #include "pngpriv.h"
     14 #if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
     15 #  include <errno.h>
     16 #endif
     17 
     18 #ifdef PNG_WRITE_SUPPORTED
     19 
     20 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
     21 /* Write out all the unknown chunks for the current given location */
     22 static void
     23 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
     24    unsigned int where)
     25 {
     26    if (info_ptr->unknown_chunks_num)
     27    {
     28       png_const_unknown_chunkp up;
     29 
     30       png_debug(5, "writing extra chunks");
     31 
     32       for (up = info_ptr->unknown_chunks;
     33            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
     34            ++up)
     35          if (up->location & where)
     36       {
     37          /* If per-chunk unknown chunk handling is enabled use it, otherwise
     38           * just write the chunks the application has set.
     39           */
     40 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
     41          int keep = png_handle_as_unknown(png_ptr, up->name);
     42 
     43          /* NOTE: this code is radically different from the read side in the
     44           * matter of handling an ancillary unknown chunk.  In the read side
     45           * the default behavior is to discard it, in the code below the default
     46           * behavior is to write it.  Critical chunks are, however, only
     47           * written if explicitly listed or if the default is set to write all
     48           * unknown chunks.
     49           *
     50           * The default handling is also slightly weird - it is not possible to
     51           * stop the writing of all unsafe-to-copy chunks!
     52           *
     53           * TODO: REVIEW: this would seem to be a bug.
     54           */
     55          if (keep != PNG_HANDLE_CHUNK_NEVER &&
     56              ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
     57               keep == PNG_HANDLE_CHUNK_ALWAYS ||
     58               (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
     59                png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
     60 #endif
     61          {
     62             /* TODO: review, what is wrong with a zero length unknown chunk? */
     63             if (up->size == 0)
     64                png_warning(png_ptr, "Writing zero-length unknown chunk");
     65 
     66             png_write_chunk(png_ptr, up->name, up->data, up->size);
     67          }
     68       }
     69    }
     70 }
     71 #endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */
     72 
     73 /* Writes all the PNG information.  This is the suggested way to use the
     74  * library.  If you have a new chunk to add, make a function to write it,
     75  * and put it in the correct location here.  If you want the chunk written
     76  * after the image data, put it in png_write_end().  I strongly encourage
     77  * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
     78  * the chunk, as that will keep the code from breaking if you want to just
     79  * write a plain PNG file.  If you have long comments, I suggest writing
     80  * them in png_write_end(), and compressing them.
     81  */
     82 void PNGAPI
     83 png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
     84 {
     85    png_debug(1, "in png_write_info_before_PLTE");
     86 
     87    if (png_ptr == NULL || info_ptr == NULL)
     88       return;
     89 
     90    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
     91    {
     92    /* Write PNG signature */
     93    png_write_sig(png_ptr);
     94 
     95 #ifdef PNG_MNG_FEATURES_SUPPORTED
     96    if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
     97        (png_ptr->mng_features_permitted))
     98    {
     99       png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
    100       png_ptr->mng_features_permitted = 0;
    101    }
    102 #endif
    103 
    104    /* Write IHDR information. */
    105    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
    106        info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
    107        info_ptr->filter_type,
    108 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
    109        info_ptr->interlace_type
    110 #else
    111        0
    112 #endif
    113       );
    114 
    115    /* The rest of these check to see if the valid field has the appropriate
    116     * flag set, and if it does, writes the chunk.
    117     *
    118     * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
    119     * the chunks will be written if the WRITE routine is there and information
    120     * is available in the COLORSPACE.  (See png_colorspace_sync_info in png.c
    121     * for where the valid flags get set.)
    122     *
    123     * Under certain circumstances the colorspace can be invalidated without
    124     * syncing the info_struct 'valid' flags; this happens if libpng detects and
    125     * error and calls png_error while the color space is being set, yet the
    126     * application continues writing the PNG.  So check the 'invalid' flag here
    127     * too.
    128     */
    129 #ifdef PNG_GAMMA_SUPPORTED
    130 #  ifdef PNG_WRITE_gAMA_SUPPORTED
    131       if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
    132          (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) &&
    133          (info_ptr->valid & PNG_INFO_gAMA))
    134          png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
    135 #  endif
    136 #endif
    137 
    138 #ifdef PNG_COLORSPACE_SUPPORTED
    139    /* Write only one of sRGB or an ICC profile.  If a profile was supplied
    140     * and it matches one of the known sRGB ones issue a warning.
    141     */
    142 #  ifdef PNG_WRITE_iCCP_SUPPORTED
    143       if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
    144          (info_ptr->valid & PNG_INFO_iCCP))
    145       {
    146 #        ifdef PNG_WRITE_sRGB_SUPPORTED
    147             if (info_ptr->valid & PNG_INFO_sRGB)
    148                png_app_warning(png_ptr,
    149                   "profile matches sRGB but writing iCCP instead");
    150 #        endif
    151 
    152          png_write_iCCP(png_ptr, info_ptr->iccp_name,
    153             info_ptr->iccp_profile);
    154       }
    155 #     ifdef PNG_WRITE_sRGB_SUPPORTED
    156          else
    157 #     endif
    158 #  endif
    159 
    160 #  ifdef PNG_WRITE_sRGB_SUPPORTED
    161       if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
    162          (info_ptr->valid & PNG_INFO_sRGB))
    163          png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
    164 #  endif /* WRITE_sRGB */
    165 #endif /* COLORSPACE */
    166 
    167 #ifdef PNG_WRITE_sBIT_SUPPORTED
    168    if (info_ptr->valid & PNG_INFO_sBIT)
    169       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
    170 #endif
    171 
    172 #ifdef PNG_COLORSPACE_SUPPORTED
    173 #  ifdef PNG_WRITE_cHRM_SUPPORTED
    174       if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
    175          (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) &&
    176          (info_ptr->valid & PNG_INFO_cHRM))
    177          png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
    178 #  endif
    179 #endif
    180 
    181 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
    182       write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
    183 #endif
    184 
    185       png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
    186    }
    187 }
    188 
    189 void PNGAPI
    190 png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
    191 {
    192 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
    193    int i;
    194 #endif
    195 
    196    png_debug(1, "in png_write_info");
    197 
    198    if (png_ptr == NULL || info_ptr == NULL)
    199       return;
    200 
    201    png_write_info_before_PLTE(png_ptr, info_ptr);
    202 
    203    if (info_ptr->valid & PNG_INFO_PLTE)
    204       png_write_PLTE(png_ptr, info_ptr->palette,
    205           (png_uint_32)info_ptr->num_palette);
    206 
    207    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    208       png_error(png_ptr, "Valid palette required for paletted images");
    209 
    210 #ifdef PNG_WRITE_tRNS_SUPPORTED
    211    if (info_ptr->valid & PNG_INFO_tRNS)
    212    {
    213 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
    214       /* Invert the alpha channel (in tRNS) */
    215       if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
    216           info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    217       {
    218          int j;
    219          for (j = 0; j<(int)info_ptr->num_trans; j++)
    220             info_ptr->trans_alpha[j] =
    221                (png_byte)(255 - info_ptr->trans_alpha[j]);
    222       }
    223 #endif
    224       png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
    225           info_ptr->num_trans, info_ptr->color_type);
    226    }
    227 #endif
    228 #ifdef PNG_WRITE_bKGD_SUPPORTED
    229    if (info_ptr->valid & PNG_INFO_bKGD)
    230       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
    231 #endif
    232 
    233 #ifdef PNG_WRITE_hIST_SUPPORTED
    234    if (info_ptr->valid & PNG_INFO_hIST)
    235       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
    236 #endif
    237 
    238 #ifdef PNG_WRITE_oFFs_SUPPORTED
    239    if (info_ptr->valid & PNG_INFO_oFFs)
    240       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
    241           info_ptr->offset_unit_type);
    242 #endif
    243 
    244 #ifdef PNG_WRITE_pCAL_SUPPORTED
    245    if (info_ptr->valid & PNG_INFO_pCAL)
    246       png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
    247           info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
    248           info_ptr->pcal_units, info_ptr->pcal_params);
    249 #endif
    250 
    251 #ifdef PNG_WRITE_sCAL_SUPPORTED
    252    if (info_ptr->valid & PNG_INFO_sCAL)
    253       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
    254           info_ptr->scal_s_width, info_ptr->scal_s_height);
    255 #endif /* sCAL */
    256 
    257 #ifdef PNG_WRITE_pHYs_SUPPORTED
    258    if (info_ptr->valid & PNG_INFO_pHYs)
    259       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
    260           info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
    261 #endif /* pHYs */
    262 
    263 #ifdef PNG_WRITE_tIME_SUPPORTED
    264    if (info_ptr->valid & PNG_INFO_tIME)
    265    {
    266       png_write_tIME(png_ptr, &(info_ptr->mod_time));
    267       png_ptr->mode |= PNG_WROTE_tIME;
    268    }
    269 #endif /* tIME */
    270 
    271 #ifdef PNG_WRITE_sPLT_SUPPORTED
    272    if (info_ptr->valid & PNG_INFO_sPLT)
    273       for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
    274          png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
    275 #endif /* sPLT */
    276 
    277 #ifdef PNG_WRITE_TEXT_SUPPORTED
    278    /* Check to see if we need to write text chunks */
    279    for (i = 0; i < info_ptr->num_text; i++)
    280    {
    281       png_debug2(2, "Writing header text chunk %d, type %d", i,
    282           info_ptr->text[i].compression);
    283       /* An internationalized chunk? */
    284       if (info_ptr->text[i].compression > 0)
    285       {
    286 #ifdef PNG_WRITE_iTXt_SUPPORTED
    287          /* Write international chunk */
    288          png_write_iTXt(png_ptr,
    289              info_ptr->text[i].compression,
    290              info_ptr->text[i].key,
    291              info_ptr->text[i].lang,
    292              info_ptr->text[i].lang_key,
    293              info_ptr->text[i].text);
    294 #else
    295           png_warning(png_ptr, "Unable to write international text");
    296 #endif
    297           /* Mark this chunk as written */
    298           info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
    299       }
    300 
    301       /* If we want a compressed text chunk */
    302       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
    303       {
    304 #ifdef PNG_WRITE_zTXt_SUPPORTED
    305          /* Write compressed chunk */
    306          png_write_zTXt(png_ptr, info_ptr->text[i].key,
    307              info_ptr->text[i].text, 0,
    308              info_ptr->text[i].compression);
    309 #else
    310          png_warning(png_ptr, "Unable to write compressed text");
    311 #endif
    312          /* Mark this chunk as written */
    313          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
    314       }
    315 
    316       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
    317       {
    318 #ifdef PNG_WRITE_tEXt_SUPPORTED
    319          /* Write uncompressed chunk */
    320          png_write_tEXt(png_ptr, info_ptr->text[i].key,
    321              info_ptr->text[i].text,
    322              0);
    323          /* Mark this chunk as written */
    324          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
    325 #else
    326          /* Can't get here */
    327          png_warning(png_ptr, "Unable to write uncompressed text");
    328 #endif
    329       }
    330    }
    331 #endif /* tEXt */
    332 
    333 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
    334    write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
    335 #endif
    336 }
    337 
    338 /* Writes the end of the PNG file.  If you don't want to write comments or
    339  * time information, you can pass NULL for info.  If you already wrote these
    340  * in png_write_info(), do not write them again here.  If you have long
    341  * comments, I suggest writing them here, and compressing them.
    342  */
    343 void PNGAPI
    344 png_write_end(png_structrp png_ptr, png_inforp info_ptr)
    345 {
    346    png_debug(1, "in png_write_end");
    347 
    348    if (png_ptr == NULL)
    349       return;
    350 
    351    if (!(png_ptr->mode & PNG_HAVE_IDAT))
    352       png_error(png_ptr, "No IDATs written into file");
    353 
    354 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
    355    if (png_ptr->num_palette_max > png_ptr->num_palette)
    356       png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
    357 #endif
    358 
    359    /* See if user wants us to write information chunks */
    360    if (info_ptr != NULL)
    361    {
    362 #ifdef PNG_WRITE_TEXT_SUPPORTED
    363       int i; /* local index variable */
    364 #endif
    365 #ifdef PNG_WRITE_tIME_SUPPORTED
    366       /* Check to see if user has supplied a time chunk */
    367       if ((info_ptr->valid & PNG_INFO_tIME) &&
    368           !(png_ptr->mode & PNG_WROTE_tIME))
    369          png_write_tIME(png_ptr, &(info_ptr->mod_time));
    370 
    371 #endif
    372 #ifdef PNG_WRITE_TEXT_SUPPORTED
    373       /* Loop through comment chunks */
    374       for (i = 0; i < info_ptr->num_text; i++)
    375       {
    376          png_debug2(2, "Writing trailer text chunk %d, type %d", i,
    377             info_ptr->text[i].compression);
    378          /* An internationalized chunk? */
    379          if (info_ptr->text[i].compression > 0)
    380          {
    381 #ifdef PNG_WRITE_iTXt_SUPPORTED
    382             /* Write international chunk */
    383             png_write_iTXt(png_ptr,
    384                 info_ptr->text[i].compression,
    385                 info_ptr->text[i].key,
    386                 info_ptr->text[i].lang,
    387                 info_ptr->text[i].lang_key,
    388                 info_ptr->text[i].text);
    389 #else
    390             png_warning(png_ptr, "Unable to write international text");
    391 #endif
    392             /* Mark this chunk as written */
    393             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
    394          }
    395 
    396          else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
    397          {
    398 #ifdef PNG_WRITE_zTXt_SUPPORTED
    399             /* Write compressed chunk */
    400             png_write_zTXt(png_ptr, info_ptr->text[i].key,
    401                 info_ptr->text[i].text, 0,
    402                 info_ptr->text[i].compression);
    403 #else
    404             png_warning(png_ptr, "Unable to write compressed text");
    405 #endif
    406             /* Mark this chunk as written */
    407             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
    408          }
    409 
    410          else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
    411          {
    412 #ifdef PNG_WRITE_tEXt_SUPPORTED
    413             /* Write uncompressed chunk */
    414             png_write_tEXt(png_ptr, info_ptr->text[i].key,
    415                 info_ptr->text[i].text, 0);
    416 #else
    417             png_warning(png_ptr, "Unable to write uncompressed text");
    418 #endif
    419 
    420             /* Mark this chunk as written */
    421             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
    422          }
    423       }
    424 #endif
    425 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
    426       write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
    427 #endif
    428    }
    429 
    430    png_ptr->mode |= PNG_AFTER_IDAT;
    431 
    432    /* Write end of PNG file */
    433    png_write_IEND(png_ptr);
    434    /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
    435     * and restored again in libpng-1.2.30, may cause some applications that
    436     * do not set png_ptr->output_flush_fn to crash.  If your application
    437     * experiences a problem, please try building libpng with
    438     * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
    439     * png-mng-implement at lists.sf.net .
    440     */
    441 #ifdef PNG_WRITE_FLUSH_SUPPORTED
    442 #  ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
    443    png_flush(png_ptr);
    444 #  endif
    445 #endif
    446 }
    447 
    448 #ifdef PNG_CONVERT_tIME_SUPPORTED
    449 void PNGAPI
    450 png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
    451 {
    452    png_debug(1, "in png_convert_from_struct_tm");
    453 
    454    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
    455    ptime->month = (png_byte)(ttime->tm_mon + 1);
    456    ptime->day = (png_byte)ttime->tm_mday;
    457    ptime->hour = (png_byte)ttime->tm_hour;
    458    ptime->minute = (png_byte)ttime->tm_min;
    459    ptime->second = (png_byte)ttime->tm_sec;
    460 }
    461 
    462 void PNGAPI
    463 png_convert_from_time_t(png_timep ptime, time_t ttime)
    464 {
    465    struct tm *tbuf;
    466 
    467    png_debug(1, "in png_convert_from_time_t");
    468 
    469    tbuf = gmtime(&ttime);
    470    png_convert_from_struct_tm(ptime, tbuf);
    471 }
    472 #endif
    473 
    474 /* Initialize png_ptr structure, and allocate any memory needed */
    475 PNG_FUNCTION(png_structp,PNGAPI
    476 png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
    477     png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
    478 {
    479 #ifndef PNG_USER_MEM_SUPPORTED
    480    png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
    481       error_fn, warn_fn, NULL, NULL, NULL);
    482 #else
    483    return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
    484        warn_fn, NULL, NULL, NULL);
    485 }
    486 
    487 /* Alternate initialize png_ptr structure, and allocate any memory needed */
    488 PNG_FUNCTION(png_structp,PNGAPI
    489 png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
    490     png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
    491     png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
    492 {
    493    png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
    494       error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
    495 #endif /* PNG_USER_MEM_SUPPORTED */
    496    if (png_ptr != NULL)
    497    {
    498       /* Set the zlib control values to defaults; they can be overridden by the
    499        * application after the struct has been created.
    500        */
    501       png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
    502 
    503       /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
    504        * pngwutil.c defaults it according to whether or not filters will be
    505        * used, and ignores this setting.
    506        */
    507       png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
    508       png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
    509       png_ptr->zlib_mem_level = 8;
    510       png_ptr->zlib_window_bits = 15;
    511       png_ptr->zlib_method = 8;
    512 
    513 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
    514       png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
    515       png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
    516       png_ptr->zlib_text_mem_level = 8;
    517       png_ptr->zlib_text_window_bits = 15;
    518       png_ptr->zlib_text_method = 8;
    519 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
    520 
    521       /* This is a highly dubious configuration option; by default it is off,
    522        * but it may be appropriate for private builds that are testing
    523        * extensions not conformant to the current specification, or of
    524        * applications that must not fail to write at all costs!
    525        */
    526 #ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
    527       png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
    528       /* In stable builds only warn if an application error can be completely
    529        * handled.
    530        */
    531 #endif
    532 
    533       /* App warnings are warnings in release (or release candidate) builds but
    534        * are errors during development.
    535        */
    536 #if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
    537       png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
    538 #endif
    539 
    540       /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
    541        * do it itself) avoiding setting the default function if it is not
    542        * required.
    543        */
    544       png_set_write_fn(png_ptr, NULL, NULL, NULL);
    545    }
    546 
    547    return png_ptr;
    548 }
    549 
    550 
    551 /* Write a few rows of image data.  If the image is interlaced,
    552  * either you will have to write the 7 sub images, or, if you
    553  * have called png_set_interlace_handling(), you will have to
    554  * "write" the image seven times.
    555  */
    556 void PNGAPI
    557 png_write_rows(png_structrp png_ptr, png_bytepp row,
    558     png_uint_32 num_rows)
    559 {
    560    png_uint_32 i; /* row counter */
    561    png_bytepp rp; /* row pointer */
    562 
    563    png_debug(1, "in png_write_rows");
    564 
    565    if (png_ptr == NULL)
    566       return;
    567 
    568    /* Loop through the rows */
    569    for (i = 0, rp = row; i < num_rows; i++, rp++)
    570    {
    571       png_write_row(png_ptr, *rp);
    572    }
    573 }
    574 
    575 /* Write the image.  You only need to call this function once, even
    576  * if you are writing an interlaced image.
    577  */
    578 void PNGAPI
    579 png_write_image(png_structrp png_ptr, png_bytepp image)
    580 {
    581    png_uint_32 i; /* row index */
    582    int pass, num_pass; /* pass variables */
    583    png_bytepp rp; /* points to current row */
    584 
    585    if (png_ptr == NULL)
    586       return;
    587 
    588    png_debug(1, "in png_write_image");
    589 
    590 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
    591    /* Initialize interlace handling.  If image is not interlaced,
    592     * this will set pass to 1
    593     */
    594    num_pass = png_set_interlace_handling(png_ptr);
    595 #else
    596    num_pass = 1;
    597 #endif
    598    /* Loop through passes */
    599    for (pass = 0; pass < num_pass; pass++)
    600    {
    601       /* Loop through image */
    602       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
    603       {
    604          png_write_row(png_ptr, *rp);
    605       }
    606    }
    607 }
    608 
    609 /* Called by user to write a row of image data */
    610 void PNGAPI
    611 png_write_row(png_structrp png_ptr, png_const_bytep row)
    612 {
    613    /* 1.5.6: moved from png_struct to be a local structure: */
    614    png_row_info row_info;
    615 
    616    if (png_ptr == NULL)
    617       return;
    618 
    619    png_debug2(1, "in png_write_row (row %u, pass %d)",
    620       png_ptr->row_number, png_ptr->pass);
    621 
    622    /* Initialize transformations and other stuff if first time */
    623    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
    624    {
    625       /* Make sure we wrote the header info */
    626       if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
    627          png_error(png_ptr,
    628              "png_write_info was never called before png_write_row");
    629 
    630       /* Check for transforms that have been set but were defined out */
    631 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
    632       if (png_ptr->transformations & PNG_INVERT_MONO)
    633          png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
    634 #endif
    635 
    636 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
    637       if (png_ptr->transformations & PNG_FILLER)
    638          png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
    639 #endif
    640 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
    641     defined(PNG_READ_PACKSWAP_SUPPORTED)
    642       if (png_ptr->transformations & PNG_PACKSWAP)
    643          png_warning(png_ptr,
    644              "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
    645 #endif
    646 
    647 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
    648       if (png_ptr->transformations & PNG_PACK)
    649          png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
    650 #endif
    651 
    652 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
    653       if (png_ptr->transformations & PNG_SHIFT)
    654          png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
    655 #endif
    656 
    657 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
    658       if (png_ptr->transformations & PNG_BGR)
    659          png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
    660 #endif
    661 
    662 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
    663       if (png_ptr->transformations & PNG_SWAP_BYTES)
    664          png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
    665 #endif
    666 
    667       png_write_start_row(png_ptr);
    668    }
    669 
    670 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
    671    /* If interlaced and not interested in row, return */
    672    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
    673    {
    674       switch (png_ptr->pass)
    675       {
    676          case 0:
    677             if (png_ptr->row_number & 0x07)
    678             {
    679                png_write_finish_row(png_ptr);
    680                return;
    681             }
    682             break;
    683 
    684          case 1:
    685             if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
    686             {
    687                png_write_finish_row(png_ptr);
    688                return;
    689             }
    690             break;
    691 
    692          case 2:
    693             if ((png_ptr->row_number & 0x07) != 4)
    694             {
    695                png_write_finish_row(png_ptr);
    696                return;
    697             }
    698             break;
    699 
    700          case 3:
    701             if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
    702             {
    703                png_write_finish_row(png_ptr);
    704                return;
    705             }
    706             break;
    707 
    708          case 4:
    709             if ((png_ptr->row_number & 0x03) != 2)
    710             {
    711                png_write_finish_row(png_ptr);
    712                return;
    713             }
    714             break;
    715 
    716          case 5:
    717             if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
    718             {
    719                png_write_finish_row(png_ptr);
    720                return;
    721             }
    722             break;
    723 
    724          case 6:
    725             if (!(png_ptr->row_number & 0x01))
    726             {
    727                png_write_finish_row(png_ptr);
    728                return;
    729             }
    730             break;
    731 
    732          default: /* error: ignore it */
    733             break;
    734       }
    735    }
    736 #endif
    737 
    738    /* Set up row info for transformations */
    739    row_info.color_type = png_ptr->color_type;
    740    row_info.width = png_ptr->usr_width;
    741    row_info.channels = png_ptr->usr_channels;
    742    row_info.bit_depth = png_ptr->usr_bit_depth;
    743    row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
    744    row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
    745 
    746    png_debug1(3, "row_info->color_type = %d", row_info.color_type);
    747    png_debug1(3, "row_info->width = %u", row_info.width);
    748    png_debug1(3, "row_info->channels = %d", row_info.channels);
    749    png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
    750    png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
    751    png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
    752 
    753    /* Copy user's row into buffer, leaving room for filter byte. */
    754    memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
    755 
    756 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
    757    /* Handle interlacing */
    758    if (png_ptr->interlaced && png_ptr->pass < 6 &&
    759        (png_ptr->transformations & PNG_INTERLACE))
    760    {
    761       png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
    762       /* This should always get caught above, but still ... */
    763       if (!(row_info.width))
    764       {
    765          png_write_finish_row(png_ptr);
    766          return;
    767       }
    768    }
    769 #endif
    770 
    771 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
    772    /* Handle other transformations */
    773    if (png_ptr->transformations)
    774       png_do_write_transformations(png_ptr, &row_info);
    775 #endif
    776 
    777    /* At this point the row_info pixel depth must match the 'transformed' depth,
    778     * which is also the output depth.
    779     */
    780    if (row_info.pixel_depth != png_ptr->pixel_depth ||
    781       row_info.pixel_depth != png_ptr->transformed_pixel_depth)
    782       png_error(png_ptr, "internal write transform logic error");
    783 
    784 #ifdef PNG_MNG_FEATURES_SUPPORTED
    785    /* Write filter_method 64 (intrapixel differencing) only if
    786     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
    787     * 2. Libpng did not write a PNG signature (this filter_method is only
    788     *    used in PNG datastreams that are embedded in MNG datastreams) and
    789     * 3. The application called png_permit_mng_features with a mask that
    790     *    included PNG_FLAG_MNG_FILTER_64 and
    791     * 4. The filter_method is 64 and
    792     * 5. The color_type is RGB or RGBA
    793     */
    794    if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
    795        (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
    796    {
    797       /* Intrapixel differencing */
    798       png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
    799    }
    800 #endif
    801 
    802 /* Added at libpng-1.5.10 */
    803 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
    804    /* Check for out-of-range palette index */
    805    if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
    806        png_ptr->num_palette_max >= 0)
    807       png_do_check_palette_indexes(png_ptr, &row_info);
    808 #endif
    809 
    810    /* Find a filter if necessary, filter the row and write it out. */
    811    png_write_find_filter(png_ptr, &row_info);
    812 
    813    if (png_ptr->write_row_fn != NULL)
    814       (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
    815 }
    816 
    817 #ifdef PNG_WRITE_FLUSH_SUPPORTED
    818 /* Set the automatic flush interval or 0 to turn flushing off */
    819 void PNGAPI
    820 png_set_flush(png_structrp png_ptr, int nrows)
    821 {
    822    png_debug(1, "in png_set_flush");
    823 
    824    if (png_ptr == NULL)
    825       return;
    826 
    827    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
    828 }
    829 
    830 /* Flush the current output buffers now */
    831 void PNGAPI
    832 png_write_flush(png_structrp png_ptr)
    833 {
    834    png_debug(1, "in png_write_flush");
    835 
    836    if (png_ptr == NULL)
    837       return;
    838 
    839    /* We have already written out all of the data */
    840    if (png_ptr->row_number >= png_ptr->num_rows)
    841       return;
    842 
    843    png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
    844    png_ptr->flush_rows = 0;
    845    png_flush(png_ptr);
    846 }
    847 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
    848 
    849 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    850 static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */
    851 #endif
    852 
    853 /* Free any memory used in png_ptr struct without freeing the struct itself. */
    854 static void
    855 png_write_destroy(png_structrp png_ptr)
    856 {
    857    png_debug(1, "in png_write_destroy");
    858 
    859    /* Free any memory zlib uses */
    860    if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED)
    861       deflateEnd(&png_ptr->zstream);
    862 
    863    /* Free our memory.  png_free checks NULL for us. */
    864    png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
    865    png_free(png_ptr, png_ptr->row_buf);
    866 #ifdef PNG_WRITE_FILTER_SUPPORTED
    867    png_free(png_ptr, png_ptr->prev_row);
    868    png_free(png_ptr, png_ptr->sub_row);
    869    png_free(png_ptr, png_ptr->up_row);
    870    png_free(png_ptr, png_ptr->avg_row);
    871    png_free(png_ptr, png_ptr->paeth_row);
    872 #endif
    873 
    874 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    875    /* Use this to save a little code space, it doesn't free the filter_costs */
    876    png_reset_filter_heuristics(png_ptr);
    877    png_free(png_ptr, png_ptr->filter_costs);
    878    png_free(png_ptr, png_ptr->inv_filter_costs);
    879 #endif
    880 
    881 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
    882    png_free(png_ptr, png_ptr->chunk_list);
    883 #endif
    884 
    885    /* The error handling and memory handling information is left intact at this
    886     * point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
    887     * for how this happens.
    888     */
    889 }
    890 
    891 /* Free all memory used by the write.
    892  * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
    893  * *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
    894  * the passed in info_structs but it would quietly fail to free any of the data
    895  * inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
    896  * has no png_ptr.)
    897  */
    898 void PNGAPI
    899 png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
    900 {
    901    png_debug(1, "in png_destroy_write_struct");
    902 
    903    if (png_ptr_ptr != NULL)
    904    {
    905       png_structrp png_ptr = *png_ptr_ptr;
    906 
    907       if (png_ptr != NULL) /* added in libpng 1.6.0 */
    908       {
    909          png_destroy_info_struct(png_ptr, info_ptr_ptr);
    910 
    911          *png_ptr_ptr = NULL;
    912          png_write_destroy(png_ptr);
    913          png_destroy_png_struct(png_ptr);
    914       }
    915    }
    916 }
    917 
    918 /* Allow the application to select one or more row filters to use. */
    919 void PNGAPI
    920 png_set_filter(png_structrp png_ptr, int method, int filters)
    921 {
    922    png_debug(1, "in png_set_filter");
    923 
    924    if (png_ptr == NULL)
    925       return;
    926 
    927 #ifdef PNG_MNG_FEATURES_SUPPORTED
    928    if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
    929        (method == PNG_INTRAPIXEL_DIFFERENCING))
    930       method = PNG_FILTER_TYPE_BASE;
    931 
    932 #endif
    933    if (method == PNG_FILTER_TYPE_BASE)
    934    {
    935       switch (filters & (PNG_ALL_FILTERS | 0x07))
    936       {
    937 #ifdef PNG_WRITE_FILTER_SUPPORTED
    938          case 5:
    939          case 6:
    940          case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
    941             /* FALL THROUGH */
    942 #endif /* PNG_WRITE_FILTER_SUPPORTED */
    943          case PNG_FILTER_VALUE_NONE:
    944             png_ptr->do_filter = PNG_FILTER_NONE; break;
    945 
    946 #ifdef PNG_WRITE_FILTER_SUPPORTED
    947          case PNG_FILTER_VALUE_SUB:
    948             png_ptr->do_filter = PNG_FILTER_SUB; break;
    949 
    950          case PNG_FILTER_VALUE_UP:
    951             png_ptr->do_filter = PNG_FILTER_UP; break;
    952 
    953          case PNG_FILTER_VALUE_AVG:
    954             png_ptr->do_filter = PNG_FILTER_AVG; break;
    955 
    956          case PNG_FILTER_VALUE_PAETH:
    957             png_ptr->do_filter = PNG_FILTER_PAETH; break;
    958 
    959          default:
    960             png_ptr->do_filter = (png_byte)filters; break;
    961 #else
    962          default:
    963             png_app_error(png_ptr, "Unknown row filter for method 0");
    964 #endif /* PNG_WRITE_FILTER_SUPPORTED */
    965       }
    966 
    967       /* If we have allocated the row_buf, this means we have already started
    968        * with the image and we should have allocated all of the filter buffers
    969        * that have been selected.  If prev_row isn't already allocated, then
    970        * it is too late to start using the filters that need it, since we
    971        * will be missing the data in the previous row.  If an application
    972        * wants to start and stop using particular filters during compression,
    973        * it should start out with all of the filters, and then add and
    974        * remove them after the start of compression.
    975        */
    976       if (png_ptr->row_buf != NULL)
    977       {
    978 #ifdef PNG_WRITE_FILTER_SUPPORTED
    979          if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
    980          {
    981             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
    982                 (png_ptr->rowbytes + 1));
    983             png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
    984          }
    985 
    986          if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
    987          {
    988             if (png_ptr->prev_row == NULL)
    989             {
    990                png_warning(png_ptr, "Can't add Up filter after starting");
    991                png_ptr->do_filter = (png_byte)(png_ptr->do_filter &
    992                    ~PNG_FILTER_UP);
    993             }
    994 
    995             else
    996             {
    997                png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
    998                    (png_ptr->rowbytes + 1));
    999                png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
   1000             }
   1001          }
   1002 
   1003          if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
   1004          {
   1005             if (png_ptr->prev_row == NULL)
   1006             {
   1007                png_warning(png_ptr, "Can't add Average filter after starting");
   1008                png_ptr->do_filter = (png_byte)(png_ptr->do_filter &
   1009                    ~PNG_FILTER_AVG);
   1010             }
   1011 
   1012             else
   1013             {
   1014                png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
   1015                    (png_ptr->rowbytes + 1));
   1016                png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
   1017             }
   1018          }
   1019 
   1020          if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
   1021              png_ptr->paeth_row == NULL)
   1022          {
   1023             if (png_ptr->prev_row == NULL)
   1024             {
   1025                png_warning(png_ptr, "Can't add Paeth filter after starting");
   1026                png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
   1027             }
   1028 
   1029             else
   1030             {
   1031                png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
   1032                    (png_ptr->rowbytes + 1));
   1033                png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
   1034             }
   1035          }
   1036 
   1037          if (png_ptr->do_filter == PNG_NO_FILTERS)
   1038 #endif /* PNG_WRITE_FILTER_SUPPORTED */
   1039             png_ptr->do_filter = PNG_FILTER_NONE;
   1040       }
   1041    }
   1042    else
   1043       png_error(png_ptr, "Unknown custom filter method");
   1044 }
   1045 
   1046 /* This allows us to influence the way in which libpng chooses the "best"
   1047  * filter for the current scanline.  While the "minimum-sum-of-absolute-
   1048  * differences metric is relatively fast and effective, there is some
   1049  * question as to whether it can be improved upon by trying to keep the
   1050  * filtered data going to zlib more consistent, hopefully resulting in
   1051  * better compression.
   1052  */
   1053 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED      /* GRR 970116 */
   1054 /* Convenience reset API. */
   1055 static void
   1056 png_reset_filter_heuristics(png_structrp png_ptr)
   1057 {
   1058    /* Clear out any old values in the 'weights' - this must be done because if
   1059     * the app calls set_filter_heuristics multiple times with different
   1060     * 'num_weights' values we would otherwise potentially have wrong sized
   1061     * arrays.
   1062     */
   1063    png_ptr->num_prev_filters = 0;
   1064    png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
   1065    if (png_ptr->prev_filters != NULL)
   1066    {
   1067       png_bytep old = png_ptr->prev_filters;
   1068       png_ptr->prev_filters = NULL;
   1069       png_free(png_ptr, old);
   1070    }
   1071    if (png_ptr->filter_weights != NULL)
   1072    {
   1073       png_uint_16p old = png_ptr->filter_weights;
   1074       png_ptr->filter_weights = NULL;
   1075       png_free(png_ptr, old);
   1076    }
   1077 
   1078    if (png_ptr->inv_filter_weights != NULL)
   1079    {
   1080       png_uint_16p old = png_ptr->inv_filter_weights;
   1081       png_ptr->inv_filter_weights = NULL;
   1082       png_free(png_ptr, old);
   1083    }
   1084 
   1085    /* Leave the filter_costs - this array is fixed size. */
   1086 }
   1087 
   1088 static int
   1089 png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method,
   1090    int num_weights)
   1091 {
   1092    if (png_ptr == NULL)
   1093       return 0;
   1094 
   1095    /* Clear out the arrays */
   1096    png_reset_filter_heuristics(png_ptr);
   1097 
   1098    /* Check arguments; the 'reset' function makes the correct settings for the
   1099     * unweighted case, but we must handle the weight case by initializing the
   1100     * arrays for the caller.
   1101     */
   1102    if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   1103    {
   1104       int i;
   1105 
   1106       if (num_weights > 0)
   1107       {
   1108          png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
   1109              (png_uint_32)((sizeof (png_byte)) * num_weights));
   1110 
   1111          /* To make sure that the weighting starts out fairly */
   1112          for (i = 0; i < num_weights; i++)
   1113          {
   1114             png_ptr->prev_filters[i] = 255;
   1115          }
   1116 
   1117          png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
   1118              (png_uint_32)((sizeof (png_uint_16)) * num_weights));
   1119 
   1120          png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
   1121              (png_uint_32)((sizeof (png_uint_16)) * num_weights));
   1122 
   1123          for (i = 0; i < num_weights; i++)
   1124          {
   1125             png_ptr->inv_filter_weights[i] =
   1126             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
   1127          }
   1128 
   1129          /* Safe to set this now */
   1130          png_ptr->num_prev_filters = (png_byte)num_weights;
   1131       }
   1132 
   1133       /* If, in the future, there are other filter methods, this would
   1134        * need to be based on png_ptr->filter.
   1135        */
   1136       if (png_ptr->filter_costs == NULL)
   1137       {
   1138          png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
   1139              (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
   1140 
   1141          png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
   1142              (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
   1143       }
   1144 
   1145       for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
   1146       {
   1147          png_ptr->inv_filter_costs[i] =
   1148          png_ptr->filter_costs[i] = PNG_COST_FACTOR;
   1149       }
   1150 
   1151       /* All the arrays are inited, safe to set this: */
   1152       png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED;
   1153 
   1154       /* Return the 'ok' code. */
   1155       return 1;
   1156    }
   1157    else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT ||
   1158       heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
   1159    {
   1160       return 1;
   1161    }
   1162    else
   1163    {
   1164       png_warning(png_ptr, "Unknown filter heuristic method");
   1165       return 0;
   1166    }
   1167 }
   1168 
   1169 /* Provide floating and fixed point APIs */
   1170 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1171 void PNGAPI
   1172 png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
   1173     int num_weights, png_const_doublep filter_weights,
   1174     png_const_doublep filter_costs)
   1175 {
   1176    png_debug(1, "in png_set_filter_heuristics");
   1177 
   1178    /* The internal API allocates all the arrays and ensures that the elements of
   1179     * those arrays are set to the default value.
   1180     */
   1181    if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
   1182       return;
   1183 
   1184    /* If using the weighted method copy in the weights. */
   1185    if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   1186    {
   1187       int i;
   1188       for (i = 0; i < num_weights; i++)
   1189       {
   1190          if (filter_weights[i] <= 0.0)
   1191          {
   1192             png_ptr->inv_filter_weights[i] =
   1193             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
   1194          }
   1195 
   1196          else
   1197          {
   1198             png_ptr->inv_filter_weights[i] =
   1199                 (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5);
   1200 
   1201             png_ptr->filter_weights[i] =
   1202                 (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5);
   1203          }
   1204       }
   1205 
   1206       /* Here is where we set the relative costs of the different filters.  We
   1207        * should take the desired compression level into account when setting
   1208        * the costs, so that Paeth, for instance, has a high relative cost at low
   1209        * compression levels, while it has a lower relative cost at higher
   1210        * compression settings.  The filter types are in order of increasing
   1211        * relative cost, so it would be possible to do this with an algorithm.
   1212        */
   1213       for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0)
   1214       {
   1215          png_ptr->inv_filter_costs[i] =
   1216              (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5);
   1217 
   1218          png_ptr->filter_costs[i] =
   1219              (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5);
   1220       }
   1221    }
   1222 }
   1223 #endif /* FLOATING_POINT */
   1224 
   1225 #ifdef PNG_FIXED_POINT_SUPPORTED
   1226 void PNGAPI
   1227 png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
   1228     int num_weights, png_const_fixed_point_p filter_weights,
   1229     png_const_fixed_point_p filter_costs)
   1230 {
   1231    png_debug(1, "in png_set_filter_heuristics_fixed");
   1232 
   1233    /* The internal API allocates all the arrays and ensures that the elements of
   1234     * those arrays are set to the default value.
   1235     */
   1236    if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
   1237       return;
   1238 
   1239    /* If using the weighted method copy in the weights. */
   1240    if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   1241    {
   1242       int i;
   1243       for (i = 0; i < num_weights; i++)
   1244       {
   1245          if (filter_weights[i] <= 0)
   1246          {
   1247             png_ptr->inv_filter_weights[i] =
   1248             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
   1249          }
   1250 
   1251          else
   1252          {
   1253             png_ptr->inv_filter_weights[i] = (png_uint_16)
   1254                ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1);
   1255 
   1256             png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR*
   1257                PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]);
   1258          }
   1259       }
   1260 
   1261       /* Here is where we set the relative costs of the different filters.  We
   1262        * should take the desired compression level into account when setting
   1263        * the costs, so that Paeth, for instance, has a high relative cost at low
   1264        * compression levels, while it has a lower relative cost at higher
   1265        * compression settings.  The filter types are in order of increasing
   1266        * relative cost, so it would be possible to do this with an algorithm.
   1267        */
   1268       for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
   1269          if (filter_costs[i] >= PNG_FP_1)
   1270       {
   1271          png_uint_32 tmp;
   1272 
   1273          /* Use a 32 bit unsigned temporary here because otherwise the
   1274           * intermediate value will be a 32 bit *signed* integer (ANSI rules)
   1275           * and this will get the wrong answer on division.
   1276           */
   1277          tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2);
   1278          tmp /= filter_costs[i];
   1279 
   1280          png_ptr->inv_filter_costs[i] = (png_uint_16)tmp;
   1281 
   1282          tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF;
   1283          tmp /= PNG_FP_1;
   1284 
   1285          png_ptr->filter_costs[i] = (png_uint_16)tmp;
   1286       }
   1287    }
   1288 }
   1289 #endif /* FIXED_POINT */
   1290 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
   1291 
   1292 void PNGAPI
   1293 png_set_compression_level(png_structrp png_ptr, int level)
   1294 {
   1295    png_debug(1, "in png_set_compression_level");
   1296 
   1297    if (png_ptr == NULL)
   1298       return;
   1299 
   1300    png_ptr->zlib_level = level;
   1301 }
   1302 
   1303 void PNGAPI
   1304 png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
   1305 {
   1306    png_debug(1, "in png_set_compression_mem_level");
   1307 
   1308    if (png_ptr == NULL)
   1309       return;
   1310 
   1311    png_ptr->zlib_mem_level = mem_level;
   1312 }
   1313 
   1314 void PNGAPI
   1315 png_set_compression_strategy(png_structrp png_ptr, int strategy)
   1316 {
   1317    png_debug(1, "in png_set_compression_strategy");
   1318 
   1319    if (png_ptr == NULL)
   1320       return;
   1321 
   1322    /* The flag setting here prevents the libpng dynamic selection of strategy.
   1323     */
   1324    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
   1325    png_ptr->zlib_strategy = strategy;
   1326 }
   1327 
   1328 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
   1329  * smaller value of window_bits if it can do so safely.
   1330  */
   1331 void PNGAPI
   1332 png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
   1333 {
   1334    if (png_ptr == NULL)
   1335       return;
   1336 
   1337    /* Prior to 1.6.0 this would warn but then set the window_bits value, this
   1338     * meant that negative window bits values could be selected which would cause
   1339     * libpng to write a non-standard PNG file with raw deflate or gzip
   1340     * compressed IDAT or ancillary chunks.  Such files can be read and there is
   1341     * no warning on read, so this seems like a very bad idea.
   1342     */
   1343    if (window_bits > 15)
   1344    {
   1345       png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
   1346       window_bits = 15;
   1347    }
   1348 
   1349    else if (window_bits < 8)
   1350    {
   1351       png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
   1352       window_bits = 8;
   1353    }
   1354 
   1355    png_ptr->zlib_window_bits = window_bits;
   1356 }
   1357 
   1358 void PNGAPI
   1359 png_set_compression_method(png_structrp png_ptr, int method)
   1360 {
   1361    png_debug(1, "in png_set_compression_method");
   1362 
   1363    if (png_ptr == NULL)
   1364       return;
   1365 
   1366    /* This would produce an invalid PNG file if it worked, but it doesn't and
   1367     * deflate will fault it, so it is harmless to just warn here.
   1368     */
   1369    if (method != 8)
   1370       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
   1371 
   1372    png_ptr->zlib_method = method;
   1373 }
   1374 
   1375 /* The following were added to libpng-1.5.4 */
   1376 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
   1377 void PNGAPI
   1378 png_set_text_compression_level(png_structrp png_ptr, int level)
   1379 {
   1380    png_debug(1, "in png_set_text_compression_level");
   1381 
   1382    if (png_ptr == NULL)
   1383       return;
   1384 
   1385    png_ptr->zlib_text_level = level;
   1386 }
   1387 
   1388 void PNGAPI
   1389 png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
   1390 {
   1391    png_debug(1, "in png_set_text_compression_mem_level");
   1392 
   1393    if (png_ptr == NULL)
   1394       return;
   1395 
   1396    png_ptr->zlib_text_mem_level = mem_level;
   1397 }
   1398 
   1399 void PNGAPI
   1400 png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
   1401 {
   1402    png_debug(1, "in png_set_text_compression_strategy");
   1403 
   1404    if (png_ptr == NULL)
   1405       return;
   1406 
   1407    png_ptr->zlib_text_strategy = strategy;
   1408 }
   1409 
   1410 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
   1411  * smaller value of window_bits if it can do so safely.
   1412  */
   1413 void PNGAPI
   1414 png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
   1415 {
   1416    if (png_ptr == NULL)
   1417       return;
   1418 
   1419    if (window_bits > 15)
   1420    {
   1421       png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
   1422       window_bits = 15;
   1423    }
   1424 
   1425    else if (window_bits < 8)
   1426    {
   1427       png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
   1428       window_bits = 8;
   1429    }
   1430 
   1431    png_ptr->zlib_text_window_bits = window_bits;
   1432 }
   1433 
   1434 void PNGAPI
   1435 png_set_text_compression_method(png_structrp png_ptr, int method)
   1436 {
   1437    png_debug(1, "in png_set_text_compression_method");
   1438 
   1439    if (png_ptr == NULL)
   1440       return;
   1441 
   1442    if (method != 8)
   1443       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
   1444 
   1445    png_ptr->zlib_text_method = method;
   1446 }
   1447 #endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
   1448 /* end of API added to libpng-1.5.4 */
   1449 
   1450 void PNGAPI
   1451 png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
   1452 {
   1453    if (png_ptr == NULL)
   1454       return;
   1455 
   1456    png_ptr->write_row_fn = write_row_fn;
   1457 }
   1458 
   1459 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
   1460 void PNGAPI
   1461 png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
   1462     write_user_transform_fn)
   1463 {
   1464    png_debug(1, "in png_set_write_user_transform_fn");
   1465 
   1466    if (png_ptr == NULL)
   1467       return;
   1468 
   1469    png_ptr->transformations |= PNG_USER_TRANSFORM;
   1470    png_ptr->write_user_transform_fn = write_user_transform_fn;
   1471 }
   1472 #endif
   1473 
   1474 
   1475 #ifdef PNG_INFO_IMAGE_SUPPORTED
   1476 void PNGAPI
   1477 png_write_png(png_structrp png_ptr, png_inforp info_ptr,
   1478     int transforms, voidp params)
   1479 {
   1480    if (png_ptr == NULL || info_ptr == NULL)
   1481       return;
   1482 
   1483    /* Write the file header information. */
   1484    png_write_info(png_ptr, info_ptr);
   1485 
   1486    /* ------ these transformations don't touch the info structure ------- */
   1487 
   1488 #ifdef PNG_WRITE_INVERT_SUPPORTED
   1489    /* Invert monochrome pixels */
   1490    if (transforms & PNG_TRANSFORM_INVERT_MONO)
   1491       png_set_invert_mono(png_ptr);
   1492 #endif
   1493 
   1494 #ifdef PNG_WRITE_SHIFT_SUPPORTED
   1495    /* Shift the pixels up to a legal bit depth and fill in
   1496     * as appropriate to correctly scale the image.
   1497     */
   1498    if ((transforms & PNG_TRANSFORM_SHIFT)
   1499        && (info_ptr->valid & PNG_INFO_sBIT))
   1500       png_set_shift(png_ptr, &info_ptr->sig_bit);
   1501 #endif
   1502 
   1503 #ifdef PNG_WRITE_PACK_SUPPORTED
   1504    /* Pack pixels into bytes */
   1505    if (transforms & PNG_TRANSFORM_PACKING)
   1506        png_set_packing(png_ptr);
   1507 #endif
   1508 
   1509 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
   1510    /* Swap location of alpha bytes from ARGB to RGBA */
   1511    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
   1512       png_set_swap_alpha(png_ptr);
   1513 #endif
   1514 
   1515 #ifdef PNG_WRITE_FILLER_SUPPORTED
   1516    /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */
   1517    if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
   1518       png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
   1519 
   1520    else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
   1521       png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
   1522 #endif
   1523 
   1524 #ifdef PNG_WRITE_BGR_SUPPORTED
   1525    /* Flip BGR pixels to RGB */
   1526    if (transforms & PNG_TRANSFORM_BGR)
   1527       png_set_bgr(png_ptr);
   1528 #endif
   1529 
   1530 #ifdef PNG_WRITE_SWAP_SUPPORTED
   1531    /* Swap bytes of 16-bit files to most significant byte first */
   1532    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
   1533       png_set_swap(png_ptr);
   1534 #endif
   1535 
   1536 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
   1537    /* Swap bits of 1, 2, 4 bit packed pixel formats */
   1538    if (transforms & PNG_TRANSFORM_PACKSWAP)
   1539       png_set_packswap(png_ptr);
   1540 #endif
   1541 
   1542 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
   1543    /* Invert the alpha channel from opacity to transparency */
   1544    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
   1545       png_set_invert_alpha(png_ptr);
   1546 #endif
   1547 
   1548    /* ----------------------- end of transformations ------------------- */
   1549 
   1550    /* Write the bits */
   1551    if (info_ptr->valid & PNG_INFO_IDAT)
   1552        png_write_image(png_ptr, info_ptr->row_pointers);
   1553 
   1554    /* It is REQUIRED to call this to finish writing the rest of the file */
   1555    png_write_end(png_ptr, info_ptr);
   1556 
   1557    PNG_UNUSED(transforms)   /* Quiet compiler warnings */
   1558    PNG_UNUSED(params)
   1559 }
   1560 #endif
   1561 
   1562 
   1563 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
   1564 #ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
   1565 /* Initialize the write structure - general purpose utility. */
   1566 static int
   1567 png_image_write_init(png_imagep image)
   1568 {
   1569    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
   1570           png_safe_error, png_safe_warning);
   1571 
   1572    if (png_ptr != NULL)
   1573    {
   1574       png_infop info_ptr = png_create_info_struct(png_ptr);
   1575 
   1576       if (info_ptr != NULL)
   1577       {
   1578          png_controlp control = png_voidcast(png_controlp,
   1579             png_malloc_warn(png_ptr, (sizeof *control)));
   1580 
   1581          if (control != NULL)
   1582          {
   1583             memset(control, 0, (sizeof *control));
   1584 
   1585             control->png_ptr = png_ptr;
   1586             control->info_ptr = info_ptr;
   1587             control->for_write = 1;
   1588 
   1589             image->opaque = control;
   1590             return 1;
   1591          }
   1592 
   1593          /* Error clean up */
   1594          png_destroy_info_struct(png_ptr, &info_ptr);
   1595       }
   1596 
   1597       png_destroy_write_struct(&png_ptr, NULL);
   1598    }
   1599 
   1600    return png_image_error(image, "png_image_write_: out of memory");
   1601 }
   1602 
   1603 /* Arguments to png_image_write_main: */
   1604 typedef struct
   1605 {
   1606    /* Arguments: */
   1607    png_imagep      image;
   1608    png_const_voidp buffer;
   1609    png_int_32      row_stride;
   1610    png_const_voidp colormap;
   1611    int             convert_to_8bit;
   1612    /* Local variables: */
   1613    png_const_voidp first_row;
   1614    ptrdiff_t       row_bytes;
   1615    png_voidp       local_row;
   1616 } png_image_write_control;
   1617 
   1618 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
   1619  * do any necessary byte swapping.  The component order is defined by the
   1620  * png_image format value.
   1621  */
   1622 static int
   1623 png_write_image_16bit(png_voidp argument)
   1624 {
   1625    png_image_write_control *display = png_voidcast(png_image_write_control*,
   1626       argument);
   1627    png_imagep image = display->image;
   1628    png_structrp png_ptr = image->opaque->png_ptr;
   1629 
   1630    png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
   1631       display->first_row);
   1632    png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
   1633    png_uint_16p row_end;
   1634    const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
   1635    int aindex = 0;
   1636    png_uint_32 y = image->height;
   1637 
   1638    if (image->format & PNG_FORMAT_FLAG_ALPHA)
   1639    {
   1640       if (image->format & PNG_FORMAT_FLAG_AFIRST)
   1641       {
   1642          aindex = -1;
   1643          ++input_row; /* To point to the first component */
   1644          ++output_row;
   1645       }
   1646 
   1647       else
   1648          aindex = channels;
   1649    }
   1650 
   1651    else
   1652       png_error(png_ptr, "png_write_image: internal call error");
   1653 
   1654    /* Work out the output row end and count over this, note that the increment
   1655     * above to 'row' means that row_end can actually be beyond the end of the
   1656     * row; this is correct.
   1657     */
   1658    row_end = output_row + image->width * (channels+1);
   1659 
   1660    while (y-- > 0)
   1661    {
   1662       png_const_uint_16p in_ptr = input_row;
   1663       png_uint_16p out_ptr = output_row;
   1664 
   1665       while (out_ptr < row_end)
   1666       {
   1667          const png_uint_16 alpha = in_ptr[aindex];
   1668          png_uint_32 reciprocal = 0;
   1669          int c;
   1670 
   1671          out_ptr[aindex] = alpha;
   1672 
   1673          /* Calculate a reciprocal.  The correct calculation is simply
   1674           * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
   1675           * allows correct rounding by adding .5 before the shift.  'reciprocal'
   1676           * is only initialized when required.
   1677           */
   1678          if (alpha > 0 && alpha < 65535)
   1679             reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
   1680 
   1681          c = channels;
   1682          do /* always at least one channel */
   1683          {
   1684             png_uint_16 component = *in_ptr++;
   1685 
   1686             /* The following gives 65535 for an alpha of 0, which is fine,
   1687              * otherwise if 0/0 is represented as some other value there is more
   1688              * likely to be a discontinuity which will probably damage
   1689              * compression when moving from a fully transparent area to a
   1690              * nearly transparent one.  (The assumption here is that opaque
   1691              * areas tend not to be 0 intensity.)
   1692              */
   1693             if (component >= alpha)
   1694                component = 65535;
   1695 
   1696             /* component<alpha, so component/alpha is less than one and
   1697              * component*reciprocal is less than 2^31.
   1698              */
   1699             else if (component > 0 && alpha < 65535)
   1700             {
   1701                png_uint_32 calc = component * reciprocal;
   1702                calc += 16384; /* round to nearest */
   1703                component = (png_uint_16)(calc >> 15);
   1704             }
   1705 
   1706             *out_ptr++ = component;
   1707          }
   1708          while (--c > 0);
   1709 
   1710          /* Skip to next component (skip the intervening alpha channel) */
   1711          ++in_ptr;
   1712          ++out_ptr;
   1713       }
   1714 
   1715       png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
   1716       input_row += display->row_bytes/(sizeof (png_uint_16));
   1717    }
   1718 
   1719    return 1;
   1720 }
   1721 
   1722 /* Given 16-bit input (1 to 4 channels) write 8-bit output.  If an alpha channel
   1723  * is present it must be removed from the components, the components are then
   1724  * written in sRGB encoding.  No components are added or removed.
   1725  *
   1726  * Calculate an alpha reciprocal to reverse pre-multiplication.  As above the
   1727  * calculation can be done to 15 bits of accuracy; however, the output needs to
   1728  * be scaled in the range 0..255*65535, so include that scaling here.
   1729  */
   1730 #define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
   1731 
   1732 static png_byte
   1733 png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
   1734    png_uint_32 reciprocal/*from the above macro*/)
   1735 {
   1736    /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
   1737     * is represented as some other value there is more likely to be a
   1738     * discontinuity which will probably damage compression when moving from a
   1739     * fully transparent area to a nearly transparent one.  (The assumption here
   1740     * is that opaque areas tend not to be 0 intensity.)
   1741     *
   1742     * There is a rounding problem here; if alpha is less than 128 it will end up
   1743     * as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
   1744     * output change for this too.
   1745     */
   1746    if (component >= alpha || alpha < 128)
   1747       return 255;
   1748 
   1749    /* component<alpha, so component/alpha is less than one and
   1750     * component*reciprocal is less than 2^31.
   1751     */
   1752    else if (component > 0)
   1753    {
   1754       /* The test is that alpha/257 (rounded) is less than 255, the first value
   1755        * that becomes 255 is 65407.
   1756        * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
   1757        * be exact!)  [Could also test reciprocal != 0]
   1758        */
   1759       if (alpha < 65407)
   1760       {
   1761          component *= reciprocal;
   1762          component += 64; /* round to nearest */
   1763          component >>= 7;
   1764       }
   1765 
   1766       else
   1767          component *= 255;
   1768 
   1769       /* Convert the component to sRGB. */
   1770       return (png_byte)PNG_sRGB_FROM_LINEAR(component);
   1771    }
   1772 
   1773    else
   1774       return 0;
   1775 }
   1776 
   1777 static int
   1778 png_write_image_8bit(png_voidp argument)
   1779 {
   1780    png_image_write_control *display = png_voidcast(png_image_write_control*,
   1781       argument);
   1782    png_imagep image = display->image;
   1783    png_structrp png_ptr = image->opaque->png_ptr;
   1784 
   1785    png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
   1786       display->first_row);
   1787    png_bytep output_row = png_voidcast(png_bytep, display->local_row);
   1788    png_uint_32 y = image->height;
   1789    const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
   1790 
   1791    if (image->format & PNG_FORMAT_FLAG_ALPHA)
   1792    {
   1793       png_bytep row_end;
   1794       int aindex;
   1795 
   1796       if (image->format & PNG_FORMAT_FLAG_AFIRST)
   1797       {
   1798          aindex = -1;
   1799          ++input_row; /* To point to the first component */
   1800          ++output_row;
   1801       }
   1802 
   1803       else
   1804          aindex = channels;
   1805 
   1806       /* Use row_end in place of a loop counter: */
   1807       row_end = output_row + image->width * (channels+1);
   1808 
   1809       while (y-- > 0)
   1810       {
   1811          png_const_uint_16p in_ptr = input_row;
   1812          png_bytep out_ptr = output_row;
   1813 
   1814          while (out_ptr < row_end)
   1815          {
   1816             png_uint_16 alpha = in_ptr[aindex];
   1817             png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
   1818             png_uint_32 reciprocal = 0;
   1819             int c;
   1820 
   1821             /* Scale and write the alpha channel. */
   1822             out_ptr[aindex] = alphabyte;
   1823 
   1824             if (alphabyte > 0 && alphabyte < 255)
   1825                reciprocal = UNP_RECIPROCAL(alpha);
   1826 
   1827             c = channels;
   1828             do /* always at least one channel */
   1829                *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
   1830             while (--c > 0);
   1831 
   1832             /* Skip to next component (skip the intervening alpha channel) */
   1833             ++in_ptr;
   1834             ++out_ptr;
   1835          } /* while out_ptr < row_end */
   1836 
   1837          png_write_row(png_ptr, png_voidcast(png_const_bytep,
   1838             display->local_row));
   1839          input_row += display->row_bytes/(sizeof (png_uint_16));
   1840       } /* while y */
   1841    }
   1842 
   1843    else
   1844    {
   1845       /* No alpha channel, so the row_end really is the end of the row and it
   1846        * is sufficient to loop over the components one by one.
   1847        */
   1848       png_bytep row_end = output_row + image->width * channels;
   1849 
   1850       while (y-- > 0)
   1851       {
   1852          png_const_uint_16p in_ptr = input_row;
   1853          png_bytep out_ptr = output_row;
   1854 
   1855          while (out_ptr < row_end)
   1856          {
   1857             png_uint_32 component = *in_ptr++;
   1858 
   1859             component *= 255;
   1860             *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
   1861          }
   1862 
   1863          png_write_row(png_ptr, output_row);
   1864          input_row += display->row_bytes/(sizeof (png_uint_16));
   1865       }
   1866    }
   1867 
   1868    return 1;
   1869 }
   1870 
   1871 static void
   1872 png_image_set_PLTE(png_image_write_control *display)
   1873 {
   1874    const png_imagep image = display->image;
   1875    const void *cmap = display->colormap;
   1876    const int entries = image->colormap_entries > 256 ? 256 :
   1877       (int)image->colormap_entries;
   1878 
   1879    /* NOTE: the caller must check for cmap != NULL and entries != 0 */
   1880    const png_uint_32 format = image->format;
   1881    const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
   1882 
   1883 #  ifdef PNG_FORMAT_BGR_SUPPORTED
   1884       const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
   1885          (format & PNG_FORMAT_FLAG_ALPHA) != 0;
   1886 #  else
   1887 #     define afirst 0
   1888 #  endif
   1889 
   1890 #  ifdef PNG_FORMAT_BGR_SUPPORTED
   1891       const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0;
   1892 #  else
   1893 #     define bgr 0
   1894 #  endif
   1895 
   1896    int i, num_trans;
   1897    png_color palette[256];
   1898    png_byte tRNS[256];
   1899 
   1900    memset(tRNS, 255, (sizeof tRNS));
   1901    memset(palette, 0, (sizeof palette));
   1902 
   1903    for (i=num_trans=0; i<entries; ++i)
   1904    {
   1905       /* This gets automatically converted to sRGB with reversal of the
   1906        * pre-multiplication if the color-map has an alpha channel.
   1907        */
   1908       if (format & PNG_FORMAT_FLAG_LINEAR)
   1909       {
   1910          png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
   1911 
   1912          entry += i * channels;
   1913 
   1914          if (channels & 1) /* no alpha */
   1915          {
   1916             if (channels >= 3) /* RGB */
   1917             {
   1918                palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
   1919                   entry[(2 ^ bgr)]);
   1920                palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
   1921                   entry[1]);
   1922                palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
   1923                   entry[bgr]);
   1924             }
   1925 
   1926             else /* Gray */
   1927                palette[i].blue = palette[i].red = palette[i].green =
   1928                   (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
   1929          }
   1930 
   1931          else /* alpha */
   1932          {
   1933             png_uint_16 alpha = entry[afirst ? 0 : channels-1];
   1934             png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
   1935             png_uint_32 reciprocal = 0;
   1936 
   1937             /* Calculate a reciprocal, as in the png_write_image_8bit code above
   1938              * this is designed to produce a value scaled to 255*65535 when
   1939              * divided by 128 (i.e. asr 7).
   1940              */
   1941             if (alphabyte > 0 && alphabyte < 255)
   1942                reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
   1943 
   1944             tRNS[i] = alphabyte;
   1945             if (alphabyte < 255)
   1946                num_trans = i+1;
   1947 
   1948             if (channels >= 3) /* RGB */
   1949             {
   1950                palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
   1951                   alpha, reciprocal);
   1952                palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
   1953                   reciprocal);
   1954                palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
   1955                   reciprocal);
   1956             }
   1957 
   1958             else /* gray */
   1959                palette[i].blue = palette[i].red = palette[i].green =
   1960                   png_unpremultiply(entry[afirst], alpha, reciprocal);
   1961          }
   1962       }
   1963 
   1964       else /* Color-map has sRGB values */
   1965       {
   1966          png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
   1967 
   1968          entry += i * channels;
   1969 
   1970          switch (channels)
   1971          {
   1972             case 4:
   1973                tRNS[i] = entry[afirst ? 0 : 3];
   1974                if (tRNS[i] < 255)
   1975                   num_trans = i+1;
   1976                /* FALL THROUGH */
   1977             case 3:
   1978                palette[i].blue = entry[afirst + (2 ^ bgr)];
   1979                palette[i].green = entry[afirst + 1];
   1980                palette[i].red = entry[afirst + bgr];
   1981                break;
   1982 
   1983             case 2:
   1984                tRNS[i] = entry[1 ^ afirst];
   1985                if (tRNS[i] < 255)
   1986                   num_trans = i+1;
   1987                /* FALL THROUGH */
   1988             case 1:
   1989                palette[i].blue = palette[i].red = palette[i].green =
   1990                   entry[afirst];
   1991                break;
   1992 
   1993             default:
   1994                break;
   1995          }
   1996       }
   1997    }
   1998 
   1999 #  ifdef afirst
   2000 #     undef afirst
   2001 #  endif
   2002 #  ifdef bgr
   2003 #     undef bgr
   2004 #  endif
   2005 
   2006    png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
   2007       entries);
   2008 
   2009    if (num_trans > 0)
   2010       png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
   2011          num_trans, NULL);
   2012 
   2013    image->colormap_entries = entries;
   2014 }
   2015 
   2016 static int
   2017 png_image_write_main(png_voidp argument)
   2018 {
   2019    png_image_write_control *display = png_voidcast(png_image_write_control*,
   2020       argument);
   2021    png_imagep image = display->image;
   2022    png_structrp png_ptr = image->opaque->png_ptr;
   2023    png_inforp info_ptr = image->opaque->info_ptr;
   2024    png_uint_32 format = image->format;
   2025 
   2026    int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0;
   2027    int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */
   2028    int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0;
   2029    int write_16bit = linear && !colormap && !display->convert_to_8bit;
   2030 
   2031 #  ifdef PNG_BENIGN_ERRORS_SUPPORTED
   2032       /* Make sure we error out on any bad situation */
   2033       png_set_benign_errors(png_ptr, 0/*error*/);
   2034 #  endif
   2035 
   2036    /* Default the 'row_stride' parameter if required. */
   2037    if (display->row_stride == 0)
   2038       display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
   2039 
   2040    /* Set the required transforms then write the rows in the correct order. */
   2041    if (format & PNG_FORMAT_FLAG_COLORMAP)
   2042    {
   2043       if (display->colormap != NULL && image->colormap_entries > 0)
   2044       {
   2045          png_uint_32 entries = image->colormap_entries;
   2046 
   2047          png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
   2048             entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
   2049             PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
   2050             PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
   2051 
   2052          png_image_set_PLTE(display);
   2053       }
   2054 
   2055       else
   2056          png_error(image->opaque->png_ptr,
   2057             "no color-map for color-mapped image");
   2058    }
   2059 
   2060    else
   2061       png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
   2062          write_16bit ? 16 : 8,
   2063          ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
   2064          ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
   2065          PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
   2066 
   2067    /* Counter-intuitively the data transformations must be called *after*
   2068     * png_write_info, not before as in the read code, but the 'set' functions
   2069     * must still be called before.  Just set the color space information, never
   2070     * write an interlaced image.
   2071     */
   2072 
   2073    if (write_16bit)
   2074    {
   2075       /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
   2076       png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
   2077 
   2078       if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB))
   2079          png_set_cHRM_fixed(png_ptr, info_ptr,
   2080             /* color      x       y */
   2081             /* white */ 31270, 32900,
   2082             /* red   */ 64000, 33000,
   2083             /* green */ 30000, 60000,
   2084             /* blue  */ 15000,  6000
   2085          );
   2086    }
   2087 
   2088    else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB))
   2089       png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
   2090 
   2091    /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
   2092     * space must still be gamma encoded.
   2093     */
   2094    else
   2095       png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
   2096 
   2097    /* Write the file header. */
   2098    png_write_info(png_ptr, info_ptr);
   2099 
   2100    /* Now set up the data transformations (*after* the header is written),
   2101     * remove the handled transformations from the 'format' flags for checking.
   2102     *
   2103     * First check for a little endian system if writing 16 bit files.
   2104     */
   2105    if (write_16bit)
   2106    {
   2107       PNG_CONST png_uint_16 le = 0x0001;
   2108 
   2109       if (*(png_const_bytep)&le)
   2110          png_set_swap(png_ptr);
   2111    }
   2112 
   2113 #  ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
   2114       if (format & PNG_FORMAT_FLAG_BGR)
   2115       {
   2116          if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0)
   2117             png_set_bgr(png_ptr);
   2118          format &= ~PNG_FORMAT_FLAG_BGR;
   2119       }
   2120 #  endif
   2121 
   2122 #  ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
   2123       if (format & PNG_FORMAT_FLAG_AFIRST)
   2124       {
   2125          if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
   2126             png_set_swap_alpha(png_ptr);
   2127          format &= ~PNG_FORMAT_FLAG_AFIRST;
   2128       }
   2129 #  endif
   2130 
   2131    /* If there are 16 or fewer color-map entries we wrote a lower bit depth
   2132     * above, but the application data is still byte packed.
   2133     */
   2134    if (colormap && image->colormap_entries <= 16)
   2135       png_set_packing(png_ptr);
   2136 
   2137    /* That should have handled all (both) the transforms. */
   2138    if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
   2139          PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
   2140       png_error(png_ptr, "png_write_image: unsupported transformation");
   2141 
   2142    {
   2143       png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
   2144       ptrdiff_t row_bytes = display->row_stride;
   2145 
   2146       if (linear)
   2147          row_bytes *= (sizeof (png_uint_16));
   2148 
   2149       if (row_bytes < 0)
   2150          row += (image->height-1) * (-row_bytes);
   2151 
   2152       display->first_row = row;
   2153       display->row_bytes = row_bytes;
   2154    }
   2155 
   2156    /* Apply 'fast' options if the flag is set. */
   2157    if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
   2158    {
   2159       png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
   2160       /* NOTE: determined by experiment using pngstest, this reflects some
   2161        * balance between the time to write the image once and the time to read
   2162        * it about 50 times.  The speed-up in pngstest was about 10-20% of the
   2163        * total (user) time on a heavily loaded system.
   2164        */
   2165       png_set_compression_level(png_ptr, 3);
   2166    }
   2167 
   2168    /* Check for the cases that currently require a pre-transform on the row
   2169     * before it is written.  This only applies when the input is 16-bit and
   2170     * either there is an alpha channel or it is converted to 8-bit.
   2171     */
   2172    if ((linear && alpha) || (!colormap && display->convert_to_8bit))
   2173    {
   2174       png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
   2175          png_get_rowbytes(png_ptr, info_ptr)));
   2176       int result;
   2177 
   2178       display->local_row = row;
   2179       if (write_16bit)
   2180          result = png_safe_execute(image, png_write_image_16bit, display);
   2181       else
   2182          result = png_safe_execute(image, png_write_image_8bit, display);
   2183       display->local_row = NULL;
   2184 
   2185       png_free(png_ptr, row);
   2186 
   2187       /* Skip the 'write_end' on error: */
   2188       if (!result)
   2189          return 0;
   2190    }
   2191 
   2192    /* Otherwise this is the case where the input is in a format currently
   2193     * supported by the rest of the libpng write code; call it directly.
   2194     */
   2195    else
   2196    {
   2197       png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
   2198       ptrdiff_t row_bytes = display->row_bytes;
   2199       png_uint_32 y = image->height;
   2200 
   2201       while (y-- > 0)
   2202       {
   2203          png_write_row(png_ptr, row);
   2204          row += row_bytes;
   2205       }
   2206    }
   2207 
   2208    png_write_end(png_ptr, info_ptr);
   2209    return 1;
   2210 }
   2211 
   2212 int PNGAPI
   2213 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
   2214    const void *buffer, png_int_32 row_stride, const void *colormap)
   2215 {
   2216    /* Write the image to the given (FILE*). */
   2217    if (image != NULL && image->version == PNG_IMAGE_VERSION)
   2218    {
   2219       if (file != NULL)
   2220       {
   2221          if (png_image_write_init(image))
   2222          {
   2223             png_image_write_control display;
   2224             int result;
   2225 
   2226             /* This is slightly evil, but png_init_io doesn't do anything other
   2227              * than this and we haven't changed the standard IO functions so
   2228              * this saves a 'safe' function.
   2229              */
   2230             image->opaque->png_ptr->io_ptr = file;
   2231 
   2232             memset(&display, 0, (sizeof display));
   2233             display.image = image;
   2234             display.buffer = buffer;
   2235             display.row_stride = row_stride;
   2236             display.colormap = colormap;
   2237             display.convert_to_8bit = convert_to_8bit;
   2238 
   2239             result = png_safe_execute(image, png_image_write_main, &display);
   2240             png_image_free(image);
   2241             return result;
   2242          }
   2243 
   2244          else
   2245             return 0;
   2246       }
   2247 
   2248       else
   2249          return png_image_error(image,
   2250             "png_image_write_to_stdio: invalid argument");
   2251    }
   2252 
   2253    else if (image != NULL)
   2254       return png_image_error(image,
   2255          "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
   2256 
   2257    else
   2258       return 0;
   2259 }
   2260 
   2261 int PNGAPI
   2262 png_image_write_to_file(png_imagep image, const char *file_name,
   2263    int convert_to_8bit, const void *buffer, png_int_32 row_stride,
   2264    const void *colormap)
   2265 {
   2266    /* Write the image to the named file. */
   2267    if (image != NULL && image->version == PNG_IMAGE_VERSION)
   2268    {
   2269       if (file_name != NULL)
   2270       {
   2271          FILE *fp = fopen(file_name, "wb");
   2272 
   2273          if (fp != NULL)
   2274          {
   2275             if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
   2276                row_stride, colormap))
   2277             {
   2278                int error; /* from fflush/fclose */
   2279 
   2280                /* Make sure the file is flushed correctly. */
   2281                if (fflush(fp) == 0 && ferror(fp) == 0)
   2282                {
   2283                   if (fclose(fp) == 0)
   2284                      return 1;
   2285 
   2286                   error = errno; /* from fclose */
   2287                }
   2288 
   2289                else
   2290                {
   2291                   error = errno; /* from fflush or ferror */
   2292                   (void)fclose(fp);
   2293                }
   2294 
   2295                (void)remove(file_name);
   2296                /* The image has already been cleaned up; this is just used to
   2297                 * set the error (because the original write succeeded).
   2298                 */
   2299                return png_image_error(image, strerror(error));
   2300             }
   2301 
   2302             else
   2303             {
   2304                /* Clean up: just the opened file. */
   2305                (void)fclose(fp);
   2306                (void)remove(file_name);
   2307                return 0;
   2308             }
   2309          }
   2310 
   2311          else
   2312             return png_image_error(image, strerror(errno));
   2313       }
   2314 
   2315       else
   2316          return png_image_error(image,
   2317             "png_image_write_to_file: invalid argument");
   2318    }
   2319 
   2320    else if (image != NULL)
   2321       return png_image_error(image,
   2322          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
   2323 
   2324    else
   2325       return 0;
   2326 }
   2327 #endif /* PNG_STDIO_SUPPORTED */
   2328 #endif /* SIMPLIFIED_WRITE */
   2329 #endif /* PNG_WRITE_SUPPORTED */
   2330