CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/libpng17/pngwrite.c
Views: 1401
1
2
/* pngwrite.c - general routines to write a PNG file
3
*
4
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
5
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
6
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
*
9
* This code is released under the libpng license.
10
* For conditions of distribution and use, see the disclaimer
11
* and license in png.h
12
*/
13
14
#include "pngpriv.h"
15
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
16
# include <errno.h>
17
#endif /* SIMPLIFIED_WRITE_STDIO */
18
19
#define PNG_SRC_FILE PNG_SRC_FILE_pngwrite
20
21
#ifdef PNG_WRITE_SUPPORTED
22
23
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
24
/* Write out all the unknown chunks for the current given location */
25
static void
26
write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
27
unsigned int where)
28
{
29
if (info_ptr->unknown_chunks_num != 0)
30
{
31
png_const_unknown_chunkp up;
32
33
png_debug(5, "writing extra chunks");
34
35
for (up = info_ptr->unknown_chunks;
36
up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
37
++up)
38
if ((up->location & where) != 0)
39
{
40
/* If per-chunk unknown chunk handling is enabled use it, otherwise
41
* just write the chunks the application has set.
42
*/
43
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
44
int keep = png_handle_as_unknown(png_ptr, up->name);
45
46
/* NOTE: this code is radically different from the read side in the
47
* matter of handling an ancillary unknown chunk. In the read side
48
* the default behavior is to discard it, in the code below the default
49
* behavior is to write it. Critical chunks are, however, only
50
* written if explicitly listed or if the default is set to write all
51
* unknown chunks.
52
*
53
* The default handling is also slightly weird - it is not possible to
54
* stop the writing of all unsafe-to-copy chunks!
55
*
56
* TODO: REVIEW: this would seem to be a bug.
57
*/
58
if (keep != PNG_HANDLE_CHUNK_NEVER &&
59
((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
60
keep == PNG_HANDLE_CHUNK_ALWAYS ||
61
(keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
62
png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
63
#endif
64
png_write_chunk(png_ptr, up->name, up->data, up->size);
65
}
66
}
67
}
68
#endif /* WRITE_UNKNOWN_CHUNKS */
69
70
#ifdef PNG_WRITE_TEXT_SUPPORTED
71
static void
72
png_write_text(png_structrp png_ptr, png_const_inforp info_ptr, png_byte where)
73
/* Text chunk helper */
74
{
75
int i;
76
77
/* Check to see if we need to write text chunks */
78
for (i = 0; i < info_ptr->num_text; i++)
79
{
80
png_debug2(2, "Writing text chunk %d, type %d", i,
81
info_ptr->text[i].compression);
82
83
/* Text chunks are written at info_ptr->text[i].location, skip the chunk
84
* if we are not writing at that location:
85
*/
86
if ((info_ptr->text[i].location & where) == 0U)
87
continue;
88
89
switch (info_ptr->text[i].compression)
90
{
91
case PNG_ITXT_COMPRESSION_NONE:
92
case PNG_ITXT_COMPRESSION_zTXt:
93
# ifdef PNG_WRITE_iTXt_SUPPORTED
94
/* Write international chunk */
95
png_write_iTXt(png_ptr, info_ptr->text[i].compression,
96
info_ptr->text[i].key, info_ptr->text[i].lang,
97
info_ptr->text[i].lang_key, info_ptr->text[i].text);
98
# else /* !WRITE_iTXT */
99
png_app_error(png_ptr, "Unable to write international text");
100
# endif /* !WRITE_iTXT */
101
break;
102
103
case PNG_TEXT_COMPRESSION_zTXt:
104
# ifdef PNG_WRITE_zTXt_SUPPORTED
105
/* Write compressed chunk */
106
png_write_zTXt(png_ptr, info_ptr->text[i].key,
107
info_ptr->text[i].text, info_ptr->text[i].compression);
108
# else /* !WRITE_zTXT */
109
png_app_error(png_ptr, "Unable to write compressed text");
110
# endif /* !WRITE_zTXT */
111
break;
112
113
case PNG_TEXT_COMPRESSION_NONE:
114
# ifdef PNG_WRITE_tEXt_SUPPORTED
115
/* Write uncompressed chunk */
116
png_write_tEXt(png_ptr, info_ptr->text[i].key,
117
info_ptr->text[i].text, 0);
118
# else /* !WRITE_tEXt */
119
/* Can't get here TODO: why not? */
120
png_app_error(png_ptr, "Unable to write uncompressed text");
121
# endif /* !WRITE_tEXt */
122
break;
123
124
default:
125
/* This is an internal error because the libpng checking should
126
* never manage to set any 'compression' except the above values.
127
*/
128
impossible("invalid text compression");
129
}
130
131
/* The chunk was written, record where. This allows the location to have
132
* multiple bits set; the first successful write freezes the location.
133
*/
134
info_ptr->text[i].location = where;
135
}
136
}
137
#endif /* WRITE_TEXT */
138
139
/* Writes all the PNG information. This is the suggested way to use the
140
* library. If you have a new chunk to add, make a function to write it,
141
* and put it in the correct location here. If you want the chunk written
142
* after the image data, put it in png_write_end(). I strongly encourage
143
* you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
144
* the chunk, as that will keep the code from breaking if you want to just
145
* write a plain PNG file. If you have long comments, I suggest writing
146
* them in png_write_end(), and compressing them.
147
*/
148
void PNGAPI
149
png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
150
{
151
png_debug(1, "in png_write_info_before_PLTE");
152
153
if (png_ptr == NULL || info_ptr == NULL)
154
return;
155
156
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
157
{
158
int color_type = PNG_COLOR_TYPE_FROM_FORMAT(info_ptr->format);
159
160
/* Write PNG signature; doesn't set PNG_HAVE_PNG_SIGNATURE if it has
161
* already been written (or rather, if at least 3 bytes have already been
162
* written; undocumented wackiness, it means the 'PNG' at the start can be
163
* replace by, e.g. "FOO" or "BAR" or "MNG").
164
*/
165
png_write_sig(png_ptr);
166
167
# ifdef PNG_MNG_FEATURES_SUPPORTED
168
if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
169
png_ptr->mng_features_permitted != 0)
170
{
171
png_app_error(png_ptr,
172
"MNG features are not allowed in a PNG datastream");
173
/* Recovery: disable MNG features: */
174
png_ptr->mng_features_permitted = 0;
175
}
176
# endif /* MNG_FEATURES */
177
178
/* Write IHDR information. */
179
png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
180
info_ptr->bit_depth, color_type, info_ptr->compression_type,
181
info_ptr->filter_type, info_ptr->interlace_type);
182
183
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
184
/* This are used for checking later on: */
185
png_ptr->info_format = info_ptr->format;
186
# endif /* WRITE_TRANSFORMS */
187
188
/* This sets the flag that prevents re-entry to the 'before PLTE' case: */
189
affirm((png_ptr->mode & PNG_HAVE_IHDR) != 0);
190
191
/* The rest of these check to see if the valid field has the appropriate
192
* flag set, and if it does, writes the chunk.
193
*
194
* 1.6.0: COLORSPACE support controls the writing of these chunks too, and
195
* the chunks will be written if the WRITE routine is there and
196
* information is available in the COLORSPACE. (See
197
* png_colorspace_sync_info in png.c for where the valid flags get set.)
198
*
199
* Under certain circumstances the colorspace can be invalidated without
200
* syncing the info_struct 'valid' flags; this happens if libpng detects
201
* an error and calls png_error while the color space is being set, yet
202
* the application continues writing the PNG. So check the 'invalid'
203
* flag here too.
204
*/
205
# ifdef PNG_WRITE_tIME_SUPPORTED
206
if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
207
(info_ptr->time_location & PNG_HAVE_IHDR) != 0)
208
png_write_tIME(png_ptr, &(info_ptr->mod_time));
209
# endif /* WRITE_tIME */
210
211
# ifdef PNG_WRITE_gAMA_SUPPORTED /* enables GAMMA */
212
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
213
(info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
214
(info_ptr->valid & PNG_INFO_gAMA) != 0)
215
{
216
/* This is the inverse of the test in png.c: */
217
affirm(info_ptr->colorspace.gamma >= 16 &&
218
info_ptr->colorspace.gamma <= 625000000);
219
png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
220
}
221
# endif /* WRITE_gAMA */
222
223
/* Write only one of sRGB or an ICC profile. If a profile was supplied
224
* and it matches one of the known sRGB ones issue a warning.
225
*/
226
# ifdef PNG_WRITE_iCCP_SUPPORTED /* enables COLORSPACE, GAMMA */
227
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
228
(info_ptr->valid & PNG_INFO_iCCP) != 0)
229
{
230
# ifdef PNG_WRITE_sRGB_SUPPORTED
231
/* The app must have supplied an sRGB iCCP profile (and one that
232
* is recognized and therefore known to be correct) so we write
233
* that profile, even though it increases the size of the PNG
234
* significantly. A warning is reasonable:
235
*/
236
if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
237
png_app_warning(png_ptr,
238
"profile matches sRGB but writing iCCP instead");
239
# endif /* WRITE_sRGB */
240
241
png_write_iCCP(png_ptr, info_ptr->iccp_name,
242
info_ptr->iccp_profile);
243
}
244
# ifdef PNG_WRITE_sRGB_SUPPORTED
245
else /* iCCP not written */
246
# endif /* WRITE_sRGB */
247
# endif /* WRITE_iCCP */
248
249
# ifdef PNG_WRITE_sRGB_SUPPORTED /* enables COLORSPACE, GAMMA */
250
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
251
(info_ptr->valid & PNG_INFO_sRGB) != 0)
252
png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
253
# endif /* WRITE_sRGB */
254
255
# ifdef PNG_WRITE_sBIT_SUPPORTED
256
if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
257
png_write_sBIT(png_ptr, &(info_ptr->sig_bit), color_type);
258
# endif /* WRITE_sBIT */
259
260
# ifdef PNG_WRITE_cHRM_SUPPORTED /* enables COLORSPACE */
261
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
262
(info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
263
(info_ptr->valid & PNG_INFO_cHRM) != 0)
264
png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
265
# endif /* WRITE_cHRM */
266
267
# ifdef PNG_WRITE_TEXT_SUPPORTED
268
if (info_ptr->num_text > 0)
269
png_write_text(png_ptr, info_ptr, PNG_HAVE_IHDR);
270
# endif /* WRITE_TEXT */
271
272
# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
273
/* The third arugment must encode only one bit, otherwise chunks will
274
* be written twice because the test in write_unknown_chunks is
275
* 'location & where'.
276
*/
277
write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
278
# endif
279
}
280
281
else /* 1.7.0: flag multiple calls; previously ignored */
282
png_app_error(png_ptr,
283
"png_write_info_before_PLTE called more than once");
284
}
285
286
void PNGAPI
287
png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
288
{
289
png_debug(1, "in png_write_info");
290
291
if (png_ptr == NULL || info_ptr == NULL)
292
return;
293
294
if ((png_ptr->mode & (PNG_HAVE_PLTE+PNG_HAVE_IDAT)) != 0)
295
{
296
png_app_error(png_ptr, "late call to png_write_info");
297
return;
298
}
299
300
/* The app may do this for us, and in 1.7.0 multiple calls are flagged as an
301
* application error, so this code must check:
302
*/
303
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
304
png_write_info_before_PLTE(png_ptr, info_ptr);
305
306
if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
307
png_write_PLTE(png_ptr, info_ptr->palette, info_ptr->num_palette);
308
309
/* Validate the consistency of the PNG being produced; a palette must have
310
* been written if a palette mapped PNG is to be valid:
311
*/
312
if ((png_ptr->mode & PNG_HAVE_PLTE) == 0 &&
313
png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
314
png_error(png_ptr, "Valid palette required for paletted images");
315
316
/* But always set the mode flag because without this we don't know when to
317
* write the post-palette text or unknown chunks.
318
*/
319
png_ptr->mode |= PNG_HAVE_PLTE;
320
321
# ifdef PNG_WRITE_tRNS_SUPPORTED
322
if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
323
{
324
png_write_tRNS(png_ptr, info_ptr->trans_alpha,
325
&(info_ptr->trans_color), info_ptr->num_trans,
326
PNG_COLOR_TYPE_FROM_FORMAT(info_ptr->format));
327
}
328
# endif /* WRITE_tRNS */
329
330
# ifdef PNG_WRITE_bKGD_SUPPORTED
331
if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
332
png_write_bKGD(png_ptr, &(info_ptr->background),
333
PNG_COLOR_TYPE_FROM_FORMAT(info_ptr->format));
334
# endif /* WRITE_bKGD */
335
336
# ifdef PNG_WRITE_hIST_SUPPORTED
337
if ((info_ptr->valid & PNG_INFO_hIST) != 0)
338
png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
339
# endif /* WRITE_hIST */
340
341
# ifdef PNG_WRITE_oFFs_SUPPORTED
342
if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
343
png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
344
info_ptr->offset_unit_type);
345
# endif /* WRITE_oFFs */
346
347
# ifdef PNG_WRITE_pCAL_SUPPORTED
348
if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
349
png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
350
info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
351
info_ptr->pcal_units, info_ptr->pcal_params);
352
# endif /* WRITE_pCAL */
353
354
# ifdef PNG_WRITE_sCAL_SUPPORTED
355
if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
356
png_write_sCAL_s(png_ptr, info_ptr->scal_unit, info_ptr->scal_s_width,
357
info_ptr->scal_s_height);
358
# endif /* WRITE_sCAL */
359
360
# ifdef PNG_WRITE_pHYs_SUPPORTED
361
if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
362
png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
363
info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
364
# endif /* WRITE_pHYs */
365
366
# ifdef PNG_WRITE_tIME_SUPPORTED
367
if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
368
(info_ptr->time_location & PNG_HAVE_PLTE) != 0)
369
png_write_tIME(png_ptr, &(info_ptr->mod_time));
370
# endif /* WRITE_tIME */
371
372
# ifdef PNG_WRITE_sPLT_SUPPORTED
373
if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
374
{
375
int i;
376
377
for (i = 0; i < info_ptr->splt_palettes_num; i++)
378
png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
379
}
380
# endif /* WRITE_sPLT */
381
382
# ifdef PNG_WRITE_TEXT_SUPPORTED
383
if (info_ptr->num_text > 0)
384
png_write_text(png_ptr, info_ptr, PNG_HAVE_PLTE);
385
# endif /* WRITE_TEXT */
386
387
# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
388
write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
389
# endif /* WRITE_UNKNOWN_CHUNKS */
390
}
391
392
/* Writes the end of the PNG file. If you don't want to write comments or
393
* time information, you can pass NULL for info. If you already wrote these
394
* in png_write_info(), do not write them again here. If you have long
395
* comments, I suggest writing them here, and compressing them.
396
*/
397
void PNGAPI
398
png_write_end(png_structrp png_ptr, png_inforp info_ptr)
399
{
400
png_debug(1, "in png_write_end");
401
402
if (png_ptr == NULL)
403
return;
404
405
if ((png_ptr->mode &
406
(PNG_HAVE_IHDR+PNG_HAVE_IDAT+PNG_AFTER_IDAT+PNG_HAVE_IEND)) !=
407
(PNG_HAVE_IHDR+PNG_HAVE_IDAT+PNG_AFTER_IDAT))
408
{
409
/* Out of place png_write_end: */
410
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
411
png_error(png_ptr, "Missing call to png_write_info");
412
413
else if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 && png_ptr->zowner == 0)
414
{
415
/* TODO: write unknown IDAT here, for the moment allow the app to write
416
* IDAT then call write_end:
417
*/
418
png_app_error(png_ptr, "No IDATs written into file");
419
png_ptr->mode |= PNG_HAVE_IDAT+PNG_AFTER_IDAT;
420
}
421
422
else if ((png_ptr->mode & PNG_AFTER_IDAT) == 0)
423
{
424
affirm(png_ptr->zowner == png_IDAT);
425
png_error(png_ptr, "incomplete PNG image"); /* unrecoverable */
426
}
427
428
else if ((png_ptr->mode & PNG_HAVE_IEND) != 0)
429
{
430
png_app_error(png_ptr, "multiple calls to png_write_end");
431
return;
432
}
433
434
else
435
impossible("not reached");
436
}
437
438
/* And double check that the image rows were all written; this is actually
439
* a harmless error on an interlaced image because the image rows with
440
* data were all passed in or the above check would not work.
441
*
442
* Don't do this if the IDAT came from unknowns (TBD) or the app, above.
443
*
444
* The check depends on the precise logic in png_write_row.
445
*/
446
else if (png_ptr->pass != 7U)
447
png_app_error(png_ptr, "png_write_row not called to last row");
448
449
else
450
debug(png_ptr->row_number == 0U);
451
452
/* See if user wants us to write information chunks */
453
if (info_ptr != NULL)
454
{
455
# ifdef PNG_WRITE_tIME_SUPPORTED
456
/* Check to see if user has supplied a time chunk */
457
if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
458
(info_ptr->time_location & PNG_AFTER_IDAT) != 0)
459
png_write_tIME(png_ptr, &(info_ptr->mod_time));
460
# endif
461
462
# ifdef PNG_WRITE_TEXT_SUPPORTED
463
if (info_ptr->num_text > 0)
464
png_write_text(png_ptr, info_ptr, PNG_AFTER_IDAT);
465
# endif /* WRITE_TEXT */
466
467
# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
468
write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
469
# endif
470
}
471
472
/* Write end of PNG file */
473
png_write_IEND(png_ptr);
474
475
/* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
476
* and restored again in libpng-1.2.30, may cause some applications that
477
* do not set png_ptr->output_flush_fn to crash. If your application
478
* experiences a problem, please try building libpng with
479
* PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
480
* png-mng-implement at lists.sf.net .
481
*/
482
# ifdef PNG_WRITE_FLUSH_SUPPORTED
483
# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
484
if (png_ptr->output_flush_fn != NULL)
485
png_ptr->output_flush_fn(png_ptr);
486
# endif
487
# endif
488
}
489
490
#ifdef PNG_CONVERT_tIME_SUPPORTED
491
void PNGAPI
492
png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
493
{
494
png_debug(1, "in png_convert_from_struct_tm");
495
496
ptime->year = png_check_u16(0/*TODO: fixme*/, 1900 + ttime->tm_year);
497
ptime->month = png_check_byte(0/*TODO: fixme*/, ttime->tm_mon + 1);
498
ptime->day = png_check_byte(0/*TODO: fixme*/, ttime->tm_mday);
499
ptime->hour = png_check_byte(0/*TODO: fixme*/, ttime->tm_hour);
500
ptime->minute = png_check_byte(0/*TODO: fixme*/, ttime->tm_min);
501
ptime->second = png_check_byte(0/*TODO: fixme*/, ttime->tm_sec);
502
}
503
504
void PNGAPI
505
png_convert_from_time_t(png_timep ptime, time_t ttime)
506
{
507
struct tm *tbuf;
508
509
png_debug(1, "in png_convert_from_time_t");
510
511
tbuf = gmtime(&ttime);
512
png_convert_from_struct_tm(ptime, tbuf);
513
}
514
#endif
515
516
/* Initialize png_ptr structure, and allocate any memory needed */
517
PNG_FUNCTION(png_structp,PNGAPI
518
png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
519
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
520
{
521
#ifndef PNG_USER_MEM_SUPPORTED
522
png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
523
error_fn, warn_fn, NULL, NULL, NULL);
524
#else
525
return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
526
warn_fn, NULL, NULL, NULL);
527
}
528
529
/* Alternate initialize png_ptr structure, and allocate any memory needed */
530
PNG_FUNCTION(png_structp,PNGAPI
531
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
532
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
533
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
534
{
535
png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
536
error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
537
#endif /* USER_MEM */
538
539
if (png_ptr != NULL)
540
{
541
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
542
# if !PNG_RELEASE_BUILD
543
/* Always quit on error prior to release */
544
png_ptr->benign_error_action = PNG_ERROR;
545
png_ptr->app_warning_action = PNG_WARN;
546
png_ptr->app_error_action = PNG_ERROR;
547
# else /* RELEASE_BUILD */
548
/* Allow benign errors on write, subject to app control. */
549
# ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
550
png_ptr->benign_error_action = PNG_WARN;
551
png_ptr->app_error_action = PNG_WARN;
552
png_ptr->app_warning_action = PNG_WARN;
553
# else /* !BENIGN_WRITE_ERRORS */
554
/* libpng build without benign error support; the application
555
* author has to be assumed to be correct, so:
556
*/
557
png_ptr->benign_error_action = PNG_ERROR;
558
png_ptr->app_warning_action = PNG_WARN;
559
png_ptr->app_error_action = PNG_ERROR;
560
# endif /* !BENIGN_WRITE_ERRORS */
561
# endif /* RELEASE_BUILD */
562
# endif /* BENIGN_ERRORS */
563
}
564
565
return png_ptr;
566
}
567
568
569
#if defined(PNG_WRITE_INTERLACING_SUPPORTED) ||\
570
defined(PNG_WRITE_TRANSFORMS_SUPPORTED)
571
static void
572
write_row_buffered(png_structrp png_ptr,
573
png_const_bytep row, unsigned int row_info_flags,
574
void (*copy_fn)(png_const_structrp png_ptr, png_bytep row_buffer,
575
png_const_bytep row, png_uint_32 x, unsigned int count, unsigned int p),
576
unsigned int copy_parameter)
577
{
578
unsigned int max_pixels = png_max_pixel_block(png_ptr);
579
const unsigned int pass = png_ptr->pass;
580
const png_uint_32 width = png_ptr->interlaced == PNG_INTERLACE_NONE ?
581
png_ptr->width : PNG_PASS_COLS(png_ptr->width, pass);
582
png_uint_32 x;
583
png_byte prev_pixels[4*2*2]; /* 2 pixels up to 4 2-byte channels each */
584
585
memset(prev_pixels, 0U, sizeof prev_pixels);
586
587
for (x = 0U; x < width; x += max_pixels)
588
{
589
union
590
{
591
PNG_ROW_BUFFER_ALIGN_TYPE force_buffer_alignment;
592
png_byte buffer[PNG_ROW_BUFFER_SIZE];
593
} pixel_buffer;
594
595
if (max_pixels > width - x)
596
max_pixels = (unsigned int)/*SAFE*/(width - x);
597
598
debug((row_info_flags & png_row_end) == 0U); /* must be set here at end */
599
if (x + max_pixels >= width)
600
row_info_flags |= png_row_end;
601
602
/* Copy a block of input pixels into the buffer, effecting the interlace
603
* on the way if required. The argument is the number of pixels in the
604
* buffer, not the number handled from the input which will be larger in
605
* the interlaced case.
606
*/
607
copy_fn(png_ptr, pixel_buffer.buffer, row, x, max_pixels, copy_parameter);
608
609
/* Now pixel_buffer[0..max_pixels-1] contains max_pixels pixels which may
610
* need to be transformed (the interlace has already been handled).
611
*/
612
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
613
if (png_ptr->transform_list != NULL)
614
{
615
png_transform_control tc;
616
617
/* The initial values are the memory format; this was worked out in
618
* png_init_row_info below.
619
*/
620
memset(&tc, 0, sizeof tc);
621
tc.png_ptr = png_ptr;
622
tc.sp = tc.dp = pixel_buffer.buffer;
623
624
tc.width = max_pixels; /* width of block that we have */
625
tc.format = png_ptr->row_format;
626
tc.range = png_ptr->row_range;
627
tc.bit_depth = png_ptr->row_bit_depth;
628
/* tc.init == 0 */
629
/* tc.caching: not used */
630
/* tc.palette: not used */
631
debug(PNG_TC_PIXEL_DEPTH(tc) == png_ptr->row_input_pixel_depth);
632
633
/* Run the list. */
634
png_run_transform_list_backwards(png_ptr, &tc);
635
636
/* Make sure the format that resulted is compatible with PNG: */
637
affirm((tc.format & PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA +
638
PNG_FORMAT_FLAG_COLOR + PNG_FORMAT_FLAG_LINEAR +
639
PNG_FORMAT_FLAG_COLORMAP)) == 0);
640
641
/* Now we must have the PNG format from the IHDR: */
642
affirm(png_ptr->bit_depth == tc.bit_depth &&
643
png_ptr->color_type == PNG_COLOR_TYPE_FROM_FORMAT(tc.format));
644
}
645
# endif /* WRITE_TRANSFORMS */
646
647
/* Call png_write_png_data to write this block of data, the test on
648
* maxpixels says if this is the final block in the row.
649
*/
650
png_write_png_data(png_ptr, prev_pixels, pixel_buffer.buffer, x,
651
max_pixels, row_info_flags);
652
}
653
}
654
#endif /* WRITE { INTERLACING || TRANSFORMS } */
655
656
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
657
static void
658
copy_row(png_const_structrp png_ptr, png_bytep row_buffer,
659
png_const_bytep row, png_uint_32 x, unsigned int count,
660
unsigned int pixel_depth)
661
{
662
/* Copy row[x..x+count] pixels to row_buffer. */
663
png_copy_row(png_ptr, row_buffer, row, x, count, pixel_depth, 1/*clear*/,
664
0/* x_in_dest; row[x]->row_buffer */);
665
}
666
#endif /* WRITE_TRANSFORMS */
667
668
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
669
static void
670
interlace_row_lbd(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp,
671
png_uint_32 x, unsigned int count, const unsigned int B)
672
{
673
/* Pick out the correct pixels for the interlace pass. The basic idea here
674
* is to go through the row with a source pointer and a destination pointer
675
* (sp and dp), and copy the correct pixels for the pass. As the row gets
676
* compacted, sp will always be >= dp, so we should never overwrite anything.
677
* See the default: case for the easiest code to understand.
678
*/
679
const unsigned int pass = png_ptr->pass;
680
png_uint_32 i = PNG_COL_FROM_PASS_COL(x, pass);
681
const unsigned int inc = PNG_PASS_COL_OFFSET(pass);
682
683
/* For pixels less than one byte wide the correct pixels have to be
684
* extracted from the input bytes. Because we are reading data in
685
* the application memory format we cannot rely on the PNG big
686
* endian order. Notice that this was apparently broken before
687
* 1.7.0.
688
*
689
* In libpng 1.7.0 libpng uses a classic bit-pump to optimize the
690
* extraction. In all passes before the last (6/7) no two pixels
691
* are adjacent in the input, so we are always extracting 1 bit.
692
* At present the code uses an 8-bit buffer to avoid coding for
693
* different byte sexes, but this could easily be changed.
694
*
695
* 'i' is the bit-index of bit in the input (sp[]), so,
696
* considering the 1-bit per pixel case, sp[i>>3] is the byte
697
* and the bit is bit (i&7) (0 lowest) on swapped (little endian)
698
* data or 7-(i&7) on PNG default (big-endian) data.
699
*
700
* Define these macros, where:
701
*
702
* B: the log2 bit depth (0, 1, 2 for 1bpp, 2bpp or 4bpp) of
703
* the data; this should be a constant.
704
* sp: the source pointer (sp) (a png_const_bytep)
705
* i: the pixel index in the input (png_uint_32)
706
* j: the bit index in the output (unsigned int)
707
*
708
* Unlike 'i', 'j' is interpreted directly; for LSB bytes it counts
709
* up, for MSB it counts down.
710
*
711
* NOTE: this could all be expanded to eliminate the code below by
712
* the time honoured copy'n'paste into three separate functions. This
713
* might be worth doing in the future.
714
*/
715
# define PIXEL_MASK ((1U << (1<<B))-1U)
716
# define BIT_MASK ((1U << (3-(B)))-1U) /* within a byte */
717
# define SP_BYTE (sp[i>>(3-(B))]) /* byte to use */
718
# define SP_OFFSET_LSB ((BIT_MASK & i) << (B))
719
# define SP_OFFSET_MSB ((BIT_MASK & ~i) << (B))
720
# define SP_PIXEL(sex) ((SP_BYTE >> SP_OFFSET_ ## sex) & PIXEL_MASK)
721
{
722
unsigned int j;
723
unsigned int d;
724
725
/* The data is always in the PNG, big-endian, format: */
726
for (j = 8U, d = 0U; count > 0U; --count, i += inc)
727
{ /* big-endian */
728
j -= 1U<<B;
729
d |= SP_PIXEL(MSB) << j;
730
if (j == 0U) *dp++ = png_check_byte(png_ptr, d), j = 8U, d = 0U;
731
}
732
733
/* The end condition: if j is not 0 the last byte was not
734
* written:
735
*/
736
if (j != 0U) *dp = png_check_byte(png_ptr, d);
737
}
738
# undef PIXEL_MASK
739
# undef BIT_MASK
740
# undef SP_BYTE
741
# undef SP_OFFSET_MSB
742
# undef SP_OFFSET_LSB
743
# undef SP_PIXEL
744
}
745
746
static void
747
interlace_row_byte(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp,
748
png_uint_32 x, unsigned int count, unsigned int cbytes)
749
{
750
const unsigned int pass = png_ptr->pass;
751
const unsigned int inc = PNG_PASS_COL_OFFSET(pass);
752
753
/* Loop through the input copying each pixel to the correct place
754
* in the output. Note that the loop may be executed 0 times if
755
* this is called on a narrow image that does not contain this
756
* pass.
757
*/
758
for (sp += PNG_COL_FROM_PASS_COL(x, pass) * cbytes; count > 0;
759
--count, sp += inc * cbytes, dp += cbytes)
760
memcpy(dp, sp, cbytes);
761
}
762
#endif /* WRITE_INTERLACING */
763
764
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
765
static void
766
write_row_core(png_structrp png_ptr, png_const_bytep row,
767
unsigned int row_info_flags)
768
{
769
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
770
if (png_ptr->transform_list != NULL)
771
write_row_buffered(png_ptr, row, row_info_flags,
772
copy_row, png_ptr->row_input_pixel_depth);
773
774
else
775
# endif /* WRITE_TRANSFORMS */
776
777
/* If control reaches this point the intermediate buffer is not required and
778
* the input data can be used unmodified.
779
*/
780
png_write_png_rows(png_ptr, &row, 1U);
781
PNG_UNUSED(row_info_flags)
782
}
783
784
/* Write a single non-interlaced row. */
785
static void
786
write_row_non_interlaced(png_structrp png_ptr, png_const_bytep row)
787
{
788
const png_uint_32 row_number = png_ptr->row_number+1U;
789
/* There is only one pass, so this is the last pass: */
790
const unsigned int row_info_flags =
791
(row_number == 1U ? png_pass_first_row : 0) |
792
(row_number >= png_ptr->height ? png_pass_last_row : 0) |
793
png_pass_last;
794
795
debug(png_ptr->interlaced == PNG_INTERLACE_NONE);
796
797
write_row_core(png_ptr, row, row_info_flags);
798
}
799
800
/* Write a single interlaced row. */
801
static void
802
write_row_interlaced(png_structrp png_ptr, png_const_bytep row)
803
{
804
const png_uint_32 row_number = png_ptr->row_number+1U;
805
const png_uint_32 height = png_ptr->height;
806
const unsigned int pass = png_ptr->pass;
807
const unsigned int row_info_flags =
808
(row_number == 1U ? png_pass_first_row : 0) |
809
(row_number == PNG_PASS_ROWS(height, pass) ? png_pass_last_row : 0) |
810
(pass == PNG_LAST_PASS(png_ptr->width, height) ? png_pass_last : 0);
811
812
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
813
/* Check that libpng is not doing the interlace: */
814
debug(png_ptr->interlaced != PNG_INTERLACE_NONE &&
815
!png_ptr->do_interlace);
816
# endif /* WRITE_INTERLACING */
817
818
write_row_core(png_ptr, row, row_info_flags);
819
}
820
#endif /* WRITE_TRANSFORMS */
821
822
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
823
/* Interlace a row then write it out. */
824
static void
825
interlace_row(png_structrp png_ptr, png_const_bytep row)
826
{
827
/* The row may not exist in the image (for this pass). */
828
const png_uint_32 row_number = png_ptr->row_number; /* in image */
829
const unsigned int pass = png_ptr->pass;
830
831
if (png_ptr->width > PNG_PASS_START_COL(pass) &&
832
PNG_ROW_IN_INTERLACE_PASS(row_number, pass))
833
{
834
const unsigned int row_info_flags =
835
(row_number == PNG_PASS_START_ROW(pass) ? png_pass_first_row : 0) |
836
(PNG_LAST_PASS_ROW(row_number, pass, png_ptr->height) ?
837
png_pass_last_row : 0) |
838
(pass == PNG_LAST_PASS(png_ptr->width, png_ptr->height) ?
839
png_pass_last : 0);
840
841
if (pass < 6)
842
{
843
/* Libpng is doing the interlacing and pixels need to be selected
844
* from the input row for this pass.
845
*/
846
/* row interlacing uses either the log bit depth for low bit
847
* depth input or the byte count for 8bpp or bigger pixels.
848
*/
849
const unsigned int input_depth = png_ptr->row_input_pixel_depth;
850
unsigned int B = 0; /* log2(input_depth) */
851
852
switch (input_depth)
853
{
854
case 4U: /* B will be 2 */
855
++B;
856
/*FALL THROUGH*/
857
case 2U: /* B will be 1 */
858
++B;
859
/*FALL THROUGH*/
860
case 1U: /* B will be 0 */
861
write_row_buffered(png_ptr, row, row_info_flags,
862
interlace_row_lbd, B);
863
break;
864
865
default: /* Parameter is the pixel size in bytes */
866
write_row_buffered(png_ptr, row, row_info_flags,
867
interlace_row_byte, input_depth >> 3);
868
break;
869
}
870
} /* pass < 6 */
871
872
else /* pass 6: no interlacing required */
873
write_row_core(png_ptr, row, row_info_flags);
874
}
875
876
else
877
{
878
/* This code must advance row_number/pass itself; the row has been
879
* skipped.
880
*/
881
if (row_number+1U < png_ptr->height)
882
png_ptr->row_number = row_number+1U;
883
884
else
885
{
886
png_ptr->row_number = 0U;
887
png_ptr->pass = 0x7U & (pass+1U);
888
}
889
}
890
}
891
#endif /* WRITE_INTERLACING */
892
893
/* Bottleneck API to actually write a number of rows, only exists because the
894
* rows parameter to png_write_rows is wrong.
895
*/
896
static void
897
png_write_rows_internal(png_structrp png_ptr, png_const_bytep *rows,
898
png_uint_32 num_rows)
899
{
900
if (png_ptr != NULL && num_rows > 0U && rows != NULL)
901
{
902
/* Unlike the read code initialization happens automatically: */
903
if (png_ptr->row_number == 0U && png_ptr->pass == 0U)
904
{
905
png_init_row_info(png_ptr);
906
907
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
908
/* If the app takes a png_info from a read operation and if the app has
909
* performed transforms on the data the png_info can contain IHDR
910
* information that cannot be represented in PNG. The code that writes
911
* the IHDR takes the color type from the png_info::format. The app
912
* adds transforms, before or after writing the IHDR, then the IHDR
913
* color_type stored in png_struct::color_type is used in
914
* png_init_row_info above to work out the actual row format.
915
*
916
* Prior to 1.7.0 this was not verified (there was no easy way to do
917
* so). Now we can check it here, however this is an:
918
*
919
* API CHANGE: in 1.7.0 an error may be flagged against bogus
920
* info_struct formats even though the app had removed them itself.
921
* It's just a warning at present.
922
*
923
* The test is that either the row_format produced by the write
924
* transforms exactly matches that in the original info_struct::format
925
* or that the info_struct::format was a simple mapping of the
926
* color_type that ended up in the IHDR:
927
*/
928
if (png_ptr->row_format != png_ptr->info_format &&
929
PNG_FORMAT_FROM_COLOR_TYPE(png_ptr->color_type) !=
930
png_ptr->info_format)
931
png_app_warning(png_ptr, "info_struct format does not match IHDR");
932
# endif /* WRITE_TRANSFORMS */
933
934
/* Perform initialization required before IDATs are written. */
935
png_write_start_IDAT(png_ptr);
936
}
937
938
else if (png_ptr->pass >= 7U) /* too many calls; write already ended */
939
{
940
debug(png_ptr->row_number == 0U);
941
png_app_error(png_ptr, "Too many calls to png_write_row");
942
return;
943
}
944
945
/* The remainder of these tests detect internal errors in libpng */
946
else if (png_ptr->interlaced == PNG_INTERLACE_NONE)
947
affirm(png_ptr->row_number < png_ptr->height && png_ptr->pass == 0U);
948
949
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
950
else if (png_ptr->do_interlace)
951
affirm(png_ptr->row_number < png_ptr->height);
952
# endif /* WRITE_INTERLACING */
953
954
else /* app does interlace */
955
affirm(
956
PNG_PASS_IN_IMAGE(png_ptr->width, png_ptr->height, png_ptr->pass) &&
957
png_ptr->row_number < PNG_PASS_ROWS(png_ptr->height, png_ptr->pass)
958
);
959
960
/* First handle rows that require buffering because of the need to
961
* interlace them or the need to perform write transforms.
962
*/
963
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
964
/* libpng is doing the interlacing, but this only makes a difference to
965
* the first six passes (numbered, in libpng, 0..5); the seventh pass
966
* (numbered 6 by libpng) consists of complete image rows.
967
*/
968
if (png_ptr->do_interlace) while (num_rows > 0U && png_ptr->pass < 6)
969
interlace_row(png_ptr, *rows++), --num_rows;
970
# endif /* WRITE_INTERLACING */
971
972
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
973
/* Transforms required however the row interlacing has already been
974
* handled and we have a complete (PNG) row.
975
*/
976
if (png_ptr->transform_list != NULL)
977
{
978
if (png_ptr->interlaced == PNG_INTERLACE_NONE)
979
while (num_rows > 0U)
980
write_row_non_interlaced(png_ptr, *rows++), --num_rows;
981
982
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
983
else if (png_ptr->do_interlace)
984
while (num_rows > 0U)
985
interlace_row(png_ptr, *rows++), --num_rows;
986
# endif /* WRITE_INTERLACING */
987
988
else /* app does the interlacing */
989
while (num_rows > 0U)
990
write_row_interlaced(png_ptr, *rows++), --num_rows;
991
}
992
# endif /* WRITE_TRANSFORMS */
993
994
/* Finally handle any remaining rows that require no (libpng) interlace
995
* and no transforms.
996
*/
997
if (num_rows > 0U)
998
png_write_png_rows(png_ptr, rows, num_rows);
999
1000
/* Repeat the checks above, but allow for end-of-image. */
1001
if (png_ptr->pass < 7U)
1002
{
1003
if (png_ptr->interlaced == PNG_INTERLACE_NONE)
1004
affirm(png_ptr->row_number < png_ptr->height &&
1005
png_ptr->pass == 0U);
1006
1007
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
1008
else if (png_ptr->do_interlace)
1009
affirm(png_ptr->row_number < png_ptr->height);
1010
# endif /* WRITE_INTERLACING */
1011
1012
else /* app does interlace */
1013
affirm(PNG_PASS_IN_IMAGE(png_ptr->width, png_ptr->height,
1014
png_ptr->pass) &&
1015
png_ptr->row_number <
1016
PNG_PASS_ROWS(png_ptr->height, png_ptr->pass));
1017
}
1018
} /* png_ptr, rows, num_rows all valid */
1019
1020
else if (png_ptr != NULL)
1021
png_app_warning(png_ptr, "Missing rows to row write API");
1022
}
1023
1024
/* ROW WRITE APIs */
1025
/* Called by user to write a single row of image data */
1026
void PNGAPI
1027
png_write_row(png_structrp png_ptr, png_const_bytep row)
1028
{
1029
png_debug(1, "in png_write_row");
1030
png_write_rows_internal(png_ptr, &row, 1U);
1031
}
1032
1033
/* Write a few rows of image data. If the image is interlaced,
1034
* either you will have to write the 7 sub images, or, if you
1035
* have called png_set_interlace_handling(), you will have to
1036
* "write" the image seven times.
1037
*/
1038
void PNGAPI
1039
png_write_rows(png_structrp png_ptr, png_bytepp rows, png_uint_32 num_rows)
1040
{
1041
png_debug(1, "in png_write_rows");
1042
1043
if (png_ptr != NULL)
1044
png_write_rows_internal(png_ptr, png_constcast(png_const_bytep*,rows),
1045
num_rows);
1046
}
1047
1048
/* Write the image. You only need to call this function once, even
1049
* if you are writing an interlaced image.
1050
*/
1051
void PNGAPI
1052
png_write_image(png_structrp png_ptr, png_bytepp image)
1053
{
1054
png_debug(1, "in png_write_image");
1055
1056
if (png_ptr != NULL)
1057
{
1058
int num_pass = 1;
1059
1060
/* The image is always an non-interlaced image. To write it as interlaced
1061
* interlace handling must be present:
1062
*/
1063
if (png_ptr->interlaced)
1064
{
1065
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
1066
num_pass = png_set_interlace_handling(png_ptr);
1067
# else /* !WRITE_INTERLACING */
1068
/* There is no recovery because the IHDR has already been written.
1069
*/
1070
png_error(png_ptr, "No interlace support");
1071
# endif /* !WRITE_INTERLACING */
1072
}
1073
1074
/* And write the whole thing, 7 times if interlacing it: */
1075
for (; num_pass > 0; --num_pass)
1076
png_write_rows(png_ptr, image, png_ptr->height);
1077
}
1078
}
1079
1080
/* Free any memory used in png_ptr struct without freeing the struct itself. */
1081
static void
1082
png_write_destroy(png_structrp png_ptr)
1083
{
1084
png_debug(1, "in png_write_destroy");
1085
1086
png_deflate_destroy(png_ptr);
1087
1088
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
1089
png_transform_free(png_ptr, &png_ptr->transform_list);
1090
#endif
1091
1092
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
1093
png_free(png_ptr, png_ptr->chunk_list);
1094
png_ptr->chunk_list = NULL;
1095
#endif
1096
1097
/* The error handling and memory handling information is left intact at this
1098
* point: the jmp_buf may still have to be freed. See png_destroy_png_struct
1099
* for how this happens.
1100
*/
1101
}
1102
1103
/* Free all memory used by the write.
1104
* In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
1105
* *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
1106
* the passed in info_structs but it would quietly fail to free any of the data
1107
* inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
1108
* has no png_ptr.)
1109
*/
1110
void PNGAPI
1111
png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
1112
{
1113
png_debug(1, "in png_destroy_write_struct");
1114
1115
if (png_ptr_ptr != NULL)
1116
{
1117
png_structrp png_ptr = *png_ptr_ptr;
1118
1119
if (png_ptr != NULL) /* added in libpng 1.6.0 */
1120
{
1121
png_destroy_info_struct(png_ptr, info_ptr_ptr);
1122
1123
*png_ptr_ptr = NULL;
1124
png_write_destroy(png_ptr);
1125
png_destroy_png_struct(png_ptr);
1126
}
1127
}
1128
}
1129
1130
void PNGAPI
1131
png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
1132
{
1133
if (png_ptr == NULL)
1134
return;
1135
1136
png_ptr->write_row_fn = write_row_fn;
1137
}
1138
1139
#ifdef PNG_WRITE_PNG_SUPPORTED
1140
void PNGAPI
1141
png_write_png(png_structrp png_ptr, png_inforp info_ptr,
1142
int transforms, voidp params)
1143
{
1144
if (png_ptr == NULL || info_ptr == NULL)
1145
return;
1146
1147
if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
1148
{
1149
png_app_error(png_ptr, "no rows for png_write_image to write");
1150
return;
1151
}
1152
1153
/* Write the file header information. */
1154
png_write_info(png_ptr, info_ptr);
1155
1156
/* ------ these transformations don't touch the info structure ------- */
1157
1158
/* Invert monochrome pixels */
1159
if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
1160
#ifdef PNG_WRITE_INVERT_SUPPORTED
1161
png_set_invert_mono(png_ptr);
1162
#else
1163
png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
1164
#endif
1165
1166
/* Shift the pixels up to a legal bit depth and fill in
1167
* as appropriate to correctly scale the image.
1168
*/
1169
if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
1170
#ifdef PNG_WRITE_SHIFT_SUPPORTED
1171
if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
1172
png_set_shift(png_ptr, &info_ptr->sig_bit);
1173
#else
1174
png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
1175
#endif
1176
1177
/* Pack pixels into bytes */
1178
if ((transforms & PNG_TRANSFORM_PACKING) != 0)
1179
#ifdef PNG_WRITE_PACK_SUPPORTED
1180
png_set_packing(png_ptr);
1181
#else
1182
png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
1183
#endif
1184
1185
/* Swap location of alpha bytes from ARGB to RGBA */
1186
if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
1187
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
1188
png_set_swap_alpha(png_ptr);
1189
#else
1190
png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
1191
#endif
1192
1193
/* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
1194
* RGB, note that the code expects the input color type to be G or RGB; no
1195
* alpha channel.
1196
*/
1197
if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
1198
PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
1199
{
1200
#ifdef PNG_WRITE_FILLER_SUPPORTED
1201
if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
1202
{
1203
if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1204
png_app_error(png_ptr,
1205
"PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
1206
1207
/* Continue if ignored - this is the pre-1.6.10 behavior */
1208
png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1209
}
1210
1211
else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1212
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1213
#else
1214
png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
1215
#endif
1216
}
1217
1218
/* Flip BGR pixels to RGB */
1219
if ((transforms & PNG_TRANSFORM_BGR) != 0)
1220
#ifdef PNG_WRITE_BGR_SUPPORTED
1221
png_set_bgr(png_ptr);
1222
#else
1223
png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
1224
#endif
1225
1226
/* Swap bytes of 16-bit files to most significant byte first */
1227
if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
1228
#ifdef PNG_WRITE_SWAP_SUPPORTED
1229
png_set_swap(png_ptr);
1230
#else
1231
png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
1232
#endif
1233
1234
/* Swap bits of 1, 2, 4 bit packed pixel formats */
1235
if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
1236
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
1237
png_set_packswap(png_ptr);
1238
#else
1239
png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
1240
#endif
1241
1242
/* Invert the alpha channel from opacity to transparency */
1243
if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
1244
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1245
png_set_invert_alpha(png_ptr);
1246
#else
1247
png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
1248
#endif
1249
1250
/* ----------------------- end of transformations ------------------- */
1251
1252
/* Write the bits */
1253
png_write_image(png_ptr, info_ptr->row_pointers);
1254
1255
/* It is REQUIRED to call this to finish writing the rest of the file */
1256
png_write_end(png_ptr, info_ptr);
1257
1258
PNG_UNUSED(params)
1259
}
1260
#endif /* WRITE_PNG */
1261
1262
1263
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1264
/* Initialize the write structure - general purpose utility. */
1265
static int
1266
png_image_write_init(png_imagep image)
1267
{
1268
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1269
png_safe_error, png_safe_warning);
1270
1271
if (png_ptr != NULL)
1272
{
1273
png_infop info_ptr = png_create_info_struct(png_ptr);
1274
1275
if (info_ptr != NULL)
1276
{
1277
png_controlp control = png_voidcast(png_controlp,
1278
png_malloc_warn(png_ptr, (sizeof *control)));
1279
1280
if (control != NULL)
1281
{
1282
memset(control, 0, (sizeof *control));
1283
1284
control->png_ptr = png_ptr;
1285
control->info_ptr = info_ptr;
1286
control->for_write = 1;
1287
1288
image->opaque = control;
1289
return 1;
1290
}
1291
1292
/* Error clean up */
1293
png_destroy_info_struct(png_ptr, &info_ptr);
1294
}
1295
1296
png_destroy_write_struct(&png_ptr, NULL);
1297
}
1298
1299
return png_image_error(image, "png_image_write_: out of memory");
1300
}
1301
1302
/* Arguments to png_image_write_main: */
1303
typedef struct
1304
{
1305
/* Arguments: */
1306
png_imagep image;
1307
png_const_voidp buffer;
1308
ptrdiff_t row_stride;
1309
png_const_voidp colormap;
1310
int convert_to_8bit;
1311
/* Local variables: */
1312
png_const_voidp first_row;
1313
ptrdiff_t row_bytes;
1314
png_voidp local_row;
1315
/* Byte count for memory writing */
1316
png_bytep memory;
1317
png_alloc_size_t memory_bytes; /* not used for STDIO */
1318
png_alloc_size_t output_bytes; /* running total */
1319
} png_image_write_control;
1320
1321
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1322
* do any necessary byte swapping. The component order is defined by the
1323
* png_image format value.
1324
*/
1325
static int
1326
png_write_image_16bit(png_voidp argument)
1327
{
1328
png_image_write_control *display = png_voidcast(png_image_write_control*,
1329
argument);
1330
png_imagep image = display->image;
1331
png_structrp png_ptr = image->opaque->png_ptr;
1332
1333
png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1334
display->first_row);
1335
png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
1336
png_uint_16p row_end;
1337
const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1338
int aindex = 0;
1339
png_uint_32 y = image->height;
1340
1341
if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1342
{
1343
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1344
if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1345
{
1346
aindex = -1;
1347
++input_row; /* To point to the first component */
1348
++output_row;
1349
}
1350
1351
else
1352
# endif
1353
aindex = channels;
1354
}
1355
1356
else
1357
png_error(png_ptr, "png_write_image: internal call error");
1358
1359
/* Work out the output row end and count over this, note that the increment
1360
* above to 'row' means that row_end can actually be beyond the end of the
1361
* row; this is correct.
1362
*/
1363
row_end = output_row + image->width * (channels+1);
1364
1365
while (y-- > 0)
1366
{
1367
png_const_uint_16p in_ptr = input_row;
1368
png_uint_16p out_ptr = output_row;
1369
1370
while (out_ptr < row_end)
1371
{
1372
const png_uint_16 alpha = in_ptr[aindex];
1373
png_uint_32 reciprocal = 0;
1374
int c;
1375
1376
out_ptr[aindex] = alpha;
1377
1378
/* Calculate a reciprocal. The correct calculation is simply
1379
* component/alpha*65535 << 15. (I.e. 15 bits of precision); this
1380
* allows correct rounding by adding .5 before the shift. 'reciprocal'
1381
* is only initialized when required.
1382
*/
1383
if (alpha > 0 && alpha < 65535)
1384
reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
1385
1386
c = channels;
1387
do /* always at least one channel */
1388
{
1389
png_uint_16 component = *in_ptr++;
1390
1391
/* The following gives 65535 for an alpha of 0, which is fine,
1392
* otherwise if 0/0 is represented as some other value there is more
1393
* likely to be a discontinuity which will probably damage
1394
* compression when moving from a fully transparent area to a
1395
* nearly transparent one. (The assumption here is that opaque
1396
* areas tend not to be 0 intensity.)
1397
*/
1398
if (component >= alpha)
1399
component = 65535;
1400
1401
/* component<alpha, so component/alpha is less than one and
1402
* component*reciprocal is less than 2^31.
1403
*/
1404
else if (component > 0 && alpha < 65535)
1405
{
1406
png_uint_32 calc = component * reciprocal;
1407
calc += 16384; /* round to nearest */
1408
component = png_check_u16(png_ptr, calc >> 15);
1409
}
1410
1411
*out_ptr++ = component;
1412
}
1413
while (--c > 0);
1414
1415
/* Skip to next component (skip the intervening alpha channel) */
1416
++in_ptr;
1417
++out_ptr;
1418
}
1419
1420
png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
1421
input_row += display->row_bytes/(sizeof (png_uint_16));
1422
}
1423
1424
return 1;
1425
}
1426
1427
/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
1428
* is present it must be removed from the components, the components are then
1429
* written in sRGB encoding. No components are added or removed.
1430
*
1431
* Calculate an alpha reciprocal to reverse pre-multiplication. As above the
1432
* calculation can be done to 15 bits of accuracy; however, the output needs to
1433
* be scaled in the range 0..255*65535, so include that scaling here.
1434
*/
1435
#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
1436
1437
static png_byte
1438
png_unpremultiply(png_const_structrp png_ptr, png_uint_32 component,
1439
png_uint_32 alpha, png_uint_32 reciprocal/*from the above macro*/)
1440
{
1441
/* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
1442
* is represented as some other value there is more likely to be a
1443
* discontinuity which will probably damage compression when moving from a
1444
* fully transparent area to a nearly transparent one. (The assumption here
1445
* is that opaque areas tend not to be 0 intensity.)
1446
*
1447
* There is a rounding problem here; if alpha is less than 128 it will end up
1448
* as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
1449
* output change for this too.
1450
*/
1451
if (component >= alpha || alpha < 128)
1452
return 255;
1453
1454
/* component<alpha, so component/alpha is less than one and
1455
* component*reciprocal is less than 2^31.
1456
*/
1457
else if (component > 0)
1458
{
1459
/* The test is that alpha/257 (rounded) is less than 255, the first value
1460
* that becomes 255 is 65407.
1461
* NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
1462
* be exact!) [Could also test reciprocal != 0]
1463
*/
1464
if (alpha < 65407)
1465
{
1466
component *= reciprocal;
1467
component += 64; /* round to nearest */
1468
component >>= 7;
1469
}
1470
1471
else
1472
component *= 255;
1473
1474
/* Convert the component to sRGB. */
1475
return PNG_sRGB_FROM_LINEAR(png_ptr, component);
1476
}
1477
1478
else
1479
return 0;
1480
1481
PNG_UNUSEDRC(png_ptr)
1482
}
1483
1484
static int
1485
png_write_image_8bit(png_voidp argument)
1486
{
1487
png_image_write_control *display = png_voidcast(png_image_write_control*,
1488
argument);
1489
png_imagep image = display->image;
1490
png_structrp png_ptr = image->opaque->png_ptr;
1491
1492
png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1493
display->first_row);
1494
png_bytep output_row = png_voidcast(png_bytep, display->local_row);
1495
png_uint_32 y = image->height;
1496
const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1497
1498
if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1499
{
1500
png_bytep row_end;
1501
int aindex;
1502
1503
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1504
if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1505
{
1506
aindex = -1;
1507
++input_row; /* To point to the first component */
1508
++output_row;
1509
}
1510
1511
else
1512
# endif
1513
aindex = channels;
1514
1515
/* Use row_end in place of a loop counter: */
1516
row_end = output_row + image->width * (channels+1);
1517
1518
while (y-- > 0)
1519
{
1520
png_const_uint_16p in_ptr = input_row;
1521
png_bytep out_ptr = output_row;
1522
1523
while (out_ptr < row_end)
1524
{
1525
png_uint_16 alpha = in_ptr[aindex];
1526
png_byte alphabyte = png_check_byte(png_ptr, PNG_DIV257(alpha));
1527
png_uint_32 reciprocal = 0;
1528
int c;
1529
1530
/* Scale and write the alpha channel. */
1531
out_ptr[aindex] = alphabyte;
1532
1533
if (alphabyte > 0 && alphabyte < 255)
1534
reciprocal = UNP_RECIPROCAL(alpha);
1535
1536
c = channels;
1537
do /* always at least one channel */
1538
*out_ptr++ = png_unpremultiply(png_ptr, *in_ptr++, alpha,
1539
reciprocal);
1540
while (--c > 0);
1541
1542
/* Skip to next component (skip the intervening alpha channel) */
1543
++in_ptr;
1544
++out_ptr;
1545
} /* while out_ptr < row_end */
1546
1547
png_write_row(png_ptr, png_voidcast(png_const_bytep,
1548
display->local_row));
1549
input_row += display->row_bytes/(sizeof (png_uint_16));
1550
} /* while y */
1551
}
1552
1553
else
1554
{
1555
/* No alpha channel, so the row_end really is the end of the row and it
1556
* is sufficient to loop over the components one by one.
1557
*/
1558
png_bytep row_end = output_row + image->width * channels;
1559
1560
while (y-- > 0)
1561
{
1562
png_const_uint_16p in_ptr = input_row;
1563
png_bytep out_ptr = output_row;
1564
1565
while (out_ptr < row_end)
1566
{
1567
png_uint_32 component = *in_ptr++;
1568
1569
component *= 255;
1570
*out_ptr++ = PNG_sRGB_FROM_LINEAR(png_ptr, component);
1571
}
1572
1573
png_write_row(png_ptr, output_row);
1574
input_row += display->row_bytes/(sizeof (png_uint_16));
1575
}
1576
}
1577
1578
return 1;
1579
}
1580
1581
static void
1582
png_image_set_PLTE(png_image_write_control *display)
1583
{
1584
const png_imagep image = display->image;
1585
const void *cmap = display->colormap;
1586
const int entries = image->colormap_entries > 256 ? 256 :
1587
(int)image->colormap_entries;
1588
1589
/* NOTE: the caller must check for cmap != NULL and entries != 0 */
1590
const png_uint_32 format = image->format;
1591
const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
1592
1593
# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
1594
defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
1595
const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
1596
(format & PNG_FORMAT_FLAG_ALPHA) != 0;
1597
# else
1598
# define afirst 0
1599
# endif
1600
1601
# ifdef PNG_FORMAT_BGR_SUPPORTED
1602
const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
1603
# else
1604
# define bgr 0
1605
# endif
1606
1607
int i, num_trans;
1608
png_color palette[256];
1609
png_byte tRNS[256];
1610
1611
memset(tRNS, 255, (sizeof tRNS));
1612
memset(palette, 0, (sizeof palette));
1613
1614
for (i=num_trans=0; i<entries; ++i)
1615
{
1616
/* This gets automatically converted to sRGB with reversal of the
1617
* pre-multiplication if the color-map has an alpha channel.
1618
*/
1619
if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
1620
{
1621
png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
1622
1623
entry += i * channels;
1624
1625
if ((channels & 1) != 0) /* no alpha */
1626
{
1627
if (channels >= 3) /* RGB */
1628
{
1629
palette[i].blue = PNG_sRGB_FROM_LINEAR(
1630
display->image->opaque->png_ptr, 255 * entry[(2 ^ bgr)]);
1631
palette[i].green = PNG_sRGB_FROM_LINEAR(
1632
display->image->opaque->png_ptr, 255 * entry[1]);
1633
palette[i].red = PNG_sRGB_FROM_LINEAR(
1634
display->image->opaque->png_ptr, 255 * entry[bgr]);
1635
}
1636
1637
else /* Gray */
1638
palette[i].blue = palette[i].red = palette[i].green =
1639
PNG_sRGB_FROM_LINEAR(display->image->opaque->png_ptr,
1640
255 * *entry);
1641
}
1642
1643
else /* alpha */
1644
{
1645
png_uint_16 alpha = entry[afirst ? 0 : channels-1];
1646
png_byte alphabyte = png_check_byte(
1647
display->image->opaque->png_ptr, PNG_DIV257(alpha));
1648
png_uint_32 reciprocal = 0;
1649
1650
/* Calculate a reciprocal, as in the png_write_image_8bit code above
1651
* this is designed to produce a value scaled to 255*65535 when
1652
* divided by 128 (i.e. asr 7).
1653
*/
1654
if (alphabyte > 0 && alphabyte < 255)
1655
reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
1656
1657
tRNS[i] = alphabyte;
1658
if (alphabyte < 255)
1659
num_trans = i+1;
1660
1661
if (channels >= 3) /* RGB */
1662
{
1663
palette[i].blue = png_unpremultiply(
1664
display->image->opaque->png_ptr, entry[afirst + (2 ^ bgr)],
1665
alpha, reciprocal);
1666
palette[i].green = png_unpremultiply(
1667
display->image->opaque->png_ptr, entry[afirst + 1], alpha,
1668
reciprocal);
1669
palette[i].red = png_unpremultiply(
1670
display->image->opaque->png_ptr, entry[afirst + bgr], alpha,
1671
reciprocal);
1672
}
1673
1674
else /* gray */
1675
palette[i].blue = palette[i].red = palette[i].green =
1676
png_unpremultiply(display->image->opaque->png_ptr,
1677
entry[afirst], alpha, reciprocal);
1678
}
1679
}
1680
1681
else /* Color-map has sRGB values */
1682
{
1683
png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
1684
1685
entry += i * channels;
1686
1687
switch (channels)
1688
{
1689
case 4:
1690
tRNS[i] = entry[afirst ? 0 : 3];
1691
if (tRNS[i] < 255)
1692
num_trans = i+1;
1693
/* FALL THROUGH */
1694
case 3:
1695
palette[i].blue = entry[afirst + (2 ^ bgr)];
1696
palette[i].green = entry[afirst + 1];
1697
palette[i].red = entry[afirst + bgr];
1698
break;
1699
1700
case 2:
1701
tRNS[i] = entry[1 ^ afirst];
1702
if (tRNS[i] < 255)
1703
num_trans = i+1;
1704
/* FALL THROUGH */
1705
case 1:
1706
palette[i].blue = palette[i].red = palette[i].green =
1707
entry[afirst];
1708
break;
1709
1710
default:
1711
break;
1712
}
1713
}
1714
}
1715
1716
# ifdef afirst
1717
# undef afirst
1718
# endif
1719
# ifdef bgr
1720
# undef bgr
1721
# endif
1722
1723
png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
1724
entries);
1725
1726
if (num_trans > 0)
1727
png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
1728
num_trans, NULL);
1729
1730
image->colormap_entries = entries;
1731
}
1732
1733
static int
1734
png_image_write_main(png_voidp argument)
1735
{
1736
png_image_write_control *display = png_voidcast(png_image_write_control*,
1737
argument);
1738
png_imagep image = display->image;
1739
png_structrp png_ptr = image->opaque->png_ptr;
1740
png_inforp info_ptr = image->opaque->info_ptr;
1741
png_uint_32 format = image->format;
1742
1743
/* The following four ints are actually booleans */
1744
int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
1745
int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
1746
int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
1747
int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
1748
1749
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
1750
/* Make sure we error out on any bad situation */
1751
png_set_benign_errors(png_ptr, 0/*error*/);
1752
# endif
1753
1754
/* Default the 'row_stride' parameter if required, also check the row stride
1755
* and total image size to ensure that they are within the system limits.
1756
*/
1757
{
1758
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
1759
1760
/* The test is slightly evil: it assumes that a signed pointer difference
1761
* (ptrdiff_t) can hold a maximum value of half, rounded down, of the
1762
* maximum of a (size_t). This is almost certain to be true.
1763
*/
1764
if (image->width <= (PNG_SIZE_MAX >> 1)/channels) /* no overflow */
1765
{
1766
png_alloc_size_t check;
1767
const png_alloc_size_t png_row_stride =
1768
(png_alloc_size_t)/*SAFE*/image->width * channels;
1769
1770
if (display->row_stride == 0)
1771
display->row_stride = (ptrdiff_t)png_row_stride;
1772
1773
if (display->row_stride < 0)
1774
check = -display->row_stride;
1775
1776
else
1777
check = display->row_stride;
1778
1779
if (check >= png_row_stride)
1780
{
1781
/* Now check for overflow of the image buffer calculation; check for
1782
* (size_t) overflow here. This detects issues with the
1783
* PNG_IMAGE_BUFFER_SIZE macro.
1784
*/
1785
if (image->height > PNG_SIZE_MAX/png_row_stride)
1786
png_error(image->opaque->png_ptr, "memory image too large");
1787
}
1788
1789
else
1790
png_error(image->opaque->png_ptr, "supplied row stride too small");
1791
}
1792
1793
else
1794
png_error(image->opaque->png_ptr, "image row stride too large");
1795
}
1796
1797
/* Set the required transforms then write the rows in the correct order. */
1798
if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
1799
{
1800
if (display->colormap != NULL && image->colormap_entries > 0)
1801
{
1802
png_uint_32 entries = image->colormap_entries;
1803
1804
png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
1805
entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
1806
PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
1807
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1808
1809
png_image_set_PLTE(display);
1810
}
1811
1812
else
1813
png_error(image->opaque->png_ptr,
1814
"no color-map for color-mapped image");
1815
}
1816
1817
else
1818
png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
1819
write_16bit ? 16 : 8,
1820
((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
1821
((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
1822
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1823
1824
/* Counter-intuitively the data transformations must be called *after*
1825
* png_write_info, not before as in the read code, but the 'set' functions
1826
* must still be called before. Just set the color space information, never
1827
* write an interlaced image.
1828
*/
1829
1830
if (write_16bit != 0)
1831
{
1832
/* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
1833
png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
1834
1835
if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
1836
png_set_cHRM_fixed(png_ptr, info_ptr,
1837
/* color x y */
1838
/* white */ 31270, 32900,
1839
/* red */ 64000, 33000,
1840
/* green */ 30000, 60000,
1841
/* blue */ 15000, 6000
1842
);
1843
}
1844
1845
else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
1846
png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
1847
1848
/* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
1849
* space must still be gamma encoded.
1850
*/
1851
else
1852
png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
1853
1854
/* Write the file header. */
1855
png_write_info(png_ptr, info_ptr);
1856
1857
/* Now set up the data transformations (*after* the header is written),
1858
* remove the handled transformations from the 'format' flags for checking.
1859
*
1860
* First check for a little endian system if writing 16 bit files.
1861
*/
1862
if (write_16bit != 0)
1863
{
1864
PNG_CONST png_uint_16 le = 0x0001;
1865
1866
if ((*(png_const_bytep) & le) != 0)
1867
png_set_swap(png_ptr);
1868
}
1869
1870
# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
1871
if ((format & PNG_FORMAT_FLAG_BGR) != 0)
1872
{
1873
if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
1874
png_set_bgr(png_ptr);
1875
format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_BGR);
1876
}
1877
# endif
1878
1879
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1880
if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
1881
{
1882
if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
1883
png_set_swap_alpha(png_ptr);
1884
format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_AFIRST);
1885
}
1886
# endif
1887
1888
/* If there are 16 or fewer color-map entries we wrote a lower bit depth
1889
* above, but the application data is still byte packed.
1890
*/
1891
if (colormap != 0 && image->colormap_entries <= 16)
1892
png_set_packing(png_ptr);
1893
1894
/* That should have handled all (both) the transforms. */
1895
if ((format & PNG_BIC_MASK(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
1896
PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
1897
png_error(png_ptr, "png_write_image: unsupported transformation");
1898
1899
{
1900
png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
1901
ptrdiff_t row_bytes = display->row_stride;
1902
1903
if (linear != 0)
1904
row_bytes *= (sizeof (png_uint_16));
1905
1906
if (row_bytes < 0)
1907
row += (image->height-1) * (-row_bytes);
1908
1909
display->first_row = row;
1910
display->row_bytes = row_bytes;
1911
}
1912
1913
/* Select the right compression mode based on the presence or absence of the
1914
* 'fast' flag. This will use whatever options are available in the libpng
1915
* build. It is always supported.
1916
*/
1917
png_set_compression(png_ptr, (image->flags & PNG_IMAGE_FLAG_FAST) != 0 ?
1918
PNG_COMPRESSION_HIGH_SPEED : PNG_COMPRESSION_HIGH);
1919
1920
/* Check for the cases that currently require a pre-transform on the row
1921
* before it is written. This only applies when the input is 16-bit and
1922
* either there is an alpha channel or it is converted to 8-bit.
1923
*/
1924
if ((linear != 0 && alpha != 0 ) ||
1925
(colormap == 0 && display->convert_to_8bit != 0))
1926
{
1927
png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
1928
png_get_rowbytes(png_ptr, info_ptr)));
1929
int result;
1930
1931
display->local_row = row;
1932
if (write_16bit != 0)
1933
result = png_safe_execute(image, png_write_image_16bit, display);
1934
else
1935
result = png_safe_execute(image, png_write_image_8bit, display);
1936
display->local_row = NULL;
1937
1938
png_free(png_ptr, row);
1939
1940
/* Skip the 'write_end' on error: */
1941
if (result == 0)
1942
return 0;
1943
}
1944
1945
/* Otherwise this is the case where the input is in a format currently
1946
* supported by the rest of the libpng write code; call it directly.
1947
*/
1948
else
1949
{
1950
png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
1951
ptrdiff_t row_bytes = display->row_bytes;
1952
png_uint_32 y = image->height;
1953
1954
while (y-- > 0)
1955
{
1956
png_write_row(png_ptr, row);
1957
row += row_bytes;
1958
}
1959
}
1960
1961
png_write_end(png_ptr, info_ptr);
1962
return 1;
1963
}
1964
1965
1966
static void (PNGCBAPI
1967
image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
1968
png_size_t size)
1969
{
1970
png_image_write_control *display = png_voidcast(png_image_write_control*,
1971
png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
1972
const png_alloc_size_t ob = display->output_bytes;
1973
1974
/* Check for overflow; this should never happen: */
1975
if (size <= ((png_alloc_size_t)-1) - ob)
1976
{
1977
/* I don't think libpng ever does this, but just in case: */
1978
if (size > 0)
1979
{
1980
if (display->memory_bytes >= ob+size) /* writing */
1981
memcpy(display->memory+ob, data, size);
1982
1983
/* Always update the size: */
1984
display->output_bytes = ob+size;
1985
}
1986
}
1987
1988
else
1989
png_error(png_ptr, "png_image_write_to_memory: PNG too big");
1990
}
1991
1992
static void (PNGCBAPI
1993
image_memory_flush)(png_structp png_ptr)
1994
{
1995
PNG_UNUSED(png_ptr)
1996
}
1997
1998
static int
1999
png_image_write_memory(png_voidp argument)
2000
{
2001
png_image_write_control *display = png_voidcast(png_image_write_control*,
2002
argument);
2003
2004
/* The rest of the memory-specific init and write_main in an error protected
2005
* environment. This case needs to use callbacks for the write operations
2006
* since libpng has no built in support for writing to memory.
2007
*/
2008
png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
2009
image_memory_write, image_memory_flush);
2010
2011
return png_image_write_main(display);
2012
}
2013
2014
int PNGAPI
2015
png_image_write_to_memory(png_imagep image, void *memory,
2016
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
2017
const void *buffer, ptrdiff_t row_stride, const void *colormap)
2018
{
2019
/* Write the image to the given buffer, or count the bytes if it is NULL */
2020
if (image != NULL && image->version == PNG_IMAGE_VERSION)
2021
{
2022
if (memory_bytes != NULL && buffer != NULL)
2023
{
2024
/* This is to give the caller an easier error detection in the NULL
2025
* case and guard against uninitialized variable problems:
2026
*/
2027
if (memory == NULL)
2028
*memory_bytes = 0;
2029
2030
if (png_image_write_init(image) != 0)
2031
{
2032
png_image_write_control display;
2033
int result;
2034
2035
memset(&display, 0, (sizeof display));
2036
display.image = image;
2037
display.buffer = buffer;
2038
display.row_stride = row_stride;
2039
display.colormap = colormap;
2040
display.convert_to_8bit = convert_to_8bit;
2041
display.memory = png_voidcast(png_bytep, memory);
2042
display.memory_bytes = *memory_bytes;
2043
display.output_bytes = 0;
2044
2045
result = png_safe_execute(image, png_image_write_memory, &display);
2046
png_image_free(image);
2047
2048
/* write_memory returns true even if we ran out of buffer. */
2049
if (result)
2050
{
2051
/* On out-of-buffer this function returns '0' but still updates
2052
* memory_bytes:
2053
*/
2054
if (memory != NULL && display.output_bytes > *memory_bytes)
2055
result = 0;
2056
2057
*memory_bytes = display.output_bytes;
2058
}
2059
2060
return result;
2061
}
2062
2063
else
2064
return 0;
2065
}
2066
2067
else
2068
return png_image_error(image,
2069
"png_image_write_to_memory: invalid argument");
2070
}
2071
2072
else if (image != NULL)
2073
return png_image_error(image,
2074
"png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
2075
2076
else
2077
return 0;
2078
}
2079
2080
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
2081
int PNGAPI
2082
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
2083
const void *buffer, ptrdiff_t row_stride, const void *colormap)
2084
{
2085
/* Write the image to the given (FILE*). */
2086
if (image != NULL && image->version == PNG_IMAGE_VERSION)
2087
{
2088
if (file != NULL && buffer != NULL)
2089
{
2090
if (png_image_write_init(image) != 0 &&
2091
png_image_init_io(image, file) != 0)
2092
{
2093
png_image_write_control display;
2094
int result;
2095
2096
memset(&display, 0, (sizeof display));
2097
display.image = image;
2098
display.buffer = buffer;
2099
display.row_stride = row_stride;
2100
display.colormap = colormap;
2101
display.convert_to_8bit = convert_to_8bit;
2102
2103
result = png_safe_execute(image, png_image_write_main, &display);
2104
png_image_free(image);
2105
return result;
2106
}
2107
2108
else
2109
return 0;
2110
}
2111
2112
else
2113
return png_image_error(image,
2114
"png_image_write_to_stdio: invalid argument");
2115
}
2116
2117
else if (image != NULL)
2118
return png_image_error(image,
2119
"png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
2120
2121
else
2122
return 0;
2123
}
2124
2125
int PNGAPI
2126
png_image_write_to_file(png_imagep image, const char *file_name,
2127
int convert_to_8bit, const void *buffer, ptrdiff_t row_stride,
2128
const void *colormap)
2129
{
2130
/* Write the image to the named file. */
2131
if (image != NULL && image->version == PNG_IMAGE_VERSION)
2132
{
2133
if (file_name != NULL && buffer != NULL)
2134
{
2135
FILE *fp = fopen(file_name, "wb");
2136
2137
if (fp != NULL)
2138
{
2139
if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2140
row_stride, colormap) != 0)
2141
{
2142
int error; /* from fflush/fclose */
2143
2144
/* Make sure the file is flushed correctly. */
2145
if (fflush(fp) == 0 && ferror(fp) == 0)
2146
{
2147
if (fclose(fp) == 0)
2148
return 1;
2149
2150
error = errno; /* from fclose */
2151
}
2152
2153
else
2154
{
2155
error = errno; /* from fflush or ferror */
2156
(void)fclose(fp);
2157
}
2158
2159
(void)remove(file_name);
2160
/* The image has already been cleaned up; this is just used to
2161
* set the error (because the original write succeeded).
2162
*/
2163
return png_image_error(image, strerror(error));
2164
}
2165
2166
else
2167
{
2168
/* Clean up: just the opened file. */
2169
(void)fclose(fp);
2170
(void)remove(file_name);
2171
return 0;
2172
}
2173
}
2174
2175
else
2176
return png_image_error(image, strerror(errno));
2177
}
2178
2179
else
2180
return png_image_error(image,
2181
"png_image_write_to_file: invalid argument");
2182
}
2183
2184
else if (image != NULL)
2185
return png_image_error(image,
2186
"png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
2187
2188
else
2189
return 0;
2190
}
2191
#endif /* SIMPLIFIED_WRITE_STDIO */
2192
#endif /* SIMPLIFIED_WRITE */
2193
#endif /* WRITE */
2194
2195