~random-stuff/libpng/libpng-1.6.x

« back to all changes in this revision

Viewing changes to pngwrite.c

  • Committer: Sérgio Benjamim
  • Date: 2015-10-10 23:00:20 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20151010230020-gdtmmv30zn25396n
Update to 1.6.18.

Show diffs side-by-side

added added

removed removed

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