Subversion Repositories Kolibri OS

Rev

Rev 1897 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1897 Rev 3928
Line 1... Line 1...
1
/* pngwrite.c - general routines to write a PNG file
1
/* pngwrite.c - general routines to write a PNG file
2
 *
2
 *
3
 * Last changed in libpng 1.5.1 [February 3, 2011]
3
 * Last changed in libpng 1.6.2 [April 25, 2013]
4
 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
4
 * Copyright (c) 1998-2013 Glenn Randers-Pehrson
5
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
5
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
6
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
6
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
7
 *
7
 *
8
 * This code is released under the libpng license.
8
 * This code is released under the libpng license.
9
 * For conditions of distribution and use, see the disclaimer
9
 * For conditions of distribution and use, see the disclaimer
10
 * and license in png.h
10
 * and license in png.h
11
 */
11
 */
Line 12... Line 12...
12
 
12
 
-
 
13
#include "pngpriv.h"
-
 
14
#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
-
 
15
#  include 
Line 13... Line 16...
13
#include "pngpriv.h"
16
#endif
Line -... Line 17...
-
 
17
 
-
 
18
#ifdef PNG_WRITE_SUPPORTED
-
 
19
 
-
 
20
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-
 
21
/* Write out all the unknown chunks for the current given location */
-
 
22
static void
-
 
23
write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
-
 
24
   unsigned int where)
-
 
25
{
-
 
26
   if (info_ptr->unknown_chunks_num)
-
 
27
   {
-
 
28
      png_const_unknown_chunkp up;
-
 
29
 
-
 
30
      png_debug(5, "writing extra chunks");
-
 
31
 
-
 
32
      for (up = info_ptr->unknown_chunks;
-
 
33
           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-
 
34
           ++up)
-
 
35
         if (up->location & where)
-
 
36
      {
-
 
37
         /* If per-chunk unknown chunk handling is enabled use it, otherwise
-
 
38
          * just write the chunks the application has set.
-
 
39
          */
-
 
40
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-
 
41
         int keep = png_handle_as_unknown(png_ptr, up->name);
-
 
42
 
-
 
43
         /* NOTE: this code is radically different from the read side in the
-
 
44
          * matter of handling an ancillary unknown chunk.  In the read side
-
 
45
          * the default behavior is to discard it, in the code below the default
-
 
46
          * behavior is to write it.  Critical chunks are, however, only
-
 
47
          * written if explicitly listed or if the default is set to write all
-
 
48
          * unknown chunks.
-
 
49
          *
-
 
50
          * The default handling is also slightly weird - it is not possible to
-
 
51
          * stop the writing of all unsafe-to-copy chunks!
-
 
52
          *
-
 
53
          * TODO: REVIEW: this would seem to be a bug.
-
 
54
          */
-
 
55
         if (keep != PNG_HANDLE_CHUNK_NEVER &&
-
 
56
             ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
-
 
57
              keep == PNG_HANDLE_CHUNK_ALWAYS ||
-
 
58
              (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
-
 
59
               png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
-
 
60
#endif
-
 
61
         {
-
 
62
            /* TODO: review, what is wrong with a zero length unknown chunk? */
-
 
63
            if (up->size == 0)
-
 
64
               png_warning(png_ptr, "Writing zero-length unknown chunk");
-
 
65
 
-
 
66
            png_write_chunk(png_ptr, up->name, up->data, up->size);
-
 
67
         }
-
 
68
      }
-
 
69
   }
14
 
70
}
15
#ifdef PNG_WRITE_SUPPORTED
71
#endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */
16
 
72
 
17
/* Writes all the PNG information.  This is the suggested way to use the
73
/* Writes all the PNG information.  This is the suggested way to use the
18
 * library.  If you have a new chunk to add, make a function to write it,
74
 * library.  If you have a new chunk to add, make a function to write it,
19
 * and put it in the correct location here.  If you want the chunk written
75
 * and put it in the correct location here.  If you want the chunk written
20
 * after the image data, put it in png_write_end().  I strongly encourage
76
 * after the image data, put it in png_write_end().  I strongly encourage
21
 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
77
 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
22
 * the chunk, as that will keep the code from breaking if you want to just
78
 * the chunk, as that will keep the code from breaking if you want to just
23
 * write a plain PNG file.  If you have long comments, I suggest writing
79
 * write a plain PNG file.  If you have long comments, I suggest writing
24
 * them in png_write_end(), and compressing them.
80
 * them in png_write_end(), and compressing them.
25
 */
81
 */
26
void PNGAPI
82
void PNGAPI
Line 27... Line 83...
27
png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
83
png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
28
{
84
{
Line 49... Line 105...
49
   png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
105
   png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
50
       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
106
       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
51
       info_ptr->filter_type,
107
       info_ptr->filter_type,
52
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
108
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
53
       info_ptr->interlace_type);
109
       info_ptr->interlace_type
54
#else
110
#else
55
       0);
111
       0
56
#endif
112
#endif
57
   /* The rest of these check to see if the valid field has the appropriate
113
      );
-
 
114
 
-
 
115
   /* The rest of these check to see if the valid field has the appropriate
58
    * flag set, and if it does, writes the chunk.
116
    * flag set, and if it does, writes the chunk.
59
    */
117
    *
-
 
118
    * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
-
 
119
    * the chunks will be written if the WRITE routine is there and information
-
 
120
    * is available in the COLORSPACE.  (See png_colorspace_sync_info in png.c
-
 
121
    * for where the valid flags get set.)
-
 
122
    *
-
 
123
    * Under certain circumstances the colorspace can be invalidated without
-
 
124
    * syncing the info_struct 'valid' flags; this happens if libpng detects and
-
 
125
    * error and calls png_error while the color space is being set, yet the
-
 
126
    * application continues writing the PNG.  So check the 'invalid' flag here
-
 
127
    * too.
-
 
128
    */
60
#ifdef PNG_WRITE_gAMA_SUPPORTED
129
#ifdef PNG_GAMMA_SUPPORTED
-
 
130
#  ifdef PNG_WRITE_gAMA_SUPPORTED
61
   if (info_ptr->valid & PNG_INFO_gAMA)
131
      if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
-
 
132
         (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) &&
-
 
133
         (info_ptr->valid & PNG_INFO_gAMA))
62
      png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
134
         png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
63
#endif
135
#  endif
64
#ifdef PNG_WRITE_sRGB_SUPPORTED
136
#endif
-
 
137
 
-
 
138
#ifdef PNG_COLORSPACE_SUPPORTED
-
 
139
   /* Write only one of sRGB or an ICC profile.  If a profile was supplied
-
 
140
    * and it matches one of the known sRGB ones issue a warning.
-
 
141
    */
-
 
142
#  ifdef PNG_WRITE_iCCP_SUPPORTED
-
 
143
      if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
-
 
144
         (info_ptr->valid & PNG_INFO_iCCP))
-
 
145
      {
-
 
146
#        ifdef PNG_WRITE_sRGB_SUPPORTED
65
   if (info_ptr->valid & PNG_INFO_sRGB)
147
            if (info_ptr->valid & PNG_INFO_sRGB)
66
      png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
148
               png_app_warning(png_ptr,
-
 
149
                  "profile matches sRGB but writing iCCP instead");
67
#endif
150
#        endif
68
 
151
 
Line 69... Line 152...
69
#ifdef PNG_WRITE_iCCP_SUPPORTED
152
         png_write_iCCP(png_ptr, info_ptr->iccp_name,
70
   if (info_ptr->valid & PNG_INFO_iCCP)
153
            info_ptr->iccp_profile);
-
 
154
      }
71
      png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
155
#     ifdef PNG_WRITE_sRGB_SUPPORTED
72
          (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
156
         else
73
#endif
157
#     endif
-
 
158
#  endif
-
 
159
 
-
 
160
#  ifdef PNG_WRITE_sRGB_SUPPORTED
-
 
161
      if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
-
 
162
         (info_ptr->valid & PNG_INFO_sRGB))
-
 
163
         png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
-
 
164
#  endif /* WRITE_sRGB */
-
 
165
#endif /* COLORSPACE */
-
 
166
 
74
#ifdef PNG_WRITE_sBIT_SUPPORTED
167
#ifdef PNG_WRITE_sBIT_SUPPORTED
75
   if (info_ptr->valid & PNG_INFO_sBIT)
168
   if (info_ptr->valid & PNG_INFO_sBIT)
76
      png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
169
      png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
77
#endif
170
#endif
-
 
171
 
-
 
172
#ifdef PNG_COLORSPACE_SUPPORTED
78
#ifdef PNG_WRITE_cHRM_SUPPORTED
173
#  ifdef PNG_WRITE_cHRM_SUPPORTED
79
   if (info_ptr->valid & PNG_INFO_cHRM)
174
      if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
80
      png_write_cHRM_fixed(png_ptr,
-
 
81
          info_ptr->x_white, info_ptr->y_white,
175
         (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) &&
82
          info_ptr->x_red, info_ptr->y_red,
176
         (info_ptr->valid & PNG_INFO_cHRM))
83
          info_ptr->x_green, info_ptr->y_green,
177
         png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
84
          info_ptr->x_blue, info_ptr->y_blue);
178
#  endif
85
#endif
179
#endif
Line 86... Line 180...
86
 
180
 
87
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-
 
88
   if (info_ptr->unknown_chunks_num)
-
 
89
   {
-
 
90
      png_unknown_chunk *up;
-
 
91
 
-
 
92
      png_debug(5, "writing extra chunks");
-
 
93
 
-
 
94
      for (up = info_ptr->unknown_chunks;
-
 
95
           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-
 
96
           up++)
-
 
97
      {
-
 
98
         int keep = png_handle_as_unknown(png_ptr, up->name);
-
 
99
 
-
 
100
         if (keep != PNG_HANDLE_CHUNK_NEVER &&
-
 
101
             up->location && !(up->location & PNG_HAVE_PLTE) &&
-
 
102
             !(up->location & PNG_HAVE_IDAT) &&
-
 
103
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
-
 
104
             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
-
 
105
         {
-
 
106
            if (up->size == 0)
-
 
107
               png_warning(png_ptr, "Writing zero-length unknown chunk");
-
 
108
 
181
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
109
            png_write_chunk(png_ptr, up->name, up->data, up->size);
-
 
110
         }
-
 
111
      }
-
 
112
   }
182
      write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
-
 
183
#endif
113
#endif
184
 
114
      png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
185
      png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
115
   }
186
   }
Line 116... Line 187...
116
}
187
}
117
 
188
 
118
void PNGAPI
189
void PNGAPI
119
png_write_info(png_structp png_ptr, png_infop info_ptr)
190
png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
120
{
191
{
121
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
192
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
Line 259... Line 330...
259
   }
330
   }
260
#endif /* tEXt */
331
#endif /* tEXt */
261
 
332
 
Line 262... Line 333...
262
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
333
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
263
   if (info_ptr->unknown_chunks_num)
-
 
