src/3rdparty/libpng/pngwrite.c
changeset 30 5dc02b23752f
parent 0 1918ee327afb
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
     1 
     1 
     2 /* pngwrite.c - general routines to write a PNG file
     2 /* pngwrite.c - general routines to write a PNG file
     3  *
     3  *
     4  * Last changed in libpng 1.2.37 [June 4, 2009]
     4  * Last changed in libpng 1.4.0 [January 3, 2010]
     5  * Copyright (c) 1998-2009 Glenn Randers-Pehrson
     5  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
     8  *
     8  *
     9  * This code is released under the libpng license.
     9  * This code is released under the libpng license.
    10  * For conditions of distribution and use, see the disclaimer
    10  * For conditions of distribution and use, see the disclaimer
    11  * and license in png.h
    11  * and license in png.h
    12  */
    12  */
    13 
    13 
    14 /* Get internal access to png.h */
    14 /* Get internal access to png.h */
    15 #define PNG_INTERNAL
    15 #define PNG_NO_PEDANTIC_WARNINGS
    16 #include "png.h"
    16 #include "png.h"
    17 #ifdef PNG_WRITE_SUPPORTED
    17 #ifdef PNG_WRITE_SUPPORTED
       
    18 #include "pngpriv.h"
    18 
    19 
    19 /* Writes all the PNG information.  This is the suggested way to use the
    20 /* Writes all the PNG information.  This is the suggested way to use the
    20  * library.  If you have a new chunk to add, make a function to write it,
    21  * library.  If you have a new chunk to add, make a function to write it,
    21  * and put it in the correct location here.  If you want the chunk written
    22  * and put it in the correct location here.  If you want the chunk written
    22  * after the image data, put it in png_write_end().  I strongly encourage
    23  * after the image data, put it in png_write_end().  I strongly encourage
    27  */
    28  */
    28 void PNGAPI
    29 void PNGAPI
    29 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
    30 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
    30 {
    31 {
    31    png_debug(1, "in png_write_info_before_PLTE");
    32    png_debug(1, "in png_write_info_before_PLTE");
       
    33 
    32    if (png_ptr == NULL || info_ptr == NULL)
    34    if (png_ptr == NULL || info_ptr == NULL)
    33       return;
    35       return;
    34    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
    36    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
    35    {
    37    {
    36    png_write_sig(png_ptr); /* Write PNG signature */
    38    /* Write PNG signature */
    37 #if defined(PNG_MNG_FEATURES_SUPPORTED)
    39    png_write_sig(png_ptr);
       
    40 #ifdef PNG_MNG_FEATURES_SUPPORTED
    38    if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
    41    if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
    39    {
    42    {
    40       png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
    43       png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
    41       png_ptr->mng_features_permitted=0;
    44       png_ptr->mng_features_permitted = 0;
    42    }
    45    }
    43 #endif
    46 #endif
    44    /* Write IHDR information. */
    47    /* Write IHDR information. */
    45    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
    48    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
    46       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
    49       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
    47       info_ptr->filter_type,
    50       info_ptr->filter_type,
    48 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
    51 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
    49       info_ptr->interlace_type);
    52       info_ptr->interlace_type);
    50 #else
    53 #else
    51       0);
    54       0);
    52 #endif
    55 #endif
    53    /* The rest of these check to see if the valid field has the appropriate
    56    /* The rest of these check to see if the valid field has the appropriate
    54     * flag set, and if it does, writes the chunk.
    57     * flag set, and if it does, writes the chunk.
    55     */
    58     */
    56 #if defined(PNG_WRITE_gAMA_SUPPORTED)
    59 #ifdef PNG_WRITE_gAMA_SUPPORTED
    57    if (info_ptr->valid & PNG_INFO_gAMA)
    60    if (info_ptr->valid & PNG_INFO_gAMA)
    58    {
    61    {
    59 #  ifdef PNG_FLOATING_POINT_SUPPORTED
    62 #  ifdef PNG_FLOATING_POINT_SUPPORTED
    60       png_write_gAMA(png_ptr, info_ptr->gamma);
    63       png_write_gAMA(png_ptr, info_ptr->gamma);
    61 #else
    64 #else
    63       png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
    66       png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
    64 #  endif
    67 #  endif
    65 #endif
    68 #endif
    66    }
    69    }
    67 #endif
    70 #endif
    68 #if defined(PNG_WRITE_sRGB_SUPPORTED)
    71 #ifdef PNG_WRITE_sRGB_SUPPORTED
    69    if (info_ptr->valid & PNG_INFO_sRGB)
    72    if (info_ptr->valid & PNG_INFO_sRGB)
    70       png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
    73       png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
    71 #endif
    74 #endif
    72 #if defined(PNG_WRITE_iCCP_SUPPORTED)
    75 #ifdef PNG_WRITE_iCCP_SUPPORTED
    73    if (info_ptr->valid & PNG_INFO_iCCP)
    76    if (info_ptr->valid & PNG_INFO_iCCP)
    74       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
    77       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
    75                      info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
    78                      info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
    76 #endif
    79 #endif
    77 #if defined(PNG_WRITE_sBIT_SUPPORTED)
    80 #ifdef PNG_WRITE_sBIT_SUPPORTED
    78    if (info_ptr->valid & PNG_INFO_sBIT)
    81    if (info_ptr->valid & PNG_INFO_sBIT)
    79       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
    82       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
    80 #endif
    83 #endif
    81 #if defined(PNG_WRITE_cHRM_SUPPORTED)
    84 #ifdef PNG_WRITE_cHRM_SUPPORTED
    82    if (info_ptr->valid & PNG_INFO_cHRM)
    85    if (info_ptr->valid & PNG_INFO_cHRM)
    83    {
    86    {
    84 #ifdef PNG_FLOATING_POINT_SUPPORTED
    87 #ifdef PNG_FLOATING_POINT_SUPPORTED
    85       png_write_cHRM(png_ptr,
    88       png_write_cHRM(png_ptr,
    86          info_ptr->x_white, info_ptr->y_white,
    89          info_ptr->x_white, info_ptr->y_white,
    96          info_ptr->int_x_blue, info_ptr->int_y_blue);
    99          info_ptr->int_x_blue, info_ptr->int_y_blue);
    97 #  endif
   100 #  endif
    98 #endif
   101 #endif
    99    }
   102    }
   100 #endif
   103 #endif
   101 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
   104 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   102    if (info_ptr->unknown_chunks_num)
   105    if (info_ptr->unknown_chunks_num)
   103    {
   106    {
   104       png_unknown_chunk *up;
   107       png_unknown_chunk *up;
   105 
   108 
   106       png_debug(5, "writing extra chunks");
   109       png_debug(5, "writing extra chunks");
   107 
   110 
   108       for (up = info_ptr->unknown_chunks;
   111       for (up = info_ptr->unknown_chunks;
   109            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
   112            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
   110            up++)
   113            up++)
   111       {
   114       {
   112          int keep=png_handle_as_unknown(png_ptr, up->name);
   115          int keep = png_handle_as_unknown(png_ptr, up->name);
   113          if (keep != PNG_HANDLE_CHUNK_NEVER &&
   116          if (keep != PNG_HANDLE_CHUNK_NEVER &&
   114             up->location && !(up->location & PNG_HAVE_PLTE) &&
   117             up->location && !(up->location & PNG_HAVE_PLTE) &&
   115             !(up->location & PNG_HAVE_IDAT) &&
   118             !(up->location & PNG_HAVE_IDAT) &&
   116             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
   119             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
   117             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
   120             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
   145       png_write_PLTE(png_ptr, info_ptr->palette,
   148       png_write_PLTE(png_ptr, info_ptr->palette,
   146          (png_uint_32)info_ptr->num_palette);
   149          (png_uint_32)info_ptr->num_palette);
   147    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   150    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   148       png_error(png_ptr, "Valid palette required for paletted images");
   151       png_error(png_ptr, "Valid palette required for paletted images");
   149 
   152 
   150 #if defined(PNG_WRITE_tRNS_SUPPORTED)
   153 #ifdef PNG_WRITE_tRNS_SUPPORTED
   151    if (info_ptr->valid & PNG_INFO_tRNS)
   154    if (info_ptr->valid & PNG_INFO_tRNS)
   152    {
   155    {
   153 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
   156 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
   154       /* Invert the alpha channel (in tRNS) */
   157       /* Invert the alpha channel (in tRNS) */
   155       if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
   158       if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
   156          info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   159          info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   157       {
   160       {
   158          int j;
   161          int j;
   159          for (j=0; j<(int)info_ptr->num_trans; j++)
   162          for (j = 0; j<(int)info_ptr->num_trans; j++)
   160             info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
   163             info_ptr->trans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]);
   161       }
   164       }
   162 #endif
   165 #endif
   163       png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
   166       png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
   164          info_ptr->num_trans, info_ptr->color_type);
   167          info_ptr->num_trans, info_ptr->color_type);
   165    }
   168    }
   166 #endif
   169 #endif
   167 #if defined(PNG_WRITE_bKGD_SUPPORTED)
   170 #ifdef PNG_WRITE_bKGD_SUPPORTED
   168    if (info_ptr->valid & PNG_INFO_bKGD)
   171    if (info_ptr->valid & PNG_INFO_bKGD)
   169       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
   172       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
   170 #endif
   173 #endif
   171 #if defined(PNG_WRITE_hIST_SUPPORTED)
   174 #ifdef PNG_WRITE_hIST_SUPPORTED
   172    if (info_ptr->valid & PNG_INFO_hIST)
   175    if (info_ptr->valid & PNG_INFO_hIST)
   173       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
   176       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
   174 #endif
   177 #endif
   175 #if defined(PNG_WRITE_oFFs_SUPPORTED)
   178 #ifdef PNG_WRITE_oFFs_SUPPORTED
   176    if (info_ptr->valid & PNG_INFO_oFFs)
   179    if (info_ptr->valid & PNG_INFO_oFFs)
   177       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
   180       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
   178          info_ptr->offset_unit_type);
   181          info_ptr->offset_unit_type);
   179 #endif
   182 #endif
   180 #if defined(PNG_WRITE_pCAL_SUPPORTED)
   183 #ifdef PNG_WRITE_pCAL_SUPPORTED
   181    if (info_ptr->valid & PNG_INFO_pCAL)
   184    if (info_ptr->valid & PNG_INFO_pCAL)
   182       png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
   185       png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
   183          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
   186          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
   184          info_ptr->pcal_units, info_ptr->pcal_params);
   187          info_ptr->pcal_units, info_ptr->pcal_params);
   185 #endif
   188 #endif
   186 
   189 
   187 #if defined(PNG_sCAL_SUPPORTED)
   190 #ifdef PNG_sCAL_SUPPORTED
   188    if (info_ptr->valid & PNG_INFO_sCAL)
   191    if (info_ptr->valid & PNG_INFO_sCAL)
   189 #if defined(PNG_WRITE_sCAL_SUPPORTED)
   192 #ifdef PNG_WRITE_sCAL_SUPPORTED
   190 #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
   193 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
   191       png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
   194       png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
   192           info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
   195           info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
   193 #else /* !FLOATING_POINT */
   196 #else /* !FLOATING_POINT */
   194 #ifdef PNG_FIXED_POINT_SUPPORTED
   197 #ifdef PNG_FIXED_POINT_SUPPORTED
   195       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
   198       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
   196           info_ptr->scal_s_width, info_ptr->scal_s_height);
   199           info_ptr->scal_s_width, info_ptr->scal_s_height);
   197 #endif /* FIXED_POINT */
   200 #endif /* FIXED_POINT */
   198 #endif /* FLOATING_POINT */
   201 #endif /* FLOATING_POINT */
   199 #else  /* !WRITE_sCAL */
   202 #else  /* !WRITE_sCAL */
   200       png_warning(png_ptr,
   203       png_warning(png_ptr,
   201           "png_write_sCAL not supported; sCAL chunk not written.");
   204           "png_write_sCAL not supported; sCAL chunk not written");
   202 #endif /* WRITE_sCAL */
   205 #endif /* WRITE_sCAL */
   203 #endif /* sCAL */
   206 #endif /* sCAL */
   204 
   207 
   205 #if defined(PNG_WRITE_pHYs_SUPPORTED)
   208 #ifdef PNG_WRITE_pHYs_SUPPORTED
   206    if (info_ptr->valid & PNG_INFO_pHYs)
   209    if (info_ptr->valid & PNG_INFO_pHYs)
   207       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
   210       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
   208          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
   211          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
   209 #endif /* pHYs */
   212 #endif /* pHYs */
   210 
   213 
   211 #if defined(PNG_WRITE_tIME_SUPPORTED)
   214 #ifdef PNG_WRITE_tIME_SUPPORTED
   212    if (info_ptr->valid & PNG_INFO_tIME)
   215    if (info_ptr->valid & PNG_INFO_tIME)
   213    {
   216    {
   214       png_write_tIME(png_ptr, &(info_ptr->mod_time));
   217       png_write_tIME(png_ptr, &(info_ptr->mod_time));
   215       png_ptr->mode |= PNG_WROTE_tIME;
   218       png_ptr->mode |= PNG_WROTE_tIME;
   216    }
   219    }
   217 #endif /* tIME */
   220 #endif /* tIME */
   218 
   221 
   219 #if defined(PNG_WRITE_sPLT_SUPPORTED)
   222 #ifdef PNG_WRITE_sPLT_SUPPORTED
   220    if (info_ptr->valid & PNG_INFO_sPLT)
   223    if (info_ptr->valid & PNG_INFO_sPLT)
   221      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
   224      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
   222        png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
   225        png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
   223 #endif /* sPLT */
   226 #endif /* sPLT */
   224 
   227 
   225 #if defined(PNG_WRITE_TEXT_SUPPORTED)
   228 #ifdef PNG_WRITE_TEXT_SUPPORTED
   226    /* Check to see if we need to write text chunks */
   229    /* Check to see if we need to write text chunks */
   227    for (i = 0; i < info_ptr->num_text; i++)
   230    for (i = 0; i < info_ptr->num_text; i++)
   228    {
   231    {
   229       png_debug2(2, "Writing header text chunk %d, type %d", i,
   232       png_debug2(2, "Writing header text chunk %d, type %d", i,
   230          info_ptr->text[i].compression);
   233          info_ptr->text[i].compression);
   231       /* An internationalized chunk? */
   234       /* An internationalized chunk? */
   232       if (info_ptr->text[i].compression > 0)
   235       if (info_ptr->text[i].compression > 0)
   233       {
   236       {
   234 #if defined(PNG_WRITE_iTXt_SUPPORTED)
   237 #ifdef PNG_WRITE_iTXt_SUPPORTED
   235           /* Write international chunk */
   238           /* Write international chunk */
   236           png_write_iTXt(png_ptr,
   239           png_write_iTXt(png_ptr,
   237                          info_ptr->text[i].compression,
   240                          info_ptr->text[i].compression,
   238                          info_ptr->text[i].key,
   241                          info_ptr->text[i].key,
   239                          info_ptr->text[i].lang,
   242                          info_ptr->text[i].lang,
   246           info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
   249           info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
   247       }
   250       }
   248       /* If we want a compressed text chunk */
   251       /* If we want a compressed text chunk */
   249       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
   252       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
   250       {
   253       {
   251 #if defined(PNG_WRITE_zTXt_SUPPORTED)
   254 #ifdef PNG_WRITE_zTXt_SUPPORTED
   252          /* Write compressed chunk */
   255          /* Write compressed chunk */
   253          png_write_zTXt(png_ptr, info_ptr->text[i].key,
   256          png_write_zTXt(png_ptr, info_ptr->text[i].key,
   254             info_ptr->text[i].text, 0,
   257             info_ptr->text[i].text, 0,
   255             info_ptr->text[i].compression);
   258             info_ptr->text[i].compression);
   256 #else
   259 #else
   259          /* Mark this chunk as written */
   262          /* Mark this chunk as written */
   260          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
   263          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
   261       }
   264       }
   262       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
   265       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
   263       {
   266       {
   264 #if defined(PNG_WRITE_tEXt_SUPPORTED)
   267 #ifdef PNG_WRITE_tEXt_SUPPORTED
   265          /* Write uncompressed chunk */
   268          /* Write uncompressed chunk */
   266          png_write_tEXt(png_ptr, info_ptr->text[i].key,
   269          png_write_tEXt(png_ptr, info_ptr->text[i].key,
   267                          info_ptr->text[i].text,
   270                          info_ptr->text[i].text,
   268                          0);
   271                          0);
   269          /* Mark this chunk as written */
   272          /* Mark this chunk as written */
   274 #endif
   277 #endif
   275       }
   278       }
   276    }
   279    }
   277 #endif /* tEXt */
   280 #endif /* tEXt */
   278 
   281 
   279 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
   282 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   280    if (info_ptr->unknown_chunks_num)
   283    if (info_ptr->unknown_chunks_num)
   281    {
   284    {
   282        png_unknown_chunk *up;
   285       png_unknown_chunk *up;
   283 
   286 
   284        png_debug(5, "writing extra chunks");
   287       png_debug(5, "writing extra chunks");
   285 
   288 
   286        for (up = info_ptr->unknown_chunks;
   289       for (up = info_ptr->unknown_chunks;
   287             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
   290            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
   288             up++)
   291            up++)
   289        {
   292       {
   290          int keep=png_handle_as_unknown(png_ptr, up->name);
   293          int keep = png_handle_as_unknown(png_ptr, up->name);
   291          if (keep != PNG_HANDLE_CHUNK_NEVER &&
   294          if (keep != PNG_HANDLE_CHUNK_NEVER &&
   292             up->location && (up->location & PNG_HAVE_PLTE) &&
   295             up->location && (up->location & PNG_HAVE_PLTE) &&
   293             !(up->location & PNG_HAVE_IDAT) &&
   296             !(up->location & PNG_HAVE_IDAT) &&
   294             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
   297             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
   295             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
   298             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
   296          {
   299          {
   297             png_write_chunk(png_ptr, up->name, up->data, up->size);
   300             png_write_chunk(png_ptr, up->name, up->data, up->size);
   298          }
   301          }
   299        }
   302       }
   300    }
   303    }
   301 #endif
   304 #endif
   302 }
   305 }
   303 
   306 
   304 /* Writes the end of the PNG file.  If you don't want to write comments or
   307 /* Writes the end of the PNG file.  If you don't want to write comments or
   308  */
   311  */
   309 void PNGAPI
   312 void PNGAPI
   310 png_write_end(png_structp png_ptr, png_infop info_ptr)
   313 png_write_end(png_structp png_ptr, png_infop info_ptr)
   311 {
   314 {
   312    png_debug(1, "in png_write_end");
   315    png_debug(1, "in png_write_end");
       
   316 
   313    if (png_ptr == NULL)
   317    if (png_ptr == NULL)
   314       return;
   318       return;
   315    if (!(png_ptr->mode & PNG_HAVE_IDAT))
   319    if (!(png_ptr->mode & PNG_HAVE_IDAT))
   316       png_error(png_ptr, "No IDATs written into file");
   320       png_error(png_ptr, "No IDATs written into file");
   317 
   321 
   318    /* See if user wants us to write information chunks */
   322    /* See if user wants us to write information chunks */
   319    if (info_ptr != NULL)
   323    if (info_ptr != NULL)
   320    {
   324    {
   321 #if defined(PNG_WRITE_TEXT_SUPPORTED)
   325 #ifdef PNG_WRITE_TEXT_SUPPORTED
   322       int i; /* Local index variable */
   326       int i; /* local index variable */
   323 #endif
   327 #endif
   324 #if defined(PNG_WRITE_tIME_SUPPORTED)
   328 #ifdef PNG_WRITE_tIME_SUPPORTED
   325       /* Check to see if user has supplied a time chunk */
   329       /* Check to see if user has supplied a time chunk */
   326       if ((info_ptr->valid & PNG_INFO_tIME) &&
   330       if ((info_ptr->valid & PNG_INFO_tIME) &&
   327          !(png_ptr->mode & PNG_WROTE_tIME))
   331          !(png_ptr->mode & PNG_WROTE_tIME))
   328          png_write_tIME(png_ptr, &(info_ptr->mod_time));
   332          png_write_tIME(png_ptr, &(info_ptr->mod_time));
   329 #endif
   333 #endif
   330 #if defined(PNG_WRITE_TEXT_SUPPORTED)
   334 #ifdef PNG_WRITE_TEXT_SUPPORTED
   331       /* Loop through comment chunks */
   335       /* Loop through comment chunks */
   332       for (i = 0; i < info_ptr->num_text; i++)
   336       for (i = 0; i < info_ptr->num_text; i++)
   333       {
   337       {
   334          png_debug2(2, "Writing trailer text chunk %d, type %d", i,
   338          png_debug2(2, "Writing trailer text chunk %d, type %d", i,
   335             info_ptr->text[i].compression);
   339             info_ptr->text[i].compression);
   336          /* An internationalized chunk? */
   340          /* An internationalized chunk? */
   337          if (info_ptr->text[i].compression > 0)
   341          if (info_ptr->text[i].compression > 0)
   338          {
   342          {
   339 #if defined(PNG_WRITE_iTXt_SUPPORTED)
   343 #ifdef PNG_WRITE_iTXt_SUPPORTED
   340              /* Write international chunk */
   344             /* Write international chunk */
   341              png_write_iTXt(png_ptr,
   345             png_write_iTXt(png_ptr,
   342                          info_ptr->text[i].compression,
   346                         info_ptr->text[i].compression,
   343                          info_ptr->text[i].key,
   347                         info_ptr->text[i].key,
   344                          info_ptr->text[i].lang,
   348                         info_ptr->text[i].lang,
   345                          info_ptr->text[i].lang_key,
   349                         info_ptr->text[i].lang_key,
   346                          info_ptr->text[i].text);
   350                         info_ptr->text[i].text);
   347 #else
   351 #else
   348              png_warning(png_ptr, "Unable to write international text");
   352             png_warning(png_ptr, "Unable to write international text");
   349 #endif
   353 #endif
   350              /* Mark this chunk as written */
   354             /* Mark this chunk as written */
   351              info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
   355             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
   352          }
   356          }
   353          else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
   357          else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
   354          {
   358          {
   355 #if defined(PNG_WRITE_zTXt_SUPPORTED)
   359 #ifdef PNG_WRITE_zTXt_SUPPORTED
   356             /* Write compressed chunk */
   360             /* Write compressed chunk */
   357             png_write_zTXt(png_ptr, info_ptr->text[i].key,
   361             png_write_zTXt(png_ptr, info_ptr->text[i].key,
   358                info_ptr->text[i].text, 0,
   362                info_ptr->text[i].text, 0,
   359                info_ptr->text[i].compression);
   363                info_ptr->text[i].compression);
   360 #else
   364 #else
   363             /* Mark this chunk as written */
   367             /* Mark this chunk as written */
   364             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
   368             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
   365          }
   369          }
   366          else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
   370          else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
   367          {
   371          {
   368 #if defined(PNG_WRITE_tEXt_SUPPORTED)
   372 #ifdef PNG_WRITE_tEXt_SUPPORTED
   369             /* Write uncompressed chunk */
   373             /* Write uncompressed chunk */
   370             png_write_tEXt(png_ptr, info_ptr->text[i].key,
   374             png_write_tEXt(png_ptr, info_ptr->text[i].key,
   371                info_ptr->text[i].text, 0);
   375                info_ptr->text[i].text, 0);
   372 #else
   376 #else
   373             png_warning(png_ptr, "Unable to write uncompressed text");
   377             png_warning(png_ptr, "Unable to write uncompressed text");
   376             /* Mark this chunk as written */
   380             /* Mark this chunk as written */
   377             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
   381             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
   378          }
   382          }
   379       }
   383       }
   380 #endif
   384 #endif
   381 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
   385 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   382    if (info_ptr->unknown_chunks_num)
   386    if (info_ptr->unknown_chunks_num)
   383    {
   387    {
   384        png_unknown_chunk *up;
   388       png_unknown_chunk *up;
   385 
   389 
   386        png_debug(5, "writing extra chunks");
   390       png_debug(5, "writing extra chunks");
   387 
   391 
   388        for (up = info_ptr->unknown_chunks;
   392       for (up = info_ptr->unknown_chunks;
   389             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
   393            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
   390             up++)
   394            up++)
   391        {
   395       {
   392          int keep=png_handle_as_unknown(png_ptr, up->name);
   396          int keep = png_handle_as_unknown(png_ptr, up->name);
   393          if (keep != PNG_HANDLE_CHUNK_NEVER &&
   397          if (keep != PNG_HANDLE_CHUNK_NEVER &&
   394             up->location && (up->location & PNG_AFTER_IDAT) &&
   398             up->location && (up->location & PNG_AFTER_IDAT) &&
   395             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
   399             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
   396             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
   400             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
   397          {
   401          {
   398             png_write_chunk(png_ptr, up->name, up->data, up->size);
   402             png_write_chunk(png_ptr, up->name, up->data, up->size);
   399          }
   403          }
   400        }
   404       }
   401    }
   405    }
   402 #endif
   406 #endif
   403    }
   407    }
   404 
   408 
   405    png_ptr->mode |= PNG_AFTER_IDAT;
   409    png_ptr->mode |= PNG_AFTER_IDAT;
   409    /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
   413    /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
   410     * and restored again in libpng-1.2.30, may cause some applications that
   414     * and restored again in libpng-1.2.30, may cause some applications that
   411     * do not set png_ptr->output_flush_fn to crash.  If your application
   415     * do not set png_ptr->output_flush_fn to crash.  If your application
   412     * experiences a problem, please try building libpng with
   416     * experiences a problem, please try building libpng with
   413     * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
   417     * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
   414     * png-mng-implement at lists.sf.net .  This kludge will be removed
   418     * png-mng-implement at lists.sf.net .
   415     * from libpng-1.4.0.
       
   416     */
   419     */
   417 #if defined(PNG_WRITE_FLUSH_SUPPORTED) && \
   420 #ifdef PNG_WRITE_FLUSH_SUPPORTED
   418     defined(PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED)
   421 #  ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
   419    png_flush(png_ptr);
   422    png_flush(png_ptr);
   420 #endif
   423 #  endif
   421 }
   424 #endif
   422 
   425 }
   423 #if defined(PNG_WRITE_tIME_SUPPORTED)
   426 
   424 #if !defined(_WIN32_WCE)
   427 #ifdef PNG_CONVERT_tIME_SUPPORTED
   425 /* "time.h" functions are not supported on WindowsCE */
   428 /* "tm" structure is not supported on WindowsCE */
   426 void PNGAPI
   429 void PNGAPI
   427 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
   430 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
   428 {
   431 {
   429    png_debug(1, "in png_convert_from_struct_tm");
   432    png_debug(1, "in png_convert_from_struct_tm");
       
   433 
   430    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
   434    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
   431    ptime->month = (png_byte)(ttime->tm_mon + 1);
   435    ptime->month = (png_byte)(ttime->tm_mon + 1);
   432    ptime->day = (png_byte)ttime->tm_mday;
   436    ptime->day = (png_byte)ttime->tm_mday;
   433    ptime->hour = (png_byte)ttime->tm_hour;
   437    ptime->hour = (png_byte)ttime->tm_hour;
   434    ptime->minute = (png_byte)ttime->tm_min;
   438    ptime->minute = (png_byte)ttime->tm_min;
   439 png_convert_from_time_t(png_timep ptime, time_t ttime)
   443 png_convert_from_time_t(png_timep ptime, time_t ttime)
   440 {
   444 {
   441    struct tm *tbuf;
   445    struct tm *tbuf;
   442 
   446 
   443    png_debug(1, "in png_convert_from_time_t");
   447    png_debug(1, "in png_convert_from_time_t");
       
   448 
   444    tbuf = gmtime(&ttime);
   449    tbuf = gmtime(&ttime);
   445    png_convert_from_struct_tm(ptime, tbuf);
   450    png_convert_from_struct_tm(ptime, tbuf);
   446 }
   451 }
   447 #endif
       
   448 #endif
   452 #endif
   449 
   453 
   450 /* Initialize png_ptr structure, and allocate any memory needed */
   454 /* Initialize png_ptr structure, and allocate any memory needed */
   451 png_structp PNGAPI
   455 png_structp PNGAPI
   452 png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
   456 png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
   453    png_error_ptr error_fn, png_error_ptr warn_fn)
   457    png_error_ptr error_fn, png_error_ptr warn_fn)
   454 {
   458 {
   455 #ifdef PNG_USER_MEM_SUPPORTED
   459 #ifdef PNG_USER_MEM_SUPPORTED
   456    return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
   460    return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
   457       warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
   461       warn_fn, NULL, NULL, NULL));
   458 }
   462 }
   459 
   463 
   460 /* Alternate initialize png_ptr structure, and allocate any memory needed */
   464 /* Alternate initialize png_ptr structure, and allocate any memory needed */
   461 png_structp PNGAPI
   465 png_structp PNGAPI
   462 png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
   466 png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
   463    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
   467    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
   464    png_malloc_ptr malloc_fn, png_free_ptr free_fn)
   468    png_malloc_ptr malloc_fn, png_free_ptr free_fn)
   465 {
   469 {
   466 #endif /* PNG_USER_MEM_SUPPORTED */
   470 #endif /* PNG_USER_MEM_SUPPORTED */
       
   471    volatile int png_cleanup_needed = 0;
   467 #ifdef PNG_SETJMP_SUPPORTED
   472 #ifdef PNG_SETJMP_SUPPORTED
   468     volatile
   473    volatile
   469 #endif
   474 #endif
   470     png_structp png_ptr;
   475    png_structp png_ptr;
   471 #ifdef PNG_SETJMP_SUPPORTED
   476 #ifdef PNG_SETJMP_SUPPORTED
   472 #ifdef USE_FAR_KEYWORD
   477 #ifdef USE_FAR_KEYWORD
   473    jmp_buf jmpbuf;
   478    jmp_buf jmpbuf;
   474 #endif
   479 #endif
   475 #endif
   480 #endif
   476    int i;
   481    int i;
       
   482 
   477    png_debug(1, "in png_create_write_struct");
   483    png_debug(1, "in png_create_write_struct");
       
   484 
   478 #ifdef PNG_USER_MEM_SUPPORTED
   485 #ifdef PNG_USER_MEM_SUPPORTED
   479    png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
   486    png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
   480       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
   487       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
   481 #else
   488 #else
   482    png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
   489    png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
   484    if (png_ptr == NULL)
   491    if (png_ptr == NULL)
   485       return (NULL);
   492       return (NULL);
   486 
   493 
   487    /* Added at libpng-1.2.6 */
   494    /* Added at libpng-1.2.6 */
   488 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
   495 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
   489    png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
   496    png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
   490    png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
   497    png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
   491 #endif
   498 #endif
   492 
   499 
   493 #ifdef PNG_SETJMP_SUPPORTED
   500 #ifdef PNG_SETJMP_SUPPORTED
       
   501 /* Applications that neglect to set up their own setjmp() and then
       
   502    encounter a png_error() will longjmp here.  Since the jmpbuf is
       
   503    then meaningless we abort instead of returning. */
   494 #ifdef USE_FAR_KEYWORD
   504 #ifdef USE_FAR_KEYWORD
   495    if (setjmp(jmpbuf))
   505    if (setjmp(jmpbuf))
   496 #else
   506 #else
   497    if (setjmp(png_ptr->jmpbuf))
   507    if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
   498 #endif
   508 #endif
   499    {
       
   500       png_free(png_ptr, png_ptr->zbuf);
       
   501        png_ptr->zbuf=NULL;
       
   502       png_destroy_struct(png_ptr);
       
   503       return (NULL);
       
   504    }
       
   505 #ifdef USE_FAR_KEYWORD
   509 #ifdef USE_FAR_KEYWORD
   506    png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
   510    png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf));
   507 #endif
   511 #endif
       
   512       PNG_ABORT();
   508 #endif
   513 #endif
   509 
   514 
   510 #ifdef PNG_USER_MEM_SUPPORTED
   515 #ifdef PNG_USER_MEM_SUPPORTED
   511    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
   516    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
   512 #endif /* PNG_USER_MEM_SUPPORTED */
   517 #endif /* PNG_USER_MEM_SUPPORTED */
   513    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
   518    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
   514 
   519 
   515    if (user_png_ver)
   520    if (user_png_ver)
   516    {
   521    {
   517      i=0;
   522       i = 0;
   518      do
   523       do
   519      {
   524       {
   520        if (user_png_ver[i] != png_libpng_ver[i])
   525          if (user_png_ver[i] != png_libpng_ver[i])
   521           png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
   526             png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
   522      } while (png_libpng_ver[i++]);
   527       } while (png_libpng_ver[i++]);
   523    }
   528    }
   524 
   529 
   525    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
   530    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
   526    {
   531    {
   527      /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
   532      /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
   531       */
   536       */
   532      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
   537      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
   533          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
   538          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
   534          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
   539          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
   535      {
   540      {
   536 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
   541 #ifdef PNG_STDIO_SUPPORTED
   537         char msg[80];
   542         char msg[80];
   538         if (user_png_ver)
   543         if (user_png_ver)
   539         {
   544         {
   540           png_snprintf(msg, 80,
   545            png_snprintf(msg, 80,
   541              "Application was compiled with png.h from libpng-%.20s",
   546               "Application was compiled with png.h from libpng-%.20s",
   542              user_png_ver);
   547               user_png_ver);
   543           png_warning(png_ptr, msg);
   548            png_warning(png_ptr, msg);
   544         }
   549         }
   545         png_snprintf(msg, 80,
   550         png_snprintf(msg, 80,
   546            "Application  is  running with png.c from libpng-%.20s",
   551            "Application  is  running with png.c from libpng-%.20s",
   547            png_libpng_ver);
   552            png_libpng_ver);
   548         png_warning(png_ptr, msg);
   553         png_warning(png_ptr, msg);
   549 #endif
   554 #endif
   550 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
   555 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
   551         png_ptr->flags=0;
   556         png_ptr->flags = 0;
   552 #endif
   557 #endif
   553         png_error(png_ptr,
   558         png_warning(png_ptr,
   554            "Incompatible libpng version in application and library");
   559            "Incompatible libpng version in application and library");
       
   560         png_cleanup_needed = 1;
   555      }
   561      }
   556    }
   562    }
   557 
   563 
   558    /* Initialize zbuf - compression buffer */
   564    /* Initialize zbuf - compression buffer */
   559    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
   565    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
   560    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
   566    if (!png_cleanup_needed)
   561       (png_uint_32)png_ptr->zbuf_size);
   567    {
   562 
   568       png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
   563    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
   569          png_ptr->zbuf_size);
   564       png_flush_ptr_NULL);
   570       if (png_ptr->zbuf == NULL)
   565 
   571          png_cleanup_needed = 1;
   566 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
   572    }
       
   573    if (png_cleanup_needed)
       
   574    {
       
   575        /* Clean up PNG structure and deallocate any memory. */
       
   576        png_free(png_ptr, png_ptr->zbuf);
       
   577        png_ptr->zbuf = NULL;
       
   578 #ifdef PNG_USER_MEM_SUPPORTED
       
   579        png_destroy_struct_2((png_voidp)png_ptr,
       
   580           (png_free_ptr)free_fn, (png_voidp)mem_ptr);
       
   581 #else
       
   582        png_destroy_struct((png_voidp)png_ptr);
       
   583 #endif
       
   584        return (NULL);
       
   585    }
       
   586 
       
   587    png_set_write_fn(png_ptr, NULL, NULL, NULL);
       
   588 
       
   589 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   567    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
   590    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
   568       1, png_doublep_NULL, png_doublep_NULL);
   591       1, NULL, NULL);
   569 #endif
   592 #endif
   570 
   593 
   571 #ifdef PNG_SETJMP_SUPPORTED
       
   572 /* Applications that neglect to set up their own setjmp() and then encounter
       
   573    a png_error() will longjmp here.  Since the jmpbuf is then meaningless we
       
   574    abort instead of returning. */
       
   575 #ifdef USE_FAR_KEYWORD
       
   576    if (setjmp(jmpbuf))
       
   577       PNG_ABORT();
       
   578    png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
       
   579 #else
       
   580    if (setjmp(png_ptr->jmpbuf))
       
   581       PNG_ABORT();
       
   582 #endif
       
   583 #endif
       
   584    return (png_ptr);
   594    return (png_ptr);
   585 }
   595 }
   586 
   596 
   587 /* Initialize png_ptr structure, and allocate any memory needed */
       
   588 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
       
   589 /* Deprecated. */
       
   590 #undef png_write_init
       
   591 void PNGAPI
       
   592 png_write_init(png_structp png_ptr)
       
   593 {
       
   594    /* We only come here via pre-1.0.7-compiled applications */
       
   595    png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
       
   596 }
       
   597 
       
   598 void PNGAPI
       
   599 png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
       
   600    png_size_t png_struct_size, png_size_t png_info_size)
       
   601 {
       
   602    /* We only come here via pre-1.0.12-compiled applications */
       
   603    if (png_ptr == NULL) return;
       
   604 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
       
   605    if (png_sizeof(png_struct) > png_struct_size ||
       
   606       png_sizeof(png_info) > png_info_size)
       
   607    {
       
   608       char msg[80];
       
   609       png_ptr->warning_fn=NULL;
       
   610       if (user_png_ver)
       
   611       {
       
   612         png_snprintf(msg, 80,
       
   613            "Application was compiled with png.h from libpng-%.20s",
       
   614            user_png_ver);
       
   615         png_warning(png_ptr, msg);
       
   616       }
       
   617       png_snprintf(msg, 80,
       
   618          "Application  is  running with png.c from libpng-%.20s",
       
   619          png_libpng_ver);
       
   620       png_warning(png_ptr, msg);
       
   621    }
       
   622 #endif
       
   623    if (png_sizeof(png_struct) > png_struct_size)
       
   624      {
       
   625        png_ptr->error_fn=NULL;
       
   626 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
       
   627        png_ptr->flags=0;
       
   628 #endif
       
   629        png_error(png_ptr,
       
   630        "The png struct allocated by the application for writing is too small.");
       
   631      }
       
   632    if (png_sizeof(png_info) > png_info_size)
       
   633      {
       
   634        png_ptr->error_fn=NULL;
       
   635 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
       
   636        png_ptr->flags=0;
       
   637 #endif
       
   638        png_error(png_ptr,
       
   639        "The info struct allocated by the application for writing is too small.");
       
   640      }
       
   641    png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
       
   642 }
       
   643 #endif /* PNG_1_0_X || PNG_1_2_X */
       
   644 
       
   645 
       
   646 void PNGAPI
       
   647 png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
       
   648    png_size_t png_struct_size)
       
   649 {
       
   650    png_structp png_ptr=*ptr_ptr;
       
   651 #ifdef PNG_SETJMP_SUPPORTED
       
   652    jmp_buf tmp_jmp; /* To save current jump buffer */
       
   653 #endif
       
   654 
       
   655    int i = 0;
       
   656 
       
   657    if (png_ptr == NULL)
       
   658       return;
       
   659 
       
   660    do
       
   661    {
       
   662      if (user_png_ver[i] != png_libpng_ver[i])
       
   663      {
       
   664 #ifdef PNG_LEGACY_SUPPORTED
       
   665        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
       
   666 #else
       
   667        png_ptr->warning_fn=NULL;
       
   668        png_warning(png_ptr,
       
   669  "Application uses deprecated png_write_init() and should be recompiled.");
       
   670        break;
       
   671 #endif
       
   672      }
       
   673    } while (png_libpng_ver[i++]);
       
   674 
       
   675    png_debug(1, "in png_write_init_3");
       
   676 
       
   677 #ifdef PNG_SETJMP_SUPPORTED
       
   678    /* Save jump buffer and error functions */
       
   679    png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
       
   680 #endif
       
   681 
       
   682    if (png_sizeof(png_struct) > png_struct_size)
       
   683      {
       
   684        png_destroy_struct(png_ptr);
       
   685        png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
       
   686        *ptr_ptr = png_ptr;
       
   687      }
       
   688 
       
   689    /* Reset all variables to 0 */
       
   690    png_memset(png_ptr, 0, png_sizeof(png_struct));
       
   691 
       
   692    /* Added at libpng-1.2.6 */
       
   693 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
       
   694    png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
       
   695    png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
       
   696 #endif
       
   697 
       
   698 #ifdef PNG_SETJMP_SUPPORTED
       
   699    /* Restore jump buffer */
       
   700    png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
       
   701 #endif
       
   702 
       
   703    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
       
   704       png_flush_ptr_NULL);
       
   705 
       
   706    /* Initialize zbuf - compression buffer */
       
   707    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
       
   708    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
       
   709       (png_uint_32)png_ptr->zbuf_size);
       
   710 
       
   711 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
       
   712    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
       
   713       1, png_doublep_NULL, png_doublep_NULL);
       
   714 #endif
       
   715 }
       
   716 
   597 
   717 /* Write a few rows of image data.  If the image is interlaced,
   598 /* Write a few rows of image data.  If the image is interlaced,
   718  * either you will have to write the 7 sub images, or, if you
   599  * either you will have to write the 7 sub images, or, if you
   719  * have called png_set_interlace_handling(), you will have to
   600  * have called png_set_interlace_handling(), you will have to
   720  * "write" the image seven times.
   601  * "write" the image seven times.
   721  */
   602  */
   722 void PNGAPI
   603 void PNGAPI
   723 png_write_rows(png_structp png_ptr, png_bytepp row,
   604 png_write_rows(png_structp png_ptr, png_bytepp row,
   724    png_uint_32 num_rows)
   605    png_uint_32 num_rows)
   725 {
   606 {
   726    png_uint_32 i; /* Row counter */
   607    png_uint_32 i; /* row counter */
   727    png_bytepp rp; /* Row pointer */
   608    png_bytepp rp; /* row pointer */
   728 
   609 
   729    png_debug(1, "in png_write_rows");
   610    png_debug(1, "in png_write_rows");
   730 
   611 
   731    if (png_ptr == NULL)
   612    if (png_ptr == NULL)
   732       return;
   613       return;
   742  * if you are writing an interlaced image.
   623  * if you are writing an interlaced image.
   743  */
   624  */
   744 void PNGAPI
   625 void PNGAPI
   745 png_write_image(png_structp png_ptr, png_bytepp image)
   626 png_write_image(png_structp png_ptr, png_bytepp image)
   746 {
   627 {
   747    png_uint_32 i; /* Row index */
   628    png_uint_32 i; /* row index */
   748    int pass, num_pass; /* Pass variables */
   629    int pass, num_pass; /* pass variables */
   749    png_bytepp rp; /* Points to current row */
   630    png_bytepp rp; /* points to current row */
   750 
   631 
   751    if (png_ptr == NULL)
   632    if (png_ptr == NULL)
   752       return;
   633       return;
   753 
   634 
   754    png_debug(1, "in png_write_image");
   635    png_debug(1, "in png_write_image");
   755 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
   636 
       
   637 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   756    /* Initialize interlace handling.  If image is not interlaced,
   638    /* Initialize interlace handling.  If image is not interlaced,
   757     * this will set pass to 1
   639     * this will set pass to 1
   758     */
   640     */
   759    num_pass = png_set_interlace_handling(png_ptr);
   641    num_pass = png_set_interlace_handling(png_ptr);
   760 #else
   642 #else
   775 void PNGAPI
   657 void PNGAPI
   776 png_write_row(png_structp png_ptr, png_bytep row)
   658 png_write_row(png_structp png_ptr, png_bytep row)
   777 {
   659 {
   778    if (png_ptr == NULL)
   660    if (png_ptr == NULL)
   779       return;
   661       return;
       
   662 
   780    png_debug2(1, "in png_write_row (row %ld, pass %d)",
   663    png_debug2(1, "in png_write_row (row %ld, pass %d)",
   781       png_ptr->row_number, png_ptr->pass);
   664       png_ptr->row_number, png_ptr->pass);
   782 
   665 
   783    /* Initialize transformations and other stuff if first time */
   666    /* Initialize transformations and other stuff if first time */
   784    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
   667    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
   785    {
   668    {
   786       /* Make sure we wrote the header info */
   669       /* Make sure we wrote the header info */
   787       if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
   670       if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
   788          png_error(png_ptr,
   671          png_error(png_ptr,
   789             "png_write_info was never called before png_write_row.");
   672             "png_write_info was never called before png_write_row");
   790 
   673 
   791       /* Check for transforms that have been set but were defined out */
   674       /* Check for transforms that have been set but were defined out */
   792 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
   675 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
   793       if (png_ptr->transformations & PNG_INVERT_MONO)
   676       if (png_ptr->transformations & PNG_INVERT_MONO)
   794          png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
   677          png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
   795 #endif
   678 #endif
   796 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
   679 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
   797       if (png_ptr->transformations & PNG_FILLER)
   680       if (png_ptr->transformations & PNG_FILLER)
   798          png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
   681          png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
   799 #endif
   682 #endif
   800 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
   683 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
   801       if (png_ptr->transformations & PNG_PACKSWAP)
   684       if (png_ptr->transformations & PNG_PACKSWAP)
   802          png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
   685          png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
   803 #endif
   686 #endif
   804 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
   687 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
   805       if (png_ptr->transformations & PNG_PACK)
   688       if (png_ptr->transformations & PNG_PACK)
   806          png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
   689          png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
   807 #endif
   690 #endif
   808 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
   691 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
   809       if (png_ptr->transformations & PNG_SHIFT)
   692       if (png_ptr->transformations & PNG_SHIFT)
   810          png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
   693          png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
   811 #endif
   694 #endif
   812 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
   695 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
   813       if (png_ptr->transformations & PNG_BGR)
   696       if (png_ptr->transformations & PNG_BGR)
   814          png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
   697          png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
   815 #endif
   698 #endif
   816 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
   699 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
   817       if (png_ptr->transformations & PNG_SWAP_BYTES)
   700       if (png_ptr->transformations & PNG_SWAP_BYTES)
   818          png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
   701          png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
   819 #endif
   702 #endif
   820 
   703 
   821       png_write_start_row(png_ptr);
   704       png_write_start_row(png_ptr);
   822    }
   705    }
   823 
   706 
   824 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
   707 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   825    /* If interlaced and not interested in row, return */
   708    /* If interlaced and not interested in row, return */
   826    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
   709    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
   827    {
   710    {
   828       switch (png_ptr->pass)
   711       switch (png_ptr->pass)
   829       {
   712       {
   897    png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth);
   780    png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth);
   898    png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth);
   781    png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth);
   899    png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes);
   782    png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes);
   900 
   783 
   901    /* Copy user's row into buffer, leaving room for filter byte. */
   784    /* Copy user's row into buffer, leaving room for filter byte. */
   902    png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
   785    png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes);
   903       png_ptr->row_info.rowbytes);
   786 
   904 
   787 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   905 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
       
   906    /* Handle interlacing */
   788    /* Handle interlacing */
   907    if (png_ptr->interlaced && png_ptr->pass < 6 &&
   789    if (png_ptr->interlaced && png_ptr->pass < 6 &&
   908       (png_ptr->transformations & PNG_INTERLACE))
   790       (png_ptr->transformations & PNG_INTERLACE))
   909    {
   791    {
   910       png_do_write_interlace(&(png_ptr->row_info),
   792       png_do_write_interlace(&(png_ptr->row_info),
   920 
   802 
   921    /* Handle other transformations */
   803    /* Handle other transformations */
   922    if (png_ptr->transformations)
   804    if (png_ptr->transformations)
   923       png_do_write_transformations(png_ptr);
   805       png_do_write_transformations(png_ptr);
   924 
   806 
   925 #if defined(PNG_MNG_FEATURES_SUPPORTED)
   807 #ifdef PNG_MNG_FEATURES_SUPPORTED
   926    /* Write filter_method 64 (intrapixel differencing) only if
   808    /* Write filter_method 64 (intrapixel differencing) only if
   927     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
   809     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
   928     * 2. Libpng did not write a PNG signature (this filter_method is only
   810     * 2. Libpng did not write a PNG signature (this filter_method is only
   929     *    used in PNG datastreams that are embedded in MNG datastreams) and
   811     *    used in PNG datastreams that are embedded in MNG datastreams) and
   930     * 3. The application called png_permit_mng_features with a mask that
   812     * 3. The application called png_permit_mng_features with a mask that
   945 
   827 
   946    if (png_ptr->write_row_fn != NULL)
   828    if (png_ptr->write_row_fn != NULL)
   947       (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
   829       (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
   948 }
   830 }
   949 
   831 
   950 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
   832 #ifdef PNG_WRITE_FLUSH_SUPPORTED
   951 /* Set the automatic flush interval or 0 to turn flushing off */
   833 /* Set the automatic flush interval or 0 to turn flushing off */
   952 void PNGAPI
   834 void PNGAPI
   953 png_set_flush(png_structp png_ptr, int nrows)
   835 png_set_flush(png_structp png_ptr, int nrows)
   954 {
   836 {
   955    png_debug(1, "in png_set_flush");
   837    png_debug(1, "in png_set_flush");
       
   838 
   956    if (png_ptr == NULL)
   839    if (png_ptr == NULL)
   957       return;
   840       return;
   958    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
   841    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
   959 }
   842 }
   960 
   843 
   963 png_write_flush(png_structp png_ptr)
   846 png_write_flush(png_structp png_ptr)
   964 {
   847 {
   965    int wrote_IDAT;
   848    int wrote_IDAT;
   966 
   849 
   967    png_debug(1, "in png_write_flush");
   850    png_debug(1, "in png_write_flush");
       
   851 
   968    if (png_ptr == NULL)
   852    if (png_ptr == NULL)
   969       return;
   853       return;
   970    /* We have already written out all of the data */
   854    /* We have already written out all of the data */
   971    if (png_ptr->row_number >= png_ptr->num_rows)
   855    if (png_ptr->row_number >= png_ptr->num_rows)
   972       return;
   856       return;
  1023    png_free_ptr free_fn = NULL;
   907    png_free_ptr free_fn = NULL;
  1024    png_voidp mem_ptr = NULL;
   908    png_voidp mem_ptr = NULL;
  1025 #endif
   909 #endif
  1026 
   910 
  1027    png_debug(1, "in png_destroy_write_struct");
   911    png_debug(1, "in png_destroy_write_struct");
       
   912 
  1028    if (png_ptr_ptr != NULL)
   913    if (png_ptr_ptr != NULL)
  1029    {
   914    {
  1030       png_ptr = *png_ptr_ptr;
   915       png_ptr = *png_ptr_ptr;
  1031 #ifdef PNG_USER_MEM_SUPPORTED
   916 #ifdef PNG_USER_MEM_SUPPORTED
  1032       free_fn = png_ptr->free_fn;
   917       free_fn = png_ptr->free_fn;
  1049    {
   934    {
  1050       if (png_ptr != NULL)
   935       if (png_ptr != NULL)
  1051       {
   936       {
  1052         png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
   937         png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
  1053 
   938 
  1054 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
   939 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
  1055         if (png_ptr->num_chunk_list)
   940         if (png_ptr->num_chunk_list)
  1056         {
   941         {
  1057            png_free(png_ptr, png_ptr->chunk_list);
   942            png_free(png_ptr, png_ptr->chunk_list);
  1058            png_ptr->chunk_list=NULL;
       
  1059            png_ptr->num_chunk_list = 0;
   943            png_ptr->num_chunk_list = 0;
  1060         }
   944         }
  1061 #endif
   945 #endif
  1062       }
   946       }
  1063 
   947 
  1097 #ifdef PNG_USER_MEM_SUPPORTED
   981 #ifdef PNG_USER_MEM_SUPPORTED
  1098    png_free_ptr free_fn;
   982    png_free_ptr free_fn;
  1099 #endif
   983 #endif
  1100 
   984 
  1101    png_debug(1, "in png_write_destroy");
   985    png_debug(1, "in png_write_destroy");
       
   986 
  1102    /* Free any memory zlib uses */
   987    /* Free any memory zlib uses */
  1103    deflateEnd(&png_ptr->zstream);
   988    deflateEnd(&png_ptr->zstream);
  1104 
   989 
  1105    /* Free our memory.  png_free checks NULL for us. */
   990    /* Free our memory.  png_free checks NULL for us. */
  1106    png_free(png_ptr, png_ptr->zbuf);
   991    png_free(png_ptr, png_ptr->zbuf);
  1107    png_free(png_ptr, png_ptr->row_buf);
   992    png_free(png_ptr, png_ptr->row_buf);
  1108 #ifndef PNG_NO_WRITE_FILTER
   993 #ifdef PNG_WRITE_FILTER_SUPPORTED
  1109    png_free(png_ptr, png_ptr->prev_row);
   994    png_free(png_ptr, png_ptr->prev_row);
  1110    png_free(png_ptr, png_ptr->sub_row);
   995    png_free(png_ptr, png_ptr->sub_row);
  1111    png_free(png_ptr, png_ptr->up_row);
   996    png_free(png_ptr, png_ptr->up_row);
  1112    png_free(png_ptr, png_ptr->avg_row);
   997    png_free(png_ptr, png_ptr->avg_row);
  1113    png_free(png_ptr, png_ptr->paeth_row);
   998    png_free(png_ptr, png_ptr->paeth_row);
  1114 #endif
   999 #endif
  1115 
  1000 
  1116 #if defined(PNG_TIME_RFC1123_SUPPORTED)
  1001 #ifdef PNG_TIME_RFC1123_SUPPORTED
  1117    png_free(png_ptr, png_ptr->time_buffer);
  1002    png_free(png_ptr, png_ptr->time_buffer);
  1118 #endif
  1003 #endif
  1119 
  1004 
  1120 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1005 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1121    png_free(png_ptr, png_ptr->prev_filters);
  1006    png_free(png_ptr, png_ptr->prev_filters);
  1122    png_free(png_ptr, png_ptr->filter_weights);
  1007    png_free(png_ptr, png_ptr->filter_weights);
  1123    png_free(png_ptr, png_ptr->inv_filter_weights);
  1008    png_free(png_ptr, png_ptr->inv_filter_weights);
  1124    png_free(png_ptr, png_ptr->filter_costs);
  1009    png_free(png_ptr, png_ptr->filter_costs);
  1125    png_free(png_ptr, png_ptr->inv_filter_costs);
  1010    png_free(png_ptr, png_ptr->inv_filter_costs);
  1154 /* Allow the application to select one or more row filters to use. */
  1039 /* Allow the application to select one or more row filters to use. */
  1155 void PNGAPI
  1040 void PNGAPI
  1156 png_set_filter(png_structp png_ptr, int method, int filters)
  1041 png_set_filter(png_structp png_ptr, int method, int filters)
  1157 {
  1042 {
  1158    png_debug(1, "in png_set_filter");
  1043    png_debug(1, "in png_set_filter");
  1159    if (png_ptr == NULL)
  1044 
  1160       return;
  1045    if (png_ptr == NULL)
  1161 #if defined(PNG_MNG_FEATURES_SUPPORTED)
  1046       return;
       
  1047 #ifdef PNG_MNG_FEATURES_SUPPORTED
  1162    if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
  1048    if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
  1163       (method == PNG_INTRAPIXEL_DIFFERENCING))
  1049       (method == PNG_INTRAPIXEL_DIFFERENCING))
  1164          method = PNG_FILTER_TYPE_BASE;
  1050          method = PNG_FILTER_TYPE_BASE;
  1165 #endif
  1051 #endif
  1166    if (method == PNG_FILTER_TYPE_BASE)
  1052    if (method == PNG_FILTER_TYPE_BASE)
  1167    {
  1053    {
  1168       switch (filters & (PNG_ALL_FILTERS | 0x07))
  1054       switch (filters & (PNG_ALL_FILTERS | 0x07))
  1169       {
  1055       {
  1170 #ifndef PNG_NO_WRITE_FILTER
  1056 #ifdef PNG_WRITE_FILTER_SUPPORTED
  1171          case 5:
  1057          case 5:
  1172          case 6:
  1058          case 6:
  1173          case 7: png_warning(png_ptr, "Unknown row filter for method 0");
  1059          case 7: png_warning(png_ptr, "Unknown row filter for method 0");
  1174 #endif /* PNG_NO_WRITE_FILTER */
  1060 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  1175          case PNG_FILTER_VALUE_NONE:
  1061          case PNG_FILTER_VALUE_NONE:
  1176               png_ptr->do_filter=PNG_FILTER_NONE; break;
  1062               png_ptr->do_filter = PNG_FILTER_NONE; break;
  1177 #ifndef PNG_NO_WRITE_FILTER
  1063 #ifdef PNG_WRITE_FILTER_SUPPORTED
  1178          case PNG_FILTER_VALUE_SUB:
  1064          case PNG_FILTER_VALUE_SUB:
  1179               png_ptr->do_filter=PNG_FILTER_SUB; break;
  1065               png_ptr->do_filter = PNG_FILTER_SUB; break;
  1180          case PNG_FILTER_VALUE_UP:
  1066          case PNG_FILTER_VALUE_UP:
  1181               png_ptr->do_filter=PNG_FILTER_UP; break;
  1067               png_ptr->do_filter = PNG_FILTER_UP; break;
  1182          case PNG_FILTER_VALUE_AVG:
  1068          case PNG_FILTER_VALUE_AVG:
  1183               png_ptr->do_filter=PNG_FILTER_AVG; break;
  1069               png_ptr->do_filter = PNG_FILTER_AVG; break;
  1184          case PNG_FILTER_VALUE_PAETH:
  1070          case PNG_FILTER_VALUE_PAETH:
  1185               png_ptr->do_filter=PNG_FILTER_PAETH; break;
  1071               png_ptr->do_filter = PNG_FILTER_PAETH; break;
  1186          default: png_ptr->do_filter = (png_byte)filters; break;
  1072          default: png_ptr->do_filter = (png_byte)filters; break;
  1187 #else
  1073 #else
  1188          default: png_warning(png_ptr, "Unknown row filter for method 0");
  1074          default: png_warning(png_ptr, "Unknown row filter for method 0");
  1189 #endif /* PNG_NO_WRITE_FILTER */
  1075 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  1190       }
  1076       }
  1191 
  1077 
  1192       /* If we have allocated the row_buf, this means we have already started
  1078       /* If we have allocated the row_buf, this means we have already started
  1193        * with the image and we should have allocated all of the filter buffers
  1079        * with the image and we should have allocated all of the filter buffers
  1194        * that have been selected.  If prev_row isn't already allocated, then
  1080        * that have been selected.  If prev_row isn't already allocated, then
  1198        * it should start out with all of the filters, and then add and
  1084        * it should start out with all of the filters, and then add and
  1199        * remove them after the start of compression.
  1085        * remove them after the start of compression.
  1200        */
  1086        */
  1201       if (png_ptr->row_buf != NULL)
  1087       if (png_ptr->row_buf != NULL)
  1202       {
  1088       {
  1203 #ifndef PNG_NO_WRITE_FILTER
  1089 #ifdef PNG_WRITE_FILTER_SUPPORTED
  1204          if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
  1090          if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
  1205          {
  1091          {
  1206             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
  1092             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
  1207               (png_ptr->rowbytes + 1));
  1093               (png_ptr->rowbytes + 1));
  1208             png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1094             png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1253                png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1139                png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1254             }
  1140             }
  1255          }
  1141          }
  1256 
  1142 
  1257          if (png_ptr->do_filter == PNG_NO_FILTERS)
  1143          if (png_ptr->do_filter == PNG_NO_FILTERS)
  1258 #endif /* PNG_NO_WRITE_FILTER */
  1144 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  1259             png_ptr->do_filter = PNG_FILTER_NONE;
  1145             png_ptr->do_filter = PNG_FILTER_NONE;
  1260       }
  1146       }
  1261    }
  1147    }
  1262    else
  1148    else
  1263       png_error(png_ptr, "Unknown custom filter method");
  1149       png_error(png_ptr, "Unknown custom filter method");
  1268  * differences metric is relatively fast and effective, there is some
  1154  * differences metric is relatively fast and effective, there is some
  1269  * question as to whether it can be improved upon by trying to keep the
  1155  * question as to whether it can be improved upon by trying to keep the
  1270  * filtered data going to zlib more consistent, hopefully resulting in
  1156  * filtered data going to zlib more consistent, hopefully resulting in
  1271  * better compression.
  1157  * better compression.
  1272  */
  1158  */
  1273 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
  1159 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED      /* GRR 970116 */
  1274 void PNGAPI
  1160 void PNGAPI
  1275 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
  1161 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
  1276    int num_weights, png_doublep filter_weights,
  1162    int num_weights, png_doublep filter_weights,
  1277    png_doublep filter_costs)
  1163    png_doublep filter_costs)
  1278 {
  1164 {
  1279    int i;
  1165    int i;
  1280 
  1166 
  1281    png_debug(1, "in png_set_filter_heuristics");
  1167    png_debug(1, "in png_set_filter_heuristics");
       
  1168 
  1282    if (png_ptr == NULL)
  1169    if (png_ptr == NULL)
  1283       return;
  1170       return;
  1284    if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
  1171    if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
  1285    {
  1172    {
  1286       png_warning(png_ptr, "Unknown filter heuristic method");
  1173       png_warning(png_ptr, "Unknown filter heuristic method");
  1391 
  1278 
  1392 void PNGAPI
  1279 void PNGAPI
  1393 png_set_compression_level(png_structp png_ptr, int level)
  1280 png_set_compression_level(png_structp png_ptr, int level)
  1394 {
  1281 {
  1395    png_debug(1, "in png_set_compression_level");
  1282    png_debug(1, "in png_set_compression_level");
       
  1283 
  1396    if (png_ptr == NULL)
  1284    if (png_ptr == NULL)
  1397       return;
  1285       return;
  1398    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
  1286    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
  1399    png_ptr->zlib_level = level;
  1287    png_ptr->zlib_level = level;
  1400 }
  1288 }
  1401 
  1289 
  1402 void PNGAPI
  1290 void PNGAPI
  1403 png_set_compression_mem_level(png_structp png_ptr, int mem_level)
  1291 png_set_compression_mem_level(png_structp png_ptr, int mem_level)
  1404 {
  1292 {
  1405    png_debug(1, "in png_set_compression_mem_level");
  1293    png_debug(1, "in png_set_compression_mem_level");
       
  1294 
  1406    if (png_ptr == NULL)
  1295    if (png_ptr == NULL)
  1407       return;
  1296       return;
  1408    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
  1297    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
  1409    png_ptr->zlib_mem_level = mem_level;
  1298    png_ptr->zlib_mem_level = mem_level;
  1410 }
  1299 }
  1411 
  1300 
  1412 void PNGAPI
  1301 void PNGAPI
  1413 png_set_compression_strategy(png_structp png_ptr, int strategy)
  1302 png_set_compression_strategy(png_structp png_ptr, int strategy)
  1414 {
  1303 {
  1415    png_debug(1, "in png_set_compression_strategy");
  1304    png_debug(1, "in png_set_compression_strategy");
       
  1305 
  1416    if (png_ptr == NULL)
  1306    if (png_ptr == NULL)
  1417       return;
  1307       return;
  1418    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
  1308    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
  1419    png_ptr->zlib_strategy = strategy;
  1309    png_ptr->zlib_strategy = strategy;
  1420 }
  1310 }
  1431 #ifndef WBITS_8_OK
  1321 #ifndef WBITS_8_OK
  1432    /* Avoid libpng bug with 256-byte windows */
  1322    /* Avoid libpng bug with 256-byte windows */
  1433    if (window_bits == 8)
  1323    if (window_bits == 8)
  1434      {
  1324      {
  1435        png_warning(png_ptr, "Compression window is being reset to 512");
  1325        png_warning(png_ptr, "Compression window is being reset to 512");
  1436        window_bits=9;
  1326        window_bits = 9;
  1437      }
  1327      }
  1438 #endif
  1328 #endif
  1439    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
  1329    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
  1440    png_ptr->zlib_window_bits = window_bits;
  1330    png_ptr->zlib_window_bits = window_bits;
  1441 }
  1331 }
  1442 
  1332 
  1443 void PNGAPI
  1333 void PNGAPI
  1444 png_set_compression_method(png_structp png_ptr, int method)
  1334 png_set_compression_method(png_structp png_ptr, int method)
  1445 {
  1335 {
  1446    png_debug(1, "in png_set_compression_method");
  1336    png_debug(1, "in png_set_compression_method");
       
  1337 
  1447    if (png_ptr == NULL)
  1338    if (png_ptr == NULL)
  1448       return;
  1339       return;
  1449    if (method != 8)
  1340    if (method != 8)
  1450       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
  1341       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
  1451    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
  1342    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
  1458    if (png_ptr == NULL)
  1349    if (png_ptr == NULL)
  1459       return;
  1350       return;
  1460    png_ptr->write_row_fn = write_row_fn;
  1351    png_ptr->write_row_fn = write_row_fn;
  1461 }
  1352 }
  1462 
  1353 
  1463 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
  1354 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
  1464 void PNGAPI
  1355 void PNGAPI
  1465 png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
  1356 png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
  1466    write_user_transform_fn)
  1357    write_user_transform_fn)
  1467 {
  1358 {
  1468    png_debug(1, "in png_set_write_user_transform_fn");
  1359    png_debug(1, "in png_set_write_user_transform_fn");
       
  1360 
  1469    if (png_ptr == NULL)
  1361    if (png_ptr == NULL)
  1470       return;
  1362       return;
  1471    png_ptr->transformations |= PNG_USER_TRANSFORM;
  1363    png_ptr->transformations |= PNG_USER_TRANSFORM;
  1472    png_ptr->write_user_transform_fn = write_user_transform_fn;
  1364    png_ptr->write_user_transform_fn = write_user_transform_fn;
  1473 }
  1365 }
  1474 #endif
  1366 #endif
  1475 
  1367 
  1476 
  1368 
  1477 #if defined(PNG_INFO_IMAGE_SUPPORTED)
  1369 #ifdef PNG_INFO_IMAGE_SUPPORTED
  1478 void PNGAPI
  1370 void PNGAPI
  1479 png_write_png(png_structp png_ptr, png_infop info_ptr,
  1371 png_write_png(png_structp png_ptr, png_infop info_ptr,
  1480               int transforms, voidp params)
  1372               int transforms, voidp params)
  1481 {
  1373 {
  1482    if (png_ptr == NULL || info_ptr == NULL)
  1374    if (png_ptr == NULL || info_ptr == NULL)
  1483       return;
  1375       return;
  1484 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
       
  1485    /* Invert the alpha channel from opacity to transparency */
       
  1486    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
       
  1487       png_set_invert_alpha(png_ptr);
       
  1488 #endif
       
  1489 
  1376 
  1490    /* Write the file header information. */
  1377    /* Write the file header information. */
  1491    png_write_info(png_ptr, info_ptr);
  1378    png_write_info(png_ptr, info_ptr);
  1492 
  1379 
  1493    /* ------ these transformations don't touch the info structure ------- */
  1380    /* ------ these transformations don't touch the info structure ------- */
  1494 
  1381 
  1495 #if defined(PNG_WRITE_INVERT_SUPPORTED)
  1382 #ifdef PNG_WRITE_INVERT_SUPPORTED
  1496    /* Invert monochrome pixels */
  1383    /* Invert monochrome pixels */
  1497    if (transforms & PNG_TRANSFORM_INVERT_MONO)
  1384    if (transforms & PNG_TRANSFORM_INVERT_MONO)
  1498       png_set_invert_mono(png_ptr);
  1385       png_set_invert_mono(png_ptr);
  1499 #endif
  1386 #endif
  1500 
  1387 
  1501 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
  1388 #ifdef PNG_WRITE_SHIFT_SUPPORTED
  1502    /* Shift the pixels up to a legal bit depth and fill in
  1389    /* Shift the pixels up to a legal bit depth and fill in
  1503     * as appropriate to correctly scale the image.
  1390     * as appropriate to correctly scale the image.
  1504     */
  1391     */
  1505    if ((transforms & PNG_TRANSFORM_SHIFT)
  1392    if ((transforms & PNG_TRANSFORM_SHIFT)
  1506                && (info_ptr->valid & PNG_INFO_sBIT))
  1393                && (info_ptr->valid & PNG_INFO_sBIT))
  1507       png_set_shift(png_ptr, &info_ptr->sig_bit);
  1394       png_set_shift(png_ptr, &info_ptr->sig_bit);
  1508 #endif
  1395 #endif
  1509 
  1396 
  1510 #if defined(PNG_WRITE_PACK_SUPPORTED)
  1397 #ifdef PNG_WRITE_PACK_SUPPORTED
  1511    /* Pack pixels into bytes */
  1398    /* Pack pixels into bytes */
  1512    if (transforms & PNG_TRANSFORM_PACKING)
  1399    if (transforms & PNG_TRANSFORM_PACKING)
  1513        png_set_packing(png_ptr);
  1400        png_set_packing(png_ptr);
  1514 #endif
  1401 #endif
  1515 
  1402 
  1516 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
  1403 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
  1517    /* Swap location of alpha bytes from ARGB to RGBA */
  1404    /* Swap location of alpha bytes from ARGB to RGBA */
  1518    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
  1405    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
  1519       png_set_swap_alpha(png_ptr);
  1406       png_set_swap_alpha(png_ptr);
  1520 #endif
  1407 #endif
  1521 
  1408 
  1522 #if defined(PNG_WRITE_FILLER_SUPPORTED)
  1409 #ifdef PNG_WRITE_FILLER_SUPPORTED
  1523    /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */
  1410    /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */
  1524    if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
  1411    if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
  1525       png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
  1412       png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
  1526    else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
  1413    else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
  1527       png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
  1414       png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
  1528 #endif
  1415 #endif
  1529 
  1416 
  1530 #if defined(PNG_WRITE_BGR_SUPPORTED)
  1417 #ifdef PNG_WRITE_BGR_SUPPORTED
  1531    /* Flip BGR pixels to RGB */
  1418    /* Flip BGR pixels to RGB */
  1532    if (transforms & PNG_TRANSFORM_BGR)
  1419    if (transforms & PNG_TRANSFORM_BGR)
  1533       png_set_bgr(png_ptr);
  1420       png_set_bgr(png_ptr);
  1534 #endif
  1421 #endif
  1535 
  1422 
  1536 #if defined(PNG_WRITE_SWAP_SUPPORTED)
  1423 #ifdef PNG_WRITE_SWAP_SUPPORTED
  1537    /* Swap bytes of 16-bit files to most significant byte first */
  1424    /* Swap bytes of 16-bit files to most significant byte first */
  1538    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
  1425    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
  1539       png_set_swap(png_ptr);
  1426       png_set_swap(png_ptr);
  1540 #endif
  1427 #endif
  1541 
  1428 
  1542 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
  1429 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
  1543    /* Swap bits of 1, 2, 4 bit packed pixel formats */
  1430    /* Swap bits of 1, 2, 4 bit packed pixel formats */
  1544    if (transforms & PNG_TRANSFORM_PACKSWAP)
  1431    if (transforms & PNG_TRANSFORM_PACKSWAP)
  1545       png_set_packswap(png_ptr);
  1432       png_set_packswap(png_ptr);
  1546 #endif
  1433 #endif
  1547 
  1434 
       
  1435 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
       
  1436    /* Invert the alpha channel from opacity to transparency */
       
  1437    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
       
  1438       png_set_invert_alpha(png_ptr);
       
  1439 #endif
       
  1440 
  1548    /* ----------------------- end of transformations ------------------- */
  1441    /* ----------------------- end of transformations ------------------- */
  1549 
  1442 
  1550    /* Write the bits */
  1443    /* Write the bits */
  1551    if (info_ptr->valid & PNG_INFO_IDAT)
  1444    if (info_ptr->valid & PNG_INFO_IDAT)
  1552        png_write_image(png_ptr, info_ptr->row_pointers);
  1445        png_write_image(png_ptr, info_ptr->row_pointers);