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