264
   {
-
 
265
      png_unknown_chunk *up;
-
 
266
 
-
 
267
      png_debug(5, "writing extra chunks");
-
 
268
 
-
 
269
      for (up = info_ptr->unknown_chunks;
-
 
270
           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-
 
271
           up++)
-
 
272
      {
-
 
273
         int keep = png_handle_as_unknown(png_ptr, up->name);
-
 
274
         if (keep != PNG_HANDLE_CHUNK_NEVER &&
-
 
275
             up->location && (up->location & PNG_HAVE_PLTE) &&
-
 
276
             !(up->location & PNG_HAVE_IDAT) &&
-
 
277
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
-
 
278
             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
-
 
279
         {
-
 
280
            png_write_chunk(png_ptr, up->name, up->data, up->size);
334
   write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
281
         }
-
 
282
      }
-
 
283
   }
-
 
284
#endif
335
#endif
285
}
336
}
Line 286... Line 337...
286
 
337
 
287
/* Writes the end of the PNG file.  If you don't want to write comments or
338
/* Writes the end of the PNG file.  If you don't want to write comments or
288
 * time information, you can pass NULL for info.  If you already wrote these
339
 * time information, you can pass NULL for info.  If you already wrote these
289
 * in png_write_info(), do not write them again here.  If you have long
340
 * in png_write_info(), do not write them again here.  If you have long
290
 * comments, I suggest writing them here, and compressing them.
341
 * comments, I suggest writing them here, and compressing them.
291
 */
342
 */
292
void PNGAPI
343
void PNGAPI
293
png_write_end(png_structp png_ptr, png_infop info_ptr)
344
png_write_end(png_structrp png_ptr, png_inforp info_ptr)
294
{
345
{
Line 295... Line 346...
295
   png_debug(1, "in png_write_end");
346
   png_debug(1, "in png_write_end");
296
 
347
 
Line 297... Line 348...
297
   if (png_ptr == NULL)
348
   if (png_ptr == NULL)
298
      return;
349
      return;
Line -... Line 350...
-
 
350
 
-
 
351
   if (!(png_ptr->mode & PNG_HAVE_IDAT))
-
 
352
      png_error(png_ptr, "No IDATs written into file");
-
 
353
 
-
 
354
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
299
 
355
   if (png_ptr->num_palette_max > png_ptr->num_palette)
300
   if (!(png_ptr->mode & PNG_HAVE_IDAT))
356
      png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
301
      png_error(png_ptr, "No IDATs written into file");
357
#endif
302
 
358
 
303
   /* See if user wants us to write information chunks */
359
   /* See if user wants us to write information chunks */
Line 366... Line 422...
366
         }
422
         }
367
      }
423
      }
368
#endif
424
#endif
369
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
425
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
370
   if (info_ptr->unknown_chunks_num)
426
      write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
371
   {
-
 
372
      png_unknown_chunk *up;
-
 
373
 
-
 
374
      png_debug(5, "writing extra chunks");
-
 
375
 
-
 
376
      for (up = info_ptr->unknown_chunks;
-
 
377
           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-
 
378
           up++)
-
 
379
      {
-
 
380
         int keep = png_handle_as_unknown(png_ptr, up->name);
-
 
381
         if (keep != PNG_HANDLE_CHUNK_NEVER &&
-
 
382
             up->location && (up->location & PNG_AFTER_IDAT) &&
-
 
383
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
-
 
384
             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
-
 
385
         {
-
 
386
            png_write_chunk(png_ptr, up->name, up->data, up->size);
-
 
387
         }
427
#endif
388
      }
-
 
389
   }
-
 
390
#endif
-
 
391
   }
428
   }
392
 
429
 
Line 393... Line 430...
393
   png_ptr->mode |= PNG_AFTER_IDAT;
430
   png_ptr->mode |= PNG_AFTER_IDAT;
Line 408... Line 445...
408
#endif
445
#endif
409
}
446
}
410
 
447
 
Line 411... Line 448...
411
#ifdef PNG_CONVERT_tIME_SUPPORTED
448
#ifdef PNG_CONVERT_tIME_SUPPORTED
412
/* "tm" structure is not supported on WindowsCE */
-
 
413
void PNGAPI
449
void PNGAPI
414
png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime)
450
png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
415
{
451
{
416
   png_debug(1, "in png_convert_from_struct_tm");
452
   png_debug(1, "in png_convert_from_struct_tm");
Line 417... Line 453...
417
 
453
 
418
   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
454
   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
Line 439... Line 475...
439
PNG_FUNCTION(png_structp,PNGAPI
475
PNG_FUNCTION(png_structp,PNGAPI
440
png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
476
png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
441
    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
477
    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
442
{
478
{
443
#ifdef PNG_USER_MEM_SUPPORTED
479
#ifndef PNG_USER_MEM_SUPPORTED
444
   return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
480
   png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
-
 
481
      error_fn, warn_fn, NULL, NULL, NULL);
-
 
482
#else
-
 
483
   return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
445
       warn_fn, NULL, NULL, NULL));
484
       warn_fn, NULL, NULL, NULL);
446
}
485
}
447
 
486
 
Line 448... Line 487...
448
/* Alternate initialize png_ptr structure, and allocate any memory needed */
487
/* Alternate initialize png_ptr structure, and allocate any memory needed */
449
static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */
-
 
450
 
-
 
451
PNG_FUNCTION(png_structp,PNGAPI
488
PNG_FUNCTION(png_structp,PNGAPI
452
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
489
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
453
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
490
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
454
    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
491
    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
455
{
492
{
-
 
493
   png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
-
 
494
      error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
456
#endif /* PNG_USER_MEM_SUPPORTED */
495
#endif /* PNG_USER_MEM_SUPPORTED */
457
   volatile int png_cleanup_needed = 0;
-
 
458
#ifdef PNG_SETJMP_SUPPORTED
-
 
459
   volatile
-
 
460
#endif
-
 
461
   png_structp png_ptr;
-
 
462
#ifdef PNG_SETJMP_SUPPORTED
-
 
463
#ifdef USE_FAR_KEYWORD
-
 
464
   jmp_buf png_jmpbuf;
-
 
465
#endif
-
 
466
#endif
-
 
467
   int i;
-
 
468
 
-
 
469
   png_debug(1, "in png_create_write_struct");
-
 
470
 
-
 
471
#ifdef PNG_USER_MEM_SUPPORTED
-
 
472
   png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
-
 
473
       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
-
 
474
#else
-
 
475
   png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-
 
476
#endif /* PNG_USER_MEM_SUPPORTED */
-
 
477
   if (png_ptr == NULL)
496
   if (png_ptr != NULL)
478
      return (NULL);
-
 
479
 
-
 
480
   /* Added at libpng-1.2.6 */
-
 
481
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-
 
482
   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
-
 
483
   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
-
 
484
#endif
-
 
485
 
-
 
486
#ifdef PNG_SETJMP_SUPPORTED
-
 
487
/* Applications that neglect to set up their own setjmp() and then
-
 
488
   encounter a png_error() will longjmp here.  Since the jmpbuf is
-
 
489
   then meaningless we abort instead of returning. */
-
 
490
#ifdef USE_FAR_KEYWORD
-
 
491
   if (setjmp(png_jmpbuf))
-
 
492
#else
-
 
493
   if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
-
 
494
#endif
-
 
495
#ifdef USE_FAR_KEYWORD
-
 
496
   png_memcpy(png_jmpbuf(png_ptr), png_jmpbuf, png_sizeof(jmp_buf));
-
 
497
#endif
-
 
498
      PNG_ABORT();
-
 
499
#endif
-
 
500
 
-
 
501
#ifdef PNG_USER_MEM_SUPPORTED
-
 
502
   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
-
 
503
#endif /* PNG_USER_MEM_SUPPORTED */
-
 
504
   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
-
 
505
 
-
 
506
   if (user_png_ver)
-
 
507
   {
-
 
508
      i = 0;
-
 
509
      do
-
 
510
      {
-
 
511
         if (user_png_ver[i] != png_libpng_ver[i])
-
 
512
            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-
 
513
      } while (png_libpng_ver[i++]);
-
 
514
   }
-
 
515
 
-
 
516
   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
-
 
517
   {
497
   {
518
     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
-
 
519
      * we must recompile any applications that use any older library version.
498
      /* Set the zlib control values to defaults; they can be overridden by the
520
      * For versions after libpng 1.0, we will be compatible, so we need
499
       * application after the struct has been created.
521
      * only check the first digit.
-
 
522
      */
500
       */
523
     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
501
      png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
524
         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
-
 
525
         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
-
 
526
     {
-
 
527
#ifdef PNG_CONSOLE_IO_SUPPORTED
-
 
528
        char msg[80];
-
 
Line 529... Line -...
529
 
-
 
530
        if (user_png_ver)
-
 
531
        {
-
 
532
            png_snprintf2(msg, 80,
502
 
533
                "Application built with libpng-%.20s"
503
      /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
534
                " but running with %.20s",
-
 
535
                user_png_ver,
-
 
536
                png_libpng_ver);
504
       * pngwutil.c defaults it according to whether or not filters will be
537
            png_warning(png_ptr, msg);
505
       * used, and ignores this setting.
538
         }
-
 
539
#else
506
       */
540
         png_warning(png_ptr,
507
      png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
541
             "Incompatible libpng version in application and library");
-
 
542
#endif
508
      png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
543
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
509
      png_ptr->zlib_mem_level = 8;
544
        png_ptr->flags = 0;
-
 
545
#endif
510
      png_ptr->zlib_window_bits = 15;
546
        png_cleanup_needed = 1;
-
 
547
     }
-
 
Line -... Line 511...
-
 
511
      png_ptr->zlib_method = 8;
-
 
512
 
-
 
513
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
548
   }
514
      png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
549
 
515
      png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
-
 
516
      png_ptr->zlib_text_mem_level = 8;
-
 
517
      png_ptr->zlib_text_window_bits = 15;
Line -... Line 518...
-
 
518
      png_ptr->zlib_text_method = 8;
-
 
519
#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
-
 
520
 
550
   /* Initialize zbuf - compression buffer */
521
      /* This is a highly dubious configuration option; by default it is off,
551
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
522
       * but it may be appropriate for private builds that are testing
552
 
523
       * extensions not conformant to the current specification, or of
553
   if (!png_cleanup_needed)
524
       * applications that must not fail to write at all costs!
554
   {
525
       */
555
      png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
526
#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
556
          png_ptr->zbuf_size);
527
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
-
 
528
      /* In stable builds only warn if an application error can be completely
Line 557... Line -...
557
      if (png_ptr->zbuf == NULL)
-
 
558
         png_cleanup_needed = 1;
-
 
559
   }
529
       * handled.
560
 
530
       */
561
   if (png_cleanup_needed)
531
#endif
562
   {
-
 
563
       /* Clean up PNG structure and deallocate any memory. */
-
 
564
       png_free(png_ptr, png_ptr->zbuf);
532
 
565
       png_ptr->zbuf = NULL;
-
 
566
#ifdef PNG_USER_MEM_SUPPORTED
533
      /* App warnings are warnings in release (or release candidate) builds but
567
       png_destroy_struct_2((png_voidp)png_ptr,
534
       * are errors during development.
568
           (png_free_ptr)free_fn, (png_voidp)mem_ptr);
-
 
569
#else
-
 
Line -... Line 535...
-
 
535
       */
-
 
536
#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
-
 
537
      png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
-
 
538
#endif
570
       png_destroy_struct((png_voidp)png_ptr);
539
 
-
 
540
      /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
Line 571... Line -...
571
#endif
-
 
572
       return (NULL);
-
 
573
   }
-
 
574
 
-
 
575
   png_set_write_fn(png_ptr, NULL, NULL, NULL);
541
       * do it itself) avoiding setting the default function if it is not
576
 
542
       * required.
Line 577... Line 543...
577
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
543
       */
578
   png_reset_filter_heuristics(png_ptr);
544
      png_set_write_fn(png_ptr, NULL, NULL, NULL);
579
#endif
545
   }
580
 
546
 
581
   return (png_ptr);
547
   return png_ptr;
582
}
548
}
583
 
549
 
584
 
550
 
585
/* Write a few rows of image data.  If the image is interlaced,
551
/* Write a few rows of image data.  If the image is interlaced,
586
 * either you will have to write the 7 sub images, or, if you
552
 * either you will have to write the 7 sub images, or, if you
587
 * have called png_set_interlace_handling(), you will have to
553
 * have called png_set_interlace_handling(), you will have to
Line 609... Line 575...
609
/* Write the image.  You only need to call this function once, even
575
/* Write the image.  You only need to call this function once, even
610
 * if you are writing an interlaced image.
576
 * if you are writing an interlaced image.
611
 */
577
 */
612
void PNGAPI
578
void PNGAPI
613
png_write_image(png_structp png_ptr, png_bytepp image)
579
png_write_image(png_structrp png_ptr, png_bytepp image)
614
{
580
{
615
   png_uint_32 i; /* row index */
581
   png_uint_32 i; /* row index */
616
   int pass, num_pass; /* pass variables */
582
   int pass, num_pass; /* pass variables */
617
   png_bytepp rp; /* points to current row */
583
   png_bytepp rp; /* points to current row */
Line 641... Line 607...
641
}
607
}
642
 
608
 
Line 643... Line 609...
643
/* Called by user to write a row of image data */
609
/* Called by user to write a row of image data */
644
void PNGAPI
610
void PNGAPI
645
png_write_row(png_structp png_ptr, png_const_bytep row)
611
png_write_row(png_structrp png_ptr, png_const_bytep row)
646
{
612
{
-
 
613
   /* 1.5.6: moved from png_struct to be a local structure: */
-
 
614
   png_row_info row_info;
-
 
615
 
647
   if (png_ptr == NULL)
616
   if (png_ptr == NULL)
648
      return;
617
      return;
Line 649... Line 618...
649
 
618
 
650
   png_debug2(1, "in png_write_row (row %u, pass %d)",
619
   png_debug2(1, "in png_write_row (row %u, pass %d)",
Line 766... Line 735...
766
   }
735
   }
767
#endif
736
#endif
768
 
737
 
Line 769... Line 738...
769
   /* Set up row info for transformations */
738
   /* Set up row info for transformations */
770
   png_ptr->row_info.color_type = png_ptr->color_type;
739
   row_info.color_type = png_ptr->color_type;
771
   png_ptr->row_info.width = png_ptr->usr_width;
740
   row_info.width = png_ptr->usr_width;
772
   png_ptr->row_info.channels = png_ptr->usr_channels;
741
   row_info.channels = png_ptr->usr_channels;
773
   png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
742
   row_info.bit_depth = png_ptr->usr_bit_depth;
774
   png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
743
   row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
775
      png_ptr->row_info.channels);
-
 
776
 
-
 
777
   png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
744
   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
778
      png_ptr->row_info.width);
-
 
779
 
745
 
780
   png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type);
746
   png_debug1(3, "row_info->color_type = %d", row_info.color_type);
781
   png_debug1(3, "row_info->width = %u", png_ptr->row_info.width);
747
   png_debug1(3, "row_info->width = %u", row_info.width);
782
   png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels);
748
   png_debug1(3, "row_info->channels = %d", row_info.channels);
783
   png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth);
749
   png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
784
   png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth);
750
   png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
785
   png_debug1(3, "row_info->rowbytes = %lu",
751
   png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
786
       (unsigned long)png_ptr->row_info.rowbytes);
-
 
Line 787... Line 752...
787
 
752
 
788
   /* Copy user's row into buffer, leaving room for filter byte. */
753
   /* Copy user's row into buffer, leaving room for filter byte. */
Line 789... Line 754...
789
   png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes);
754
   memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
790
 
755
 
791
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
756
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
792
   /* Handle interlacing */
757
   /* Handle interlacing */
793
   if (png_ptr->interlaced && png_ptr->pass < 6 &&
758
   if (png_ptr->interlaced && png_ptr->pass < 6 &&
794
       (png_ptr->transformations & PNG_INTERLACE))
759
       (png_ptr->transformations & PNG_INTERLACE))
795
   {
-
 
796
      png_do_write_interlace(&(png_ptr->row_info),
760
   {
797
          png_ptr->row_buf + 1, png_ptr->pass);
761
      png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
798
      /* This should always get caught above, but still ... */
762
      /* This should always get caught above, but still ... */
799
      if (!(png_ptr->row_info.width))
763
      if (!(row_info.width))
800
      {
764
      {
801
         png_write_finish_row(png_ptr);
765
         png_write_finish_row(png_ptr);
802
         return;
766
         return;
803
      }
767
      }
Line -... Line 768...
-
 
768
   }
804
   }
769
#endif
805
#endif
770
 
806
 
771
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-
 
772
   /* Handle other transformations */
-
 
773
   if (png_ptr->transformations)
-
 
774
      png_do_write_transformations(png_ptr, &row_info);
-
 
775
#endif
-
 
776
 
-
 
777
   /* At this point the row_info pixel depth must match the 'transformed' depth,
-
 
778
    * which is also the output depth.
-
 
779
    */
Line 807... Line 780...
807
   /* Handle other transformations */
780
   if (row_info.pixel_depth != png_ptr->pixel_depth ||
808
   if (png_ptr->transformations)
781
      row_info.pixel_depth != png_ptr->transformed_pixel_depth)
809
      png_do_write_transformations(png_ptr);
782
      png_error(png_ptr, "internal write transform logic error");
810
 
783
 
Line 821... Line 794...
821
   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
794
   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
822
       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
795
       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
823
   {
796
   {
824
      /* Intrapixel differencing */
797
      /* Intrapixel differencing */
825
      png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
798
      png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
826
   }
799
   }
827
#endif
800
#endif
828
 
801
 
Line -... Line 802...
-
 
802
/* Added at libpng-1.5.10 */
-
 
803
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
-
 
804
   /* Check for out-of-range palette index */
-
 
805
   if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
-
 
806
       png_ptr->num_palette_max >= 0)
-
 
807
      png_do_check_palette_indexes(png_ptr, &row_info);
-
 
808
#endif
-
 
809
 
829
   /* Find a filter if necessary, filter the row and write it out. */
810
   /* Find a filter if necessary, filter the row and write it out. */
830
   png_write_find_filter(png_ptr, &(png_ptr->row_info));
811
   png_write_find_filter(png_ptr, &row_info);
Line 831... Line 812...
831
 
812
 
832
   if (png_ptr->write_row_fn != NULL)
813
   if (png_ptr->write_row_fn != NULL)
833
      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
814
      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
Line 834... Line 815...
834
}
815
}
835
 
816
 
836
#ifdef PNG_WRITE_FLUSH_SUPPORTED
817
#ifdef PNG_WRITE_FLUSH_SUPPORTED
837
/* Set the automatic flush interval or 0 to turn flushing off */
818
/* Set the automatic flush interval or 0 to turn flushing off */
838
void PNGAPI
819
void PNGAPI
839
png_set_flush(png_structp png_ptr, int nrows)
820
png_set_flush(png_structrp png_ptr, int nrows)
Line 840... Line 821...
840
{
821
{
841
   png_debug(1, "in png_set_flush");
822
   png_debug(1, "in png_set_flush");
Line 847... Line 828...
847
}
828
}
848
 
829
 
Line 849... Line 830...
849
/* Flush the current output buffers now */
830
/* Flush the current output buffers now */
850
void PNGAPI
831
void PNGAPI
851
png_write_flush(png_structp png_ptr)
832
png_write_flush(png_structrp png_ptr)
852
{
833
{
853
   int wrote_IDAT;
-
 
854
 
-
 
855
   png_debug(1, "in png_write_flush");
834
   png_debug(1, "in png_write_flush");
Line 856... Line 835...
856
 
835
 
857
   if (png_ptr == NULL)
836
   if (png_ptr == NULL)
Line 858... Line 837...
858
      return;
837
      return;
859
 
838
 
860
   /* We have already written out all of the data */
839
   /* We have already written out all of the data */
Line 861... Line -...
861
   if (png_ptr->row_number >= png_ptr->num_rows)
-
 
862
      return;
-
 
863
 
-
 
864
   do
-
 
865
   {
-
 
866
      int ret;
840
   if (png_ptr->row_number >= png_ptr->num_rows)
867
 
-
 
868
      /* Compress the data */
-
 
869
      ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
-
 
870
      wrote_IDAT = 0;
-
 
871
 
-
 
872
      /* Check for compression errors */
-
 
873
      if (ret != Z_OK)
-
 
874
      {
-
 
875
         if (png_ptr->zstream.msg != NULL)
-
 
876
            png_error(png_ptr, png_ptr->zstream.msg);
-
 
877
 
-
 
878
         else
-
 
879
            png_error(png_ptr, "zlib error");
-
 
880
      }
-
 
881
 
-
 
882
      if (!(png_ptr->zstream.avail_out))
-
 
883
      {
-
 
884
         /* Write the IDAT and reset the zlib output buffer */
-
 
885
         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
-
 
886
         png_ptr->zstream.next_out = png_ptr->zbuf;
-
 
887
         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
 
888
         wrote_IDAT = 1;
-
 
889
      }
-
 
890
   } while (wrote_IDAT == 1);
-
 
891
 
-
 
892
   /* If there is any data left to be output, write it into a new IDAT */
-
 
893
   if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
-
 
894
   {
-
 
895
      /* Write the IDAT and reset the zlib output buffer */
-
 
896
      png_write_IDAT(png_ptr, png_ptr->zbuf,
-
 
897
          png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
 
898
      png_ptr->zstream.next_out = png_ptr->zbuf;
841
      return;
899
      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
842
 
900
   }
843
   png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
901
   png_ptr->flush_rows = 0;
844
   png_ptr->flush_rows = 0;
Line 902... Line -...
902
   png_flush(png_ptr);
-
 
903
}
-
 
904
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
-
 
905
 
-
 
906
/* Free all memory used by the write */
-
 
907
void PNGAPI
-
 
908
png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
-
 
909
{
-
 
910
   png_structp png_ptr = NULL;
-
 
911
   png_infop info_ptr = NULL;
-
 
912
#ifdef PNG_USER_MEM_SUPPORTED
-
 
913
   png_free_ptr free_fn = NULL;
-
 
914
   png_voidp mem_ptr = NULL;
-
 
915
#endif
-
 
916
 
-
 
917
   png_debug(1, "in png_destroy_write_struct");
-
 
918
 
-
 
919
   if (png_ptr_ptr != NULL)
-
 
920
   {
-
 
921
      png_ptr = *png_ptr_ptr;
-
 
922
#ifdef PNG_USER_MEM_SUPPORTED
-
 
923
      free_fn = png_ptr->free_fn;
-
 
924
      mem_ptr = png_ptr->mem_ptr;
-
 
925
#endif
-
 
926
   }
-
 
927
 
-
 
928
#ifdef PNG_USER_MEM_SUPPORTED
-
 
929
   if (png_ptr != NULL)
-
 
930
   {
-
 
931
      free_fn = png_ptr->free_fn;
-
 
932
      mem_ptr = png_ptr->mem_ptr;
-
 
933
   }
-
 
934
#endif
-
 
935
 
-
 
936
   if (info_ptr_ptr != NULL)
-
 
937
      info_ptr = *info_ptr_ptr;
-
 
938
 
-
 
939
   if (info_ptr != NULL)
-
 
940
   {
-
 
941
      if (png_ptr != NULL)
845
   png_flush(png_ptr);
942
      {
-
 
943
         png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
 
944
 
-
 
945
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-
 
946
         if (png_ptr->num_chunk_list)
-
 
947
         {
-
 
948
            png_free(png_ptr, png_ptr->chunk_list);
-
 
949
            png_ptr->num_chunk_list = 0;
-
 
950
         }
-
 
951
#endif
846
}
952
      }
-
 
953
 
-
 
954
#ifdef PNG_USER_MEM_SUPPORTED
-
 
955
      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
847
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
956
          (png_voidp)mem_ptr);
-
 
957
#else
-
 
Line -... Line 848...
-
 
848
 
-
 
849
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
958
      png_destroy_struct((png_voidp)info_ptr);
850
static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */
959
#endif
851
#endif
960
      *info_ptr_ptr = NULL;
-
 
961
   }
-
 
962
 
-
 
963
   if (png_ptr != NULL)
-
 
964
   {
-
 
965
      png_write_destroy(png_ptr);
-
 
966
#ifdef PNG_USER_MEM_SUPPORTED
-
 
967
      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
-
 
968
          (png_voidp)mem_ptr);
-
 
969
#else
-
 
970
      png_destroy_struct((png_voidp)png_ptr);
-
 
971
#endif
-
 
972
      *png_ptr_ptr = NULL;
-
 
973
   }
-
 
974
}
-
 
975
 
-
 
976
 
-
 
977
/* Free any memory used in png_ptr struct (old method) */
-
 
978
void /* PRIVATE */
-
 
979
png_write_destroy(png_structp png_ptr)
-
 
980
{
-
 
981
#ifdef PNG_SETJMP_SUPPORTED
-
 
982
   jmp_buf tmp_jmp; /* Save jump buffer */
-
 
983
#endif
-
 
984
   png_error_ptr error_fn;
-
 
985
   png_error_ptr warning_fn;
-
 
986
   png_voidp error_ptr;
852
 
Line 987... Line 853...
987
#ifdef PNG_USER_MEM_SUPPORTED
853
/* Free any memory used in png_ptr struct without freeing the struct itself. */
-
 
854
static void
988
   png_free_ptr free_fn;
855
png_write_destroy(png_structrp png_ptr)
Line 989... Line 856...
989
#endif
856
{
990
 
857
   png_debug(1, "in png_write_destroy");
991
   png_debug(1, "in png_write_destroy");
858
 
992
 
859
   /* Free any memory zlib uses */
993
   /* Free any memory zlib uses */
860
   if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED)
994
   deflateEnd(&png_ptr->zstream);
861
      deflateEnd(&png_ptr->zstream);
995
 
862
 
996
   /* Free our memory.  png_free checks NULL for us. */
863
   /* Free our memory.  png_free checks NULL for us. */
997
   png_free(png_ptr, png_ptr->zbuf);
864
   png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
998
   png_free(png_ptr, png_ptr->row_buf);
865
   png_free(png_ptr, png_ptr->row_buf);
Line 999... Line -...
999
#ifdef PNG_WRITE_FILTER_SUPPORTED
-
 
1000
   png_free(png_ptr, png_ptr->prev_row);
-
 
1001
   png_free(png_ptr, png_ptr->sub_row);
-
 
1002
   png_free(png_ptr, png_ptr->up_row);
-
 
1003
   png_free(png_ptr, png_ptr->avg_row);
866
#ifdef PNG_WRITE_FILTER_SUPPORTED
1004
   png_free(png_ptr, png_ptr->paeth_row);
867
   png_free(png_ptr, png_ptr->prev_row);
1005
#endif
868
   png_free(png_ptr, png_ptr->sub_row);
1006
 
869
   png_free(png_ptr, png_ptr->up_row);
1007
#ifdef PNG_TIME_RFC1123_SUPPORTED
870
   png_free(png_ptr, png_ptr->avg_row);
1008
   png_free(png_ptr, png_ptr->time_buffer);
871
   png_free(png_ptr, png_ptr->paeth_row);
Line 1009... Line 872...
1009
#endif
872
#endif
1010
 
-
 
1011
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
873
 
1012
   /* Use this to save a little code space, it doesn't free the filter_costs */
874
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
Line 1013... Line -...
1013
   png_reset_filter_heuristics(png_ptr);
-
 
1014
   png_free(png_ptr, png_ptr->filter_costs);
875
   /* Use this to save a little code space, it doesn't free the filter_costs */
1015
   png_free(png_ptr, png_ptr->inv_filter_costs);
876
   png_reset_filter_heuristics(png_ptr);
1016
#endif
-
 
1017
 
877
   png_free(png_ptr, png_ptr->filter_costs);
1018
#ifdef PNG_SETJMP_SUPPORTED
878
   png_free(png_ptr, png_ptr->inv_filter_costs);
-
 
879
#endif
Line -... Line 880...
-
 
880
 
-
 
881
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-
 
882
   png_free(png_ptr, png_ptr->chunk_list);
-
 
883
#endif
-
 
884
 
-
 
885
   /* The error handling and memory handling information is left intact at this
-
 
886
    * point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
-
 
887
    * for how this happens.
-
 
888
    */
-
 
889
}
1019
   /* Reset structure */
890
 
Line 1020... Line 891...
1020
   png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf));
891
/* Free all memory used by the write.
1021
#endif
892
 * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
1022
 
893
 * *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
1023
   error_fn = png_ptr->error_fn;
-
 
1024
   warning_fn = png_ptr->warning_fn;
-
 
1025
   error_ptr = png_ptr->error_ptr;
-
 
Line -... Line 894...
-
 
894
 * the passed in info_structs but it would quietly fail to free any of the data
-
 
895
 * inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
-
 
896
 * has no png_ptr.)
-
 
897
 */
1026
#ifdef PNG_USER_MEM_SUPPORTED
898
void PNGAPI
-
 
899
png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
1027
   free_fn = png_ptr->free_fn;
900
{
1028
#endif
901
   png_debug(1, "in png_destroy_write_struct");
-
 
902
 
1029
 
903
   if (png_ptr_ptr != NULL)
Line 1030... Line 904...
1030
   png_memset(png_ptr, 0, png_sizeof(png_struct));
904
   {
1031
 
905
      png_structrp png_ptr = *png_ptr_ptr;
1032
   png_ptr->error_fn = error_fn;
906
 
1033
   png_ptr->warning_fn = warning_fn;
907
      if (png_ptr != NULL) /* added in libpng 1.6.0 */
1034
   png_ptr->error_ptr = error_ptr;
908
      {
Line 1035... Line 909...
1035
#ifdef PNG_USER_MEM_SUPPORTED
909
         png_destroy_info_struct(png_ptr, info_ptr_ptr);
1036
   png_ptr->free_fn = free_fn;
910
 
Line 1062... Line 936...
1062
      {
936
      {
1063
#ifdef PNG_WRITE_FILTER_SUPPORTED
937
#ifdef PNG_WRITE_FILTER_SUPPORTED
1064
         case 5:
938
         case 5:
1065
         case 6:
939
         case 6:
1066
         case 7: png_warning(png_ptr, "Unknown row filter for method 0");
940
         case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
1067
#endif /* PNG_WRITE_FILTER_SUPPORTED */
941
            /* FALL THROUGH */
-
 
942
#endif /* PNG_WRITE_FILTER_SUPPORTED */
1068
         case PNG_FILTER_VALUE_NONE:
943
         case PNG_FILTER_VALUE_NONE:
1069
            png_ptr->do_filter = PNG_FILTER_NONE; break;
944
            png_ptr->do_filter = PNG_FILTER_NONE; break;
1070
 
945
 
Line 1071... Line 946...
1071
#ifdef PNG_WRITE_FILTER_SUPPORTED
946
#ifdef PNG_WRITE_FILTER_SUPPORTED
Line 1084... Line 959...
1084
         default:
959
         default:
1085
            png_ptr->do_filter = (png_byte)filters; break;
960
            png_ptr->do_filter = (png_byte)filters; break;
1086
#else
961
#else
1087
         default:
962
         default:
1088
            png_warning(png_ptr, "Unknown row filter for method 0");
963
            png_app_error(png_ptr, "Unknown row filter for method 0");
1089
#endif /* PNG_WRITE_FILTER_SUPPORTED */
964
#endif /* PNG_WRITE_FILTER_SUPPORTED */
1090
      }
965
      }
Line 1091... Line 966...
1091
 
966
 
1092
      /* If we have allocated the row_buf, this means we have already started
967
      /* If we have allocated the row_buf, this means we have already started
Line 1175... Line 1050...
1175
 * filtered data going to zlib more consistent, hopefully resulting in
1050
 * filtered data going to zlib more consistent, hopefully resulting in
1176
 * better compression.
1051
 * better compression.
1177
 */
1052
 */
1178
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED      /* GRR 970116 */
1053
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED      /* GRR 970116 */
1179
/* Conveneince reset API. */
1054
/* Convenience reset API. */
1180
static void
1055
static void
1181
png_reset_filter_heuristics(png_structp png_ptr)
1056
png_reset_filter_heuristics(png_structrp png_ptr)
1182
{
1057
{
1183
   /* Clear out any old values in the 'weights' - this must be done because if
1058
   /* Clear out any old values in the 'weights' - this must be done because if
1184
    * the app calls set_filter_heuristics multiple times with different
1059
    * the app calls set_filter_heuristics multiple times with different
1185
    * 'num_weights' values we would otherwise potentially have wrong sized
1060
    * 'num_weights' values we would otherwise potentially have wrong sized
1186
    * arrays.
1061
    * arrays.
1187
    */
1062
    */
Line 1210... Line 1085...
1210
   /* Leave the filter_costs - this array is fixed size. */
1085
   /* Leave the filter_costs - this array is fixed size. */
1211
}
1086
}
Line 1212... Line 1087...
1212
 
1087
 
1213
static int
1088
static int
1214
png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
1089
png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method,
1215
   int num_weights)
1090
   int num_weights)
1216
{
1091
{
1217
   if (png_ptr == NULL)
1092
   if (png_ptr == NULL)
Line 1230... Line 1105...
1230
 
1105
 
Line 1231... Line 1106...
1231
      if (num_weights > 0)
1106
      if (num_weights > 0)
1232
      {
1107
      {
1233
         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
1108
         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
1234
             (png_uint_32)(png_sizeof(png_byte) * num_weights));
1109
             (png_uint_32)((sizeof (png_byte)) * num_weights));
Line 1235... Line 1110...
1235
 
1110
 
1236
         /* To make sure that the weighting starts out fairly */
1111
         /* To make sure that the weighting starts out fairly */
1237
         for (i = 0; i < num_weights; i++)
1112
         for (i = 0; i < num_weights; i++)
1238
         {
1113
         {
1239
            png_ptr->prev_filters[i] = 255;
1114
            png_ptr->prev_filters[i] = 255;
Line 1240... Line 1115...
1240
         }
1115
         }
1241
 
1116
 
Line 1242... Line 1117...
1242
         png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
1117
         png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
1243
             (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
1118
             (png_uint_32)((sizeof (png_uint_16)) * num_weights));
Line 1244... Line 1119...
1244
 
1119
 
1245
         png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
1120
         png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
1246
             (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
1121
             (png_uint_32)((sizeof (png_uint_16)) * num_weights));
1247
 
1122
 
Line 1260... Line 1135...
1260
       */
1135
       */
1261
      if (png_ptr->filter_costs == NULL)
1136
      if (png_ptr->filter_costs == NULL)
1262
      {
1137
      {
1263
         png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
1138
         png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
1264
             (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
1139
             (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
1265
 
1140
 
Line 1266... Line 1141...
1266
         png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
1141
         png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
1267
             (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
1142
             (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
1268
      }
1143
      }
Line 1269... Line 1144...
1269
 
1144
 
1270
      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
1145
      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
1271
      {
1146
      {
Line 1293... Line 1168...
1293
 
1168
 
Line 1294... Line 1169...
1294
/* Provide floating and fixed point APIs */
1169
/* Provide floating and fixed point APIs */
1295
#ifdef PNG_FLOATING_POINT_SUPPORTED
1170
#ifdef PNG_FLOATING_POINT_SUPPORTED
1296
void PNGAPI
1171
void PNGAPI
1297
png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
1172
png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
1298
    int num_weights, png_const_doublep filter_weights,
1173
    int num_weights, png_const_doublep filter_weights,
1299
    png_const_doublep filter_costs)
1174
    png_const_doublep filter_costs)
1300
{
1175
{
1301
   png_debug(1, "in png_set_filter_heuristics");
1176
   png_debug(1, "in png_set_filter_heuristics");
Line 1348... Line 1223...
1348
#endif /* FLOATING_POINT */
1223
#endif /* FLOATING_POINT */
1349
 
1224
 
Line 1350... Line 1225...
1350
#ifdef PNG_FIXED_POINT_SUPPORTED
1225
#ifdef PNG_FIXED_POINT_SUPPORTED
1351
void PNGAPI
1226
void PNGAPI
1352
png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
1227
png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
1353
    int num_weights, png_const_fixed_point_p filter_weights,
1228
    int num_weights, png_const_fixed_point_p filter_weights,
1354
    png_const_fixed_point_p filter_costs)
1229
    png_const_fixed_point_p filter_costs)
1355
{
1230
{
1356
   png_debug(1, "in png_set_filter_heuristics_fixed");
1231
   png_debug(1, "in png_set_filter_heuristics_fixed");
Line 1414... Line 1289...
1414
#endif /* FIXED_POINT */
1289
#endif /* FIXED_POINT */
1415
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
1290
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
1416
 
1291
 
Line 1417... Line 1292...
1417
void PNGAPI
1292
void PNGAPI
1418
png_set_compression_level(png_structp png_ptr, int level)
1293
png_set_compression_level(png_structrp png_ptr, int level)
1419
{
1294
{
1420
   png_debug(1, "in png_set_compression_level");
1295
   png_debug(1, "in png_set_compression_level");
Line 1421... Line 1296...
1421
 
1296
 
1422
   if (png_ptr == NULL)
1297
   if (png_ptr == NULL)
Line 1423... Line -...
1423
      return;
-
 
1424
 
1298
      return;
1425
   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
1299
 
Line 1426... Line 1300...
1426
   png_ptr->zlib_level = level;
1300
   png_ptr->zlib_level = level;
1427
}
1301
}
1428
 
1302
 
1429
void PNGAPI
1303
void PNGAPI
Line 1430... Line 1304...
1430
png_set_compression_mem_level(png_structp png_ptr, int mem_level)
1304
png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
1431
{
1305
{
Line 1432... Line -...
1432
   png_debug(1, "in png_set_compression_mem_level");
-
 
1433
 
1306
   png_debug(1, "in png_set_compression_mem_level");
1434
   if (png_ptr == NULL)
1307
 
Line 1435... Line 1308...
1435
      return;
1308
   if (png_ptr == NULL)
1436
 
1309
      return;
1437
   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
1310
 
1438
   png_ptr->zlib_mem_level = mem_level;
1311
   png_ptr->zlib_mem_level = mem_level;
Line 1439... Line 1312...
1439
}
1312
}
1440
 
1313
 
Line -... Line 1314...
-
 
1314
void PNGAPI
-
 
1315
png_set_compression_strategy(png_structrp png_ptr, int strategy)
1441
void PNGAPI
1316
{
1442
png_set_compression_strategy(png_structp png_ptr, int strategy)
1317
   png_debug(1, "in png_set_compression_strategy");
1443
{
1318
 
Line -... Line 1319...
-
 
1319
   if (png_ptr == NULL)
-
 
1320
      return;
-
 
1321
 
1444
   png_debug(1, "in png_set_compression_strategy");
1322
   /* The flag setting here prevents the libpng dynamic selection of strategy.
1445
 
1323
    */
1446
   if (png_ptr == NULL)
1324
   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
1447
      return;
1325
   png_ptr->zlib_strategy = strategy;
1448
 
1326
}
Line -... Line 1327...
-
 
1327
 
-
 
1328
/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
-
 
1329
 * smaller value of window_bits if it can do so safely.
-
 
1330
 */
-
 
1331
void PNGAPI
-
 
1332
png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
1449
   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
1333
{
-
 
1334
   if (png_ptr == NULL)
1450
   png_ptr->zlib_strategy = strategy;
1335
      return;
-
 
1336
 
-
 
1337
   /* Prior to 1.6.0 this would warn but then set the window_bits value, this
Line 1451... Line 1338...
1451
}
1338
    * meant that negative window bits values could be selected which would cause
1452
 
-
 
1453
void PNGAPI
-
 
1454
png_set_compression_window_bits(png_structp png_ptr, int window_bits)
-
 
1455
{
-
 
1456
   if (png_ptr == NULL)
-
 
1457
      return;
1339
    * libpng to write a non-standard PNG file with raw deflate or gzip
1458
 
1340
    * compressed IDAT or ancillary chunks.  Such files can be read and there is
1459
   if (window_bits > 15)
1341
    * no warning on read, so this seems like a very bad idea.
1460
      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1342
    */
Line 1461... Line -...
1461
 
-
 
1462
   else if (window_bits < 8)
-
 
1463
      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
1343
   if (window_bits > 15)
1464
 
1344
   {
Line 1465... Line 1345...
1465
#ifndef WBITS_8_OK
1345
      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1466
   /* Avoid libpng bug with 256-byte windows */
1346
      window_bits = 15;
1467
   if (window_bits == 8)
1347
   }
1468
      {
1348
 
Line 1469... Line 1349...
1469
        png_warning(png_ptr, "Compression window is being reset to 512");
1349
   else if (window_bits < 8)
1470
        window_bits = 9;
1350
   {
Line -... Line 1351...
-
 
1351
      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
-
 
1352
      window_bits = 8;
-
 
1353
   }
1471
      }
1354
 
1472
 
1355
   png_ptr->zlib_window_bits = window_bits;
Line 1473... Line -...
1473
#endif
-
 
1474
   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
1356
}
1475
   png_ptr->zlib_window_bits = window_bits;
1357
 
Line -... Line 1358...
-
 
1358
void PNGAPI
-
 
1359
png_set_compression_method(png_structrp png_ptr, int method)
-
 
1360
{
-
 
1361
   png_debug(1, "in png_set_compression_method");
-
 
1362
 
-
 
1363
   if (png_ptr == NULL)
-
 
1364
      return;
-
 
1365
 
-
 
1366
   /* This would produce an invalid PNG file if it worked, but it doesn't and
-
 
1367
    * deflate will fault it, so it is harmless to just warn here.
-
 
1368
    */
-
 
1369
   if (method != 8)
-
 
1370
      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
-
 
1371
 
-
 
1372
   png_ptr->zlib_method = method;
-
 
1373
}
-
 
1374
 
-
 
1375
/* The following were added to libpng-1.5.4 */
-
 
1376
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
-
 
1377
void PNGAPI
-
 
1378
png_set_text_compression_level(png_structrp png_ptr, int level)
-
 
1379
{
-
 
1380
   png_debug(1, "in png_set_text_compression_level");
-
 
1381
 
-
 
1382
   if (png_ptr == NULL)
-
 
1383
      return;
-
 
1384
 
-
 
1385
   png_ptr->zlib_text_level = level;
-
 
1386
}
-
 
1387
 
-
 
1388
void PNGAPI
-
 
1389
png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
-
 
1390
{
-
 
1391
   png_debug(1, "in png_set_text_compression_mem_level");
-
 
1392
 
-
 
1393
   if (png_ptr == NULL)
-
 
1394
      return;
-
 
1395
 
-
 
1396
   png_ptr->zlib_text_mem_level = mem_level;
-
 
1397
}
-
 
1398
 
-
 
1399
void PNGAPI
-
 
1400
png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
-
 
1401
{
-
 
1402
   png_debug(1, "in png_set_text_compression_strategy");
-
 
1403
 
-
 
1404
   if (png_ptr == NULL)
-
 
1405
      return;
-
 
1406
 
-
 
1407
   png_ptr->zlib_text_strategy = strategy;
-
 
1408
}
-
 
1409
 
-
 
1410
/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
-
 
1411
 * smaller value of window_bits if it can do so safely.
-
 
1412
 */
-
 
1413
void PNGAPI
-
 
1414
png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
-
 
1415
{
-
 
1416
   if (png_ptr == NULL)
1476
}
1417
      return;
-
 
1418
 
-
 
1419
   if (window_bits > 15)
-
 
1420
   {
-
 
1421
      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
-
 
1422
      window_bits = 15;
-
 
1423
   }
-
 
1424
 
-
 
1425
   else if (window_bits < 8)
-
 
1426
   {
-
 
1427
      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
-
 
1428
      window_bits = 8;
-
 
1429
   }
-
 
1430
 
-
 
1431
   png_ptr->zlib_text_window_bits = window_bits;
-
 
1432
}
-
 
1433
 
1477
 
1434
void PNGAPI
1478
void PNGAPI
1435
png_set_text_compression_method(png_structrp png_ptr, int method)
1479
png_set_compression_method(png_structp png_ptr, int method)
1436
{
1480
{
1437
   png_debug(1, "in png_set_text_compression_method");
Line 1481... Line 1438...
1481
   png_debug(1, "in png_set_compression_method");
1438
 
1482
 
1439
   if (png_ptr == NULL)
Line 1483... Line 1440...
1483
   if (png_ptr == NULL)
1440
      return;
1484
      return;
1441
 
1485
 
1442
   if (method != 8)
1486
   if (method != 8)
1443
      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1487
      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1444
 
1488
 
1445
   png_ptr->zlib_text_method = method;
Line 1489... Line 1446...
1489
   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
1446
}
Line 1516... Line 1473...
1516
 
1473
 
Line 1517... Line 1474...
1517
 
1474
 
1518
#ifdef PNG_INFO_IMAGE_SUPPORTED
1475
#ifdef PNG_INFO_IMAGE_SUPPORTED
1519
void PNGAPI
1476
void PNGAPI
1520
png_write_png(png_structp png_ptr, png_infop info_ptr,
1477
png_write_png(png_structrp png_ptr, png_inforp info_ptr,
1521
    int transforms, voidp params)
1478
    int transforms, voidp params)
1522
{
1479
{
1523
   if (png_ptr == NULL || info_ptr == NULL)
1480
   if (png_ptr == NULL || info_ptr == NULL)
Line 1555... Line 1512...
1555
      png_set_swap_alpha(png_ptr);
1512
      png_set_swap_alpha(png_ptr);
1556
#endif
1513
#endif
1557
 
1514
 
Line 1558... Line 1515...
1558
#ifdef PNG_WRITE_FILLER_SUPPORTED
1515
#ifdef PNG_WRITE_FILLER_SUPPORTED
1559
   /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */
1516
   /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */
1560
   if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
1517
   if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
1561
      png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1518
      png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
Line 1562... Line 1519...
1562
 
1519
 
1563
   else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
1520
   else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
Line 1600... Line 1557...
1600
   PNG_UNUSED(transforms)   /* Quiet compiler warnings */
1557
   PNG_UNUSED(transforms)   /* Quiet compiler warnings */
1601
   PNG_UNUSED(params)
1558
   PNG_UNUSED(params)
1602
}
1559
}
1603
#endif
1560
#endif
-
 
1561
 
-
 
1562
 
-
 
1563
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-
 
1564
#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
-
 
1565
/* Initialize the write structure - general purpose utility. */
-
 
1566
static int
-
 
1567
png_image_write_init(png_imagep image)
-
 
1568
{
-
 
1569
   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
-
 
1570
          png_safe_error, png_safe_warning);
-
 
1571
 
-
 
1572
   if (png_ptr != NULL)
-
 
1573
   {
-
 
1574
      png_infop info_ptr = png_create_info_struct(png_ptr);
-
 
1575
 
-
 
1576
      if (info_ptr != NULL)
-
 
1577
      {
-
 
1578
         png_controlp control = png_voidcast(png_controlp,
-
 
1579
            png_malloc_warn(png_ptr, (sizeof *control)));
-
 
1580
 
-
 
1581
         if (control != NULL)
-
 
1582
         {
-
 
1583
            memset(control, 0, (sizeof *control));
-
 
1584
 
-
 
1585
            control->png_ptr = png_ptr;
-
 
1586
            control->info_ptr = info_ptr;
-
 
1587
            control->for_write = 1;
-
 
1588
 
-
 
1589
            image->opaque = control;
-
 
1590
            return 1;
-
 
1591
         }
-
 
1592
 
-
 
1593
         /* Error clean up */
-
 
1594
         png_destroy_info_struct(png_ptr, &info_ptr);
-
 
1595
      }
-
 
1596
 
-
 
1597
      png_destroy_write_struct(&png_ptr, NULL);
-
 
1598
   }
-
 
1599
 
-
 
1600
   return png_image_error(image, "png_image_write_: out of memory");
-
 
1601
}
-
 
1602
 
-
 
1603
/* Arguments to png_image_write_main: */
-
 
1604
typedef struct
-
 
1605
{
-
 
1606
   /* Arguments: */
-
 
1607
   png_imagep      image;
-
 
1608
   png_const_voidp buffer;
-
 
1609
   png_int_32      row_stride;
-
 
1610
   png_const_voidp colormap;
-
 
1611
   int             convert_to_8bit;
-
 
1612
   /* Local variables: */
-
 
1613
   png_const_voidp first_row;
-
 
1614
   ptrdiff_t       row_bytes;
-
 
1615
   png_voidp       local_row;
-
 
1616
} png_image_write_control;
-
 
1617
 
-
 
1618
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
-
 
1619
 * do any necessary byte swapping.  The component order is defined by the
-
 
1620
 * png_image format value.
-
 
1621
 */
-
 
1622
static int
-
 
1623
png_write_image_16bit(png_voidp argument)
-
 
1624
{
-
 
1625
   png_image_write_control *display = png_voidcast(png_image_write_control*,
-
 
1626
      argument);
-
 
1627
   png_imagep image = display->image;
-
 
1628
   png_structrp png_ptr = image->opaque->png_ptr;
-
 
1629
 
-
 
1630
   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
-
 
1631
      display->first_row);
-
 
1632
   png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
-
 
1633
   png_uint_16p row_end;
-
 
1634
   const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
-
 
1635
   int aindex = 0;
-
 
1636
   png_uint_32 y = image->height;
-
 
1637
 
-
 
1638
   if (image->format & PNG_FORMAT_FLAG_ALPHA)
-
 
1639
   {
-
 
1640
      if (image->format & PNG_FORMAT_FLAG_AFIRST)
-
 
1641
      {
-
 
1642
         aindex = -1;
-
 
1643
         ++input_row; /* To point to the first component */
-
 
1644
         ++output_row;
-
 
1645
      }
-
 
1646
 
-
 
1647
      else
-
 
1648
         aindex = channels;
-
 
1649
   }
-
 
1650
 
-
 
1651
   else
-
 
1652
      png_error(png_ptr, "png_write_image: internal call error");
-
 
1653
 
-
 
1654
   /* Work out the output row end and count over this, note that the increment
-
 
1655
    * above to 'row' means that row_end can actually be beyond the end of the
-
 
1656
    * row; this is correct.
-
 
1657
    */
-
 
1658
   row_end = output_row + image->width * (channels+1);
-
 
1659
 
-
 
1660
   while (y-- > 0)
-
 
1661
   {
-
 
1662
      png_const_uint_16p in_ptr = input_row;
-
 
1663
      png_uint_16p out_ptr = output_row;
-
 
1664
 
-
 
1665
      while (out_ptr < row_end)
-
 
1666
      {
-
 
1667
         const png_uint_16 alpha = in_ptr[aindex];
-
 
1668
         png_uint_32 reciprocal = 0;
-
 
1669
         int c;
-
 
1670
 
-
 
1671
         out_ptr[aindex] = alpha;
-
 
1672
 
-
 
1673
         /* Calculate a reciprocal.  The correct calculation is simply
-
 
1674
          * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
-
 
1675
          * allows correct rounding by adding .5 before the shift.  'reciprocal'
-
 
1676
          * is only initialized when required.
-
 
1677
          */
-
 
1678
         if (alpha > 0 && alpha < 65535)
-
 
1679
            reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
-
 
1680
 
-
 
1681
         c = channels;
-
 
1682
         do /* always at least one channel */
-
 
1683
         {
-
 
1684
            png_uint_16 component = *in_ptr++;
-
 
1685
 
-
 
1686
            /* The following gives 65535 for an alpha of 0, which is fine,
-
 
1687
             * otherwise if 0/0 is represented as some other value there is more
-
 
1688
             * likely to be a discontinuity which will probably damage
-
 
1689
             * compression when moving from a fully transparent area to a
-
 
1690
             * nearly transparent one.  (The assumption here is that opaque
-
 
1691
             * areas tend not to be 0 intensity.)
-
 
1692
             */
-
 
1693
            if (component >= alpha)
-
 
1694
               component = 65535;
-
 
1695
 
-
 
1696
            /* component
-
 
1697
             * component*reciprocal is less than 2^31.
-
 
1698
             */
-
 
1699
            else if (component > 0 && alpha < 65535)
-
 
1700
            {
-
 
1701
               png_uint_32 calc = component * reciprocal;
-
 
1702
               calc += 16384; /* round to nearest */
-
 
1703
               component = (png_uint_16)(calc >> 15);
-
 
1704
            }
-
 
1705
 
-
 
1706
            *out_ptr++ = component;
-
 
1707
         }
-
 
1708
         while (--c > 0);
-
 
1709
 
-
 
1710
         /* Skip to next component (skip the intervening alpha channel) */
-
 
1711
         ++in_ptr;
-
 
1712
         ++out_ptr;
-
 
1713
      }
-
 
1714
 
-
 
1715
      png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
-
 
1716
      input_row += display->row_bytes/(sizeof (png_uint_16));
-
 
1717
   }
-
 
1718
 
-
 
1719
   return 1;
-
 
1720
}
-
 
1721
 
-
 
1722
/* Given 16-bit input (1 to 4 channels) write 8-bit output.  If an alpha channel
-
 
1723
 * is present it must be removed from the components, the components are then
-
 
1724
 * written in sRGB encoding.  No components are added or removed.
-
 
1725
 *
-
 
1726
 * Calculate an alpha reciprocal to reverse pre-multiplication.  As above the
-
 
1727
 * calculation can be done to 15 bits of accuracy; however, the output needs to
-
 
1728
 * be scaled in the range 0..255*65535, so include that scaling here.
-
 
1729
 */
-
 
1730
#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
-
 
1731
 
-
 
1732
static png_byte
-
 
1733
png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
-
 
1734
   png_uint_32 reciprocal/*from the above macro*/)
-
 
1735
{
-
 
1736
   /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
-
 
1737
    * is represented as some other value there is more likely to be a
-
 
1738
    * discontinuity which will probably damage compression when moving from a
-
 
1739
    * fully transparent area to a nearly transparent one.  (The assumption here
-
 
1740
    * is that opaque areas tend not to be 0 intensity.)
-
 
1741
    *
-
 
1742
    * There is a rounding problem here; if alpha is less than 128 it will end up
-
 
1743
    * as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
-
 
1744
    * output change for this too.
-
 
1745
    */
-
 
1746
   if (component >= alpha || alpha < 128)
-
 
1747
      return 255;
-
 
1748
 
-
 
1749
   /* component
-
 
1750
    * component*reciprocal is less than 2^31.
-
 
1751
    */
-
 
1752
   else if (component > 0)
-
 
1753
   {
-
 
1754
      /* The test is that alpha/257 (rounded) is less than 255, the first value
-
 
1755
       * that becomes 255 is 65407.
-
 
1756
       * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
-
 
1757
       * be exact!)  [Could also test reciprocal != 0]
-
 
1758
       */
-
 
1759
      if (alpha < 65407)
-
 
1760
      {
-
 
1761
         component *= reciprocal;
-
 
1762
         component += 64; /* round to nearest */
-
 
1763
         component >>= 7;
-
 
1764
      }
-
 
1765
 
-
 
1766
      else
-
 
1767
         component *= 255;
-
 
1768
 
-
 
1769
      /* Convert the component to sRGB. */
-
 
1770
      return (png_byte)PNG_sRGB_FROM_LINEAR(component);
-
 
1771
   }
-
 
1772
 
-
 
1773
   else
-
 
1774
      return 0;
-
 
1775
}
-
 
1776
 
-
 
1777
static int
-
 
1778
png_write_image_8bit(png_voidp argument)
-
 
1779
{
-
 
1780
   png_image_write_control *display = png_voidcast(png_image_write_control*,
-
 
1781
      argument);
-
 
1782
   png_imagep image = display->image;
-
 
1783
   png_structrp png_ptr = image->opaque->png_ptr;
-
 
1784
 
-
 
1785
   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
-
 
1786
      display->first_row);
-
 
1787
   png_bytep output_row = png_voidcast(png_bytep, display->local_row);
-
 
1788
   png_uint_32 y = image->height;
-
 
1789
   const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
-
 
1790
 
-
 
1791
   if (image->format & PNG_FORMAT_FLAG_ALPHA)
-
 
1792
   {
-
 
1793
      png_bytep row_end;
-
 
1794
      int aindex;
-
 
1795
 
-
 
1796
      if (image->format & PNG_FORMAT_FLAG_AFIRST)
-
 
1797
      {
-
 
1798
         aindex = -1;
-
 
1799
         ++input_row; /* To point to the first component */
-
 
1800
         ++output_row;
-
 
1801
      }
-
 
1802
 
-
 
1803
      else
-
 
1804
         aindex = channels;
-
 
1805
 
-
 
1806
      /* Use row_end in place of a loop counter: */
-
 
1807
      row_end = output_row + image->width * (channels+1);
-
 
1808
 
-
 
1809
      while (y-- > 0)
-
 
1810
      {
-
 
1811
         png_const_uint_16p in_ptr = input_row;
-
 
1812
         png_bytep out_ptr = output_row;
-
 
1813
 
-
 
1814
         while (out_ptr < row_end)
-
 
1815
         {
-
 
1816
            png_uint_16 alpha = in_ptr[aindex];
-
 
1817
            png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
-
 
1818
            png_uint_32 reciprocal = 0;
-
 
1819
            int c;
-
 
1820
 
-
 
1821
            /* Scale and write the alpha channel. */
-
 
1822
            out_ptr[aindex] = alphabyte;
-
 
1823
 
-
 
1824
            if (alphabyte > 0 && alphabyte < 255)
-
 
1825
               reciprocal = UNP_RECIPROCAL(alpha);
-
 
1826
 
-
 
1827
            c = channels;
-
 
1828
            do /* always at least one channel */
-
 
1829
               *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
-
 
1830
            while (--c > 0);
-
 
1831
 
-
 
1832
            /* Skip to next component (skip the intervening alpha channel) */
-
 
1833
            ++in_ptr;
-
 
1834
            ++out_ptr;
-
 
1835
         } /* while out_ptr < row_end */
-
 
1836
 
-
 
1837
         png_write_row(png_ptr, png_voidcast(png_const_bytep,
-
 
1838
            display->local_row));
-
 
1839
         input_row += display->row_bytes/(sizeof (png_uint_16));
-
 
1840
      } /* while y */
-
 
1841
   }
-
 
1842
 
-
 
1843
   else
-
 
1844
   {
-
 
1845
      /* No alpha channel, so the row_end really is the end of the row and it
-
 
1846
       * is sufficient to loop over the components one by one.
-
 
1847
       */
-
 
1848
      png_bytep row_end = output_row + image->width * channels;
-
 
1849
 
-
 
1850
      while (y-- > 0)
-
 
1851
      {
-
 
1852
         png_const_uint_16p in_ptr = input_row;
-
 
1853
         png_bytep out_ptr = output_row;
-
 
1854
 
-
 
1855
         while (out_ptr < row_end)
-
 
1856
         {
-
 
1857
            png_uint_32 component = *in_ptr++;
-
 
1858
 
-
 
1859
            component *= 255;
-
 
1860
            *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
-
 
1861
         }
-
 
1862
 
-
 
1863
         png_write_row(png_ptr, output_row);
-
 
1864
         input_row += display->row_bytes/(sizeof (png_uint_16));
-
 
1865
      }
-
 
1866
   }
-
 
1867
 
-
 
1868
   return 1;
-
 
1869
}
-
 
1870
 
-
 
1871
static void
-
 
1872
png_image_set_PLTE(png_image_write_control *display)
-
 
1873
{
-
 
1874
   const png_imagep image = display->image;
-
 
1875
   const void *cmap = display->colormap;
-
 
1876
   const int entries = image->colormap_entries > 256 ? 256 :
-
 
1877
      (int)image->colormap_entries;
-
 
1878
 
-
 
1879
   /* NOTE: the caller must check for cmap != NULL and entries != 0 */
-
 
1880
   const png_uint_32 format = image->format;
-
 
1881
   const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
-
 
1882
 
-
 
1883
#  ifdef PNG_FORMAT_BGR_SUPPORTED
-
 
1884
      const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
-
 
1885
         (format & PNG_FORMAT_FLAG_ALPHA) != 0;
-
 
1886
#  else
-
 
1887
#     define afirst 0
-
 
1888
#  endif
-
 
1889
 
-
 
1890
#  ifdef PNG_FORMAT_BGR_SUPPORTED
-
 
1891
      const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0;
-
 
1892
#  else
-
 
1893
#     define bgr 0
-
 
1894
#  endif
-
 
1895
 
-
 
1896
   int i, num_trans;
-
 
1897
   png_color palette[256];
-
 
1898
   png_byte tRNS[256];
-
 
1899
 
-
 
1900
   memset(tRNS, 255, (sizeof tRNS));
-
 
1901
   memset(palette, 0, (sizeof palette));
-
 
1902
 
-
 
1903
   for (i=num_trans=0; i
-
 
1904
   {
-
 
1905
      /* This gets automatically converted to sRGB with reversal of the
-
 
1906
       * pre-multiplication if the color-map has an alpha channel.
-
 
1907
       */
-
 
1908
      if (format & PNG_FORMAT_FLAG_LINEAR)
-
 
1909
      {
-
 
1910
         png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
-
 
1911
 
-
 
1912
         entry += i * channels;
-
 
1913
 
-
 
1914
         if (channels & 1) /* no alpha */
-
 
1915
         {
-
 
1916
            if (channels >= 3) /* RGB */
-
 
1917
            {
-
 
1918
               palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
-
 
1919
                  entry[(2 ^ bgr)]);
-
 
1920
               palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
-
 
1921
                  entry[1]);
-
 
1922
               palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
-
 
1923
                  entry[bgr]);
-
 
1924
            }
-
 
1925
 
-
 
1926
            else /* Gray */
-
 
1927
               palette[i].blue = palette[i].red = palette[i].green =
-
 
1928
                  (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
-
 
1929
         }
-
 
1930
 
-
 
1931
         else /* alpha */
-
 
1932
         {
-
 
1933
            png_uint_16 alpha = entry[afirst ? 0 : channels-1];
-
 
1934
            png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
-
 
1935
            png_uint_32 reciprocal = 0;
-
 
1936
 
-
 
1937
            /* Calculate a reciprocal, as in the png_write_image_8bit code above
-
 
1938
             * this is designed to produce a value scaled to 255*65535 when
-
 
1939
             * divided by 128 (i.e. asr 7).
-
 
1940
             */
-
 
1941
            if (alphabyte > 0 && alphabyte < 255)
-
 
1942
               reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
-
 
1943
 
-
 
1944
            tRNS[i] = alphabyte;
-
 
1945
            if (alphabyte < 255)
-
 
1946
               num_trans = i+1;
-
 
1947
 
-
 
1948
            if (channels >= 3) /* RGB */
-
 
1949
            {
-
 
1950
               palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
-
 
1951
                  alpha, reciprocal);
-
 
1952
               palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
-
 
1953
                  reciprocal);
-
 
1954
               palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
-
 
1955
                  reciprocal);
-
 
1956
            }
-
 
1957
 
-
 
1958
            else /* gray */
-
 
1959
               palette[i].blue = palette[i].red = palette[i].green =
-
 
1960
                  png_unpremultiply(entry[afirst], alpha, reciprocal);
-
 
1961
         }
-
 
1962
      }
-
 
1963
 
-
 
1964
      else /* Color-map has sRGB values */
-
 
1965
      {
-
 
1966
         png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
-
 
1967
 
-
 
1968
         entry += i * channels;
-
 
1969
 
-
 
1970
         switch (channels)
-
 
1971
         {
-
 
1972
            case 4:
-
 
1973
               tRNS[i] = entry[afirst ? 0 : 3];
-
 
1974
               if (tRNS[i] < 255)
-
 
1975
                  num_trans = i+1;
-
 
1976
               /* FALL THROUGH */
-
 
1977
            case 3:
-
 
1978
               palette[i].blue = entry[afirst + (2 ^ bgr)];
-
 
1979
               palette[i].green = entry[afirst + 1];
-
 
1980
               palette[i].red = entry[afirst + bgr];
-
 
1981
               break;
-
 
1982
 
-
 
1983
            case 2:
-
 
1984
               tRNS[i] = entry[1 ^ afirst];
-
 
1985
               if (tRNS[i] < 255)
-
 
1986
                  num_trans = i+1;
-
 
1987
               /* FALL THROUGH */
-
 
1988
            case 1:
-
 
1989
               palette[i].blue = palette[i].red = palette[i].green =
-
 
1990
                  entry[afirst];
-
 
1991
               break;
-
 
1992
 
-
 
1993
            default:
-
 
1994
               break;
-
 
1995
         }
-
 
1996
      }
-
 
1997
   }
-
 
1998
 
-
 
1999
#  ifdef afirst
-
 
2000
#     undef afirst
-
 
2001
#  endif
-
 
2002
#  ifdef bgr
-
 
2003
#     undef bgr
-
 
2004
#  endif
-
 
2005
 
-
 
2006
   png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
-
 
2007
      entries);
-
 
2008
 
-
 
2009
   if (num_trans > 0)
-
 
2010
      png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
-
 
2011
         num_trans, NULL);
-
 
2012
 
-
 
2013
   image->colormap_entries = entries;
-
 
2014
}
-
 
2015
 
-
 
2016
static int
-
 
2017
png_image_write_main(png_voidp argument)
-
 
2018
{
-
 
2019
   png_image_write_control *display = png_voidcast(png_image_write_control*,
-
 
2020
      argument);
-
 
2021
   png_imagep image = display->image;
-
 
2022
   png_structrp png_ptr = image->opaque->png_ptr;
-
 
2023
   png_inforp info_ptr = image->opaque->info_ptr;
-
 
2024
   png_uint_32 format = image->format;
-
 
2025
 
-
 
2026
   int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0;
-
 
2027
   int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */
-
 
2028
   int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0;
-
 
2029
   int write_16bit = linear && !colormap && !display->convert_to_8bit;
-
 
2030
 
-
 
2031
#  ifdef PNG_BENIGN_ERRORS_SUPPORTED
-
 
2032
      /* Make sure we error out on any bad situation */
-
 
2033
      png_set_benign_errors(png_ptr, 0/*error*/);
-
 
2034
#  endif
-
 
2035
 
-
 
2036
   /* Default the 'row_stride' parameter if required. */
-
 
2037
   if (display->row_stride == 0)
-
 
2038
      display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
-
 
2039
 
-
 
2040
   /* Set the required transforms then write the rows in the correct order. */
-
 
2041
   if (format & PNG_FORMAT_FLAG_COLORMAP)
-
 
2042
   {
-
 
2043
      if (display->colormap != NULL && image->colormap_entries > 0)
-
 
2044
      {
-
 
2045
         png_uint_32 entries = image->colormap_entries;
-
 
2046
 
-
 
2047
         png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
-
 
2048
            entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
-
 
2049
            PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
-
 
2050
            PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
 
2051
 
-
 
2052
         png_image_set_PLTE(display);
-
 
2053
      }
-
 
2054
 
-
 
2055
      else
-
 
2056
         png_error(image->opaque->png_ptr,
-
 
2057
            "no color-map for color-mapped image");
-
 
2058
   }
-
 
2059
 
-
 
2060
   else
-
 
2061
      png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
-
 
2062
         write_16bit ? 16 : 8,
-
 
2063
         ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
-
 
2064
         ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
-
 
2065
         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
 
2066
 
-
 
2067
   /* Counter-intuitively the data transformations must be called *after*
-
 
2068
    * png_write_info, not before as in the read code, but the 'set' functions
-
 
2069
    * must still be called before.  Just set the color space information, never
-
 
2070
    * write an interlaced image.
-
 
2071
    */
-
 
2072
 
-
 
2073
   if (write_16bit)
-
 
2074
   {
-
 
2075
      /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
-
 
2076
      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
-
 
2077
 
-
 
2078
      if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB))
-
 
2079
         png_set_cHRM_fixed(png_ptr, info_ptr,
-
 
2080
            /* color      x       y */
-
 
2081
            /* white */ 31270, 32900,
-
 
2082
            /* red   */ 64000, 33000,
-
 
2083
            /* green */ 30000, 60000,
-
 
2084
            /* blue  */ 15000,  6000
-
 
2085
         );
-
 
2086
   }
-
 
2087
 
-
 
2088
   else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB))
-
 
2089
      png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
-
 
2090
 
-
 
2091
   /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
-
 
2092
    * space must still be gamma encoded.
-
 
2093
    */
-
 
2094
   else
-
 
2095
      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
-
 
2096
 
-
 
2097
   /* Write the file header. */
-
 
2098
   png_write_info(png_ptr, info_ptr);
-
 
2099
 
-
 
2100
   /* Now set up the data transformations (*after* the header is written),
-
 
2101
    * remove the handled transformations from the 'format' flags for checking.
-
 
2102
    *
-
 
2103
    * First check for a little endian system if writing 16 bit files.
-
 
2104
    */
-
 
2105
   if (write_16bit)
-
 
2106
   {
-
 
2107
      PNG_CONST png_uint_16 le = 0x0001;
-
 
2108
 
-
 
2109
      if (*(png_const_bytep)&le)
-
 
2110
         png_set_swap(png_ptr);
-
 
2111
   }
-
 
2112
 
-
 
2113
#  ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
-
 
2114
      if (format & PNG_FORMAT_FLAG_BGR)
-
 
2115
      {
-
 
2116
         if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0)
-
 
2117
            png_set_bgr(png_ptr);
-
 
2118
         format &= ~PNG_FORMAT_FLAG_BGR;
-
 
2119
      }
-
 
2120
#  endif
-
 
2121
 
-
 
2122
#  ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
-
 
2123
      if (format & PNG_FORMAT_FLAG_AFIRST)
-
 
2124
      {
-
 
2125
         if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
-
 
2126
            png_set_swap_alpha(png_ptr);
-
 
2127
         format &= ~PNG_FORMAT_FLAG_AFIRST;
-
 
2128
      }
-
 
2129
#  endif
-
 
2130
 
-
 
2131
   /* If there are 16 or fewer color-map entries we wrote a lower bit depth
-
 
2132
    * above, but the application data is still byte packed.
-
 
2133
    */
-
 
2134
   if (colormap && image->colormap_entries <= 16)
-
 
2135
      png_set_packing(png_ptr);
-
 
2136
 
-
 
2137
   /* That should have handled all (both) the transforms. */
-
 
2138
   if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
-
 
2139
         PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
-
 
2140
      png_error(png_ptr, "png_write_image: unsupported transformation");
-
 
2141
 
-
 
2142
   {
-
 
2143
      png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
-
 
2144
      ptrdiff_t row_bytes = display->row_stride;
-
 
2145
 
-
 
2146
      if (linear)
-
 
2147
         row_bytes *= (sizeof (png_uint_16));
-
 
2148
 
-
 
2149
      if (row_bytes < 0)
-
 
2150
         row += (image->height-1) * (-row_bytes);
-
 
2151
 
-
 
2152
      display->first_row = row;
-
 
2153
      display->row_bytes = row_bytes;
-
 
2154
   }
-
 
2155
 
-
 
2156
   /* Apply 'fast' options if the flag is set. */
-
 
2157
   if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
-
 
2158
   {
-
 
2159
      png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
-
 
2160
      /* NOTE: determined by experiment using pngstest, this reflects some
-
 
2161
       * balance between the time to write the image once and the time to read
-
 
2162
       * it about 50 times.  The speed-up in pngstest was about 10-20% of the
-
 
2163
       * total (user) time on a heavily loaded system.
-
 
2164
       */
-
 
2165
      png_set_compression_level(png_ptr, 3);
-
 
2166
   }
-
 
2167
 
-
 
2168
   /* Check for the cases that currently require a pre-transform on the row
-
 
2169
    * before it is written.  This only applies when the input is 16-bit and
-
 
2170
    * either there is an alpha channel or it is converted to 8-bit.
-
 
2171
    */
-
 
2172
   if ((linear && alpha) || (!colormap && display->convert_to_8bit))
-
 
2173
   {
-
 
2174
      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
-
 
2175
         png_get_rowbytes(png_ptr, info_ptr)));
-
 
2176
      int result;
-
 
2177
 
-
 
2178
      display->local_row = row;
-
 
2179
      if (write_16bit)
-
 
2180
         result = png_safe_execute(image, png_write_image_16bit, display);
-
 
2181
      else
-
 
2182
         result = png_safe_execute(image, png_write_image_8bit, display);
-
 
2183
      display->local_row = NULL;
-
 
2184
 
-
 
2185
      png_free(png_ptr, row);
-
 
2186
 
-
 
2187
      /* Skip the 'write_end' on error: */
-
 
2188
      if (!result)
-
 
2189
         return 0;
-
 
2190
   }
-
 
2191
 
-
 
2192
   /* Otherwise this is the case where the input is in a format currently
-
 
2193
    * supported by the rest of the libpng write code; call it directly.
-
 
2194
    */
-
 
2195
   else
-
 
2196
   {
-
 
2197
      png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
-
 
2198
      ptrdiff_t row_bytes = display->row_bytes;
-
 
2199
      png_uint_32 y = image->height;
-
 
2200
 
-
 
2201
      while (y-- > 0)
-
 
2202
      {
-
 
2203
         png_write_row(png_ptr, row);
-
 
2204
         row += row_bytes;
-
 
2205
      }
-
 
2206
   }
-
 
2207
 
-
 
2208
   png_write_end(png_ptr, info_ptr);
-
 
2209
   return 1;
-
 
2210
}
-
 
2211
 
-
 
2212
int PNGAPI
-
 
2213
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
-
 
2214
   const void *buffer, png_int_32 row_stride, const void *colormap)
-
 
2215
{
-
 
2216
   /* Write the image to the given (FILE*). */
-
 
2217
   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-
 
2218
   {
-
 
2219
      if (file != NULL)
-
 
2220
      {
-
 
2221
         if (png_image_write_init(image))
-
 
2222
         {
-
 
2223
            png_image_write_control display;
-
 
2224
            int result;
-
 
2225
 
-
 
2226
            /* This is slightly evil, but png_init_io doesn't do anything other
-
 
2227
             * than this and we haven't changed the standard IO functions so
-
 
2228
             * this saves a 'safe' function.
-
 
2229
             */
-
 
2230
            image->opaque->png_ptr->io_ptr = file;
-
 
2231
 
-
 
2232
            memset(&display, 0, (sizeof display));
-
 
2233
            display.image = image;
-
 
2234
            display.buffer = buffer;
-
 
2235
            display.row_stride = row_stride;
-
 
2236
            display.colormap = colormap;
-
 
2237
            display.convert_to_8bit = convert_to_8bit;
-
 
2238
 
-
 
2239
            result = png_safe_execute(image, png_image_write_main, &display);
-
 
2240
            png_image_free(image);
-
 
2241
            return result;
-
 
2242
         }
-
 
2243
 
-
 
2244
         else
-
 
2245
            return 0;
-
 
2246
      }
-
 
2247
 
-
 
2248
      else
-
 
2249
         return png_image_error(image,
-
 
2250
            "png_image_write_to_stdio: invalid argument");
-
 
2251
   }
-
 
2252
 
-
 
2253
   else if (image != NULL)
-
 
2254
      return png_image_error(image,
-
 
2255
         "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
-
 
2256
 
-
 
2257
   else
-
 
2258
      return 0;
-
 
2259
}
-
 
2260
 
-
 
2261
int PNGAPI
-
 
2262
png_image_write_to_file(png_imagep image, const char *file_name,
-
 
2263
   int convert_to_8bit, const void *buffer, png_int_32 row_stride,
-
 
2264
   const void *colormap)
-
 
2265
{
-
 
2266
   /* Write the image to the named file. */
-
 
2267
   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-
 
2268
   {
-
 
2269
      if (file_name != NULL)
-
 
2270
      {
-
 
2271
         FILE *fp = fopen(file_name, "wb");
-
 
2272
 
-
 
2273
         if (fp != NULL)
-
 
2274
         {
-
 
2275
            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
-
 
2276
               row_stride, colormap))
-
 
2277
            {
-
 
2278
               int error; /* from fflush/fclose */
-
 
2279
 
-
 
2280
               /* Make sure the file is flushed correctly. */
-
 
2281
               if (fflush(fp) == 0 && ferror(fp) == 0)
-
 
2282
               {
-
 
2283
                  if (fclose(fp) == 0)
-
 
2284
                     return 1;
-
 
2285
 
-
 
2286
                  error = errno; /* from fclose */
-
 
2287
               }
-
 
2288
 
-
 
2289
               else
-
 
2290
               {
-
 
2291
                  error = errno; /* from fflush or ferror */
-
 
2292
                  (void)fclose(fp);
-
 
2293
               }
-
 
2294
 
-
 
2295
               (void)remove(file_name);
-
 
2296
               /* The image has already been cleaned up; this is just used to
-
 
2297
                * set the error (because the original write succeeded).
-
 
2298
                */
-
 
2299
               return png_image_error(image, strerror(error));
-
 
2300
            }
-
 
2301
 
-
 
2302
            else
-
 
2303
            {
-
 
2304
               /* Clean up: just the opened file. */
-
 
2305
               (void)fclose(fp);
-
 
2306
               (void)remove(file_name);
-
 
2307
               return 0;
-
 
2308
            }
-
 
2309
         }
-
 
2310
 
-
 
2311
         else
-
 
2312
            return png_image_error(image, strerror(errno));
-
 
2313
      }
-
 
2314
 
-
 
2315
      else
-
 
2316
         return png_image_error(image,
-
 
2317
            "png_image_write_to_file: invalid argument");
-
 
2318
   }
-
 
2319
 
-
 
2320
   else if (image != NULL)
-
 
2321
      return png_image_error(image,
-
 
2322
         "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
-
 
2323
 
-
 
2324
   else
-
 
2325
      return 0;
-
 
2326
}
-
 
2327
#endif /* PNG_STDIO_SUPPORTED */
-
 
2328
#endif /* SIMPLIFIED_WRITE */
1604
#endif /* PNG_WRITE_SUPPORTED */
2329
#endif /* PNG_WRITE_SUPPORTED */