2
/* pngwutil.c - utilities to write a PNG file
4
* libpng 1.0.8 - July 24, 2000
5
* For conditions of distribution and use, see copyright notice in png.h
6
* Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
7
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
14
/* Place a 32-bit number into a buffer in PNG byte order. We work
15
* with unsigned numbers for convenience, although one supported
16
* ancillary chunk uses signed (two's complement) numbers.
19
png_save_uint_32(png_bytep buf, png_uint_32 i)
21
buf[0] = (png_byte)((i >> 24) & 0xff);
22
buf[1] = (png_byte)((i >> 16) & 0xff);
23
buf[2] = (png_byte)((i >> 8) & 0xff);
24
buf[3] = (png_byte)(i & 0xff);
27
#if defined(PNG_WRITE_pCAL_SUPPORTED)
28
/* The png_save_int_32 function assumes integers are stored in two's
29
* complement format. If this isn't the case, then this routine needs to
30
* be modified to write data in two's complement format.
33
png_save_int_32(png_bytep buf, png_int_32 i)
35
buf[0] = (png_byte)((i >> 24) & 0xff);
36
buf[1] = (png_byte)((i >> 16) & 0xff);
37
buf[2] = (png_byte)((i >> 8) & 0xff);
38
buf[3] = (png_byte)(i & 0xff);
42
/* Place a 16-bit number into a buffer in PNG byte order.
43
* The parameter is declared unsigned int, not png_uint_16,
44
* just to avoid potential problems on pre-ANSI C compilers.
47
png_save_uint_16(png_bytep buf, unsigned int i)
49
buf[0] = (png_byte)((i >> 8) & 0xff);
50
buf[1] = (png_byte)(i & 0xff);
53
/* Write a PNG chunk all at once. The type is an array of ASCII characters
54
* representing the chunk name. The array must be at least 4 bytes in
55
* length, and does not need to be null terminated. To be safe, pass the
56
* pre-defined chunk names here, and if you need a new one, define it
57
* where the others are defined. The length is the length of the data.
58
* All the data must be present. If that is not possible, use the
59
* png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
63
png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
64
png_bytep data, png_size_t length)
66
png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
67
png_write_chunk_data(png_ptr, data, length);
68
png_write_chunk_end(png_ptr);
71
/* Write the start of a PNG chunk. The type is the chunk type.
72
* The total_length is the sum of the lengths of all the data you will be
73
* passing in png_write_chunk_data().
76
png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
80
png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length);
82
/* write the length */
83
png_save_uint_32(buf, length);
84
png_write_data(png_ptr, buf, (png_size_t)4);
86
/* write the chunk name */
87
png_write_data(png_ptr, chunk_name, (png_size_t)4);
88
/* reset the crc and run it over the chunk name */
89
png_reset_crc(png_ptr);
90
png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
93
/* Write the data of a PNG chunk started with png_write_chunk_start().
94
* Note that multiple calls to this function are allowed, and that the
95
* sum of the lengths from these calls *must* add up to the total_length
96
* given to png_write_chunk_start().
99
png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
101
/* write the data, and run the CRC over it */
102
if (data != NULL && length > 0)
104
png_calculate_crc(png_ptr, data, length);
105
png_write_data(png_ptr, data, length);
109
/* Finish a chunk started with png_write_chunk_start(). */
111
png_write_chunk_end(png_structp png_ptr)
116
png_save_uint_32(buf, png_ptr->crc);
118
png_write_data(png_ptr, buf, (png_size_t)4);
121
/* Simple function to write the signature. If we have already written
122
* the magic bytes of the signature, or more likely, the PNG stream is
123
* being embedded into another stream and doesn't need its own signature,
124
* we should call png_set_sig_bytes() to tell libpng how many of the
125
* bytes have already been written.
128
png_write_sig(png_structp png_ptr)
130
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
131
/* write the rest of the 8 byte signature */
132
png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
133
(png_size_t)8 - png_ptr->sig_bytes);
136
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
138
* This pair of functions encapsulates the operation of (a) compressing a
139
* text string, and (b) issuing it later as a series of chunk data writes.
140
* The compression_state structure is shared context for these functions
141
* set up by the caller in order to make the whole mess thread-safe.
146
char *input; /* the uncompressed input data */
147
int input_len; /* its length */
148
int num_output_ptr; /* number of output pointers used */
149
int max_output_ptr; /* size of output_ptr */
150
png_charpp output_ptr; /* array of pointers to output */
153
/* compress given text into storage in the png_ptr structure */
154
static int /* PRIVATE */
155
png_text_compress(png_structp png_ptr,
156
png_charp text, png_size_t text_len, int compression,
157
compression_state *comp)
161
comp->num_output_ptr = comp->max_output_ptr = 0;
162
comp->output_ptr = NULL;
165
/* we may just want to pass the text right through */
166
if (compression == PNG_TEXT_COMPRESSION_NONE)
169
comp->input_len = text_len;
170
return((int)text_len);
173
if (compression >= PNG_TEXT_COMPRESSION_LAST)
175
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
177
sprintf(msg, "Unknown compression type %d", compression);
178
png_warning(png_ptr, msg);
180
png_warning(png_ptr, "Unknown compression type");
184
/* We can't write the chunk until we find out how much data we have,
185
* which means we need to run the compressor first and save the
186
* output. This shouldn't be a problem, as the vast majority of
187
* comments should be reasonable, but we will set up an array of
188
* malloc'd pointers to be sure.
190
* If we knew the application was well behaved, we could simplify this
191
* greatly by assuming we can always malloc an output buffer large
192
* enough to hold the compressed text ((1001 * text_len / 1000) + 12)
193
* and malloc this directly. The only time this would be a bad idea is
194
* if we can't malloc more than 64K and we have 64K of random input
195
* data, or if the input string is incredibly large (although this
196
* wouldn't cause a failure, just a slowdown due to swapping).
199
/* set up the compression buffers */
200
png_ptr->zstream.avail_in = (uInt)text_len;
201
png_ptr->zstream.next_in = (Bytef *)text;
202
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
203
png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
205
/* this is the same compression loop as in png_write_row() */
208
/* compress the data */
209
ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
213
if (png_ptr->zstream.msg != NULL)
214
png_error(png_ptr, png_ptr->zstream.msg);
216
png_error(png_ptr, "zlib error");
218
/* check to see if we need more room */
219
if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in)
221
/* make sure the output array has room */
222
if (comp->num_output_ptr >= comp->max_output_ptr)
226
old_max = comp->max_output_ptr;
227
comp->max_output_ptr = comp->num_output_ptr + 4;
228
if (comp->output_ptr != NULL)
232
old_ptr = comp->output_ptr;
233
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
234
(png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
235
png_memcpy(comp->output_ptr, old_ptr,
236
old_max * sizeof (png_charp));
237
png_free(png_ptr, old_ptr);
240
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
241
(png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
245
comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr,
246
(png_uint_32)png_ptr->zbuf_size);
247
png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
249
comp->num_output_ptr++;
251
/* and reset the buffer */
252
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
253
png_ptr->zstream.next_out = png_ptr->zbuf;
255
/* continue until we don't have any more to compress */
256
} while (png_ptr->zstream.avail_in);
258
/* finish the compression */
261
/* tell zlib we are finished */
262
ret = deflate(&png_ptr->zstream, Z_FINISH);
266
/* check to see if we need more room */
267
if (!(png_ptr->zstream.avail_out))
269
/* check to make sure our output array has room */
270
if (comp->num_output_ptr >= comp->max_output_ptr)
274
old_max = comp->max_output_ptr;
275
comp->max_output_ptr = comp->num_output_ptr + 4;
276
if (comp->output_ptr != NULL)
280
old_ptr = comp->output_ptr;
281
/* This could be optimized to realloc() */
282
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
283
(png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
284
png_memcpy(comp->output_ptr, old_ptr,
285
old_max * sizeof (png_charp));
286
png_free(png_ptr, old_ptr);
289
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
290
(png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
293
/* save off the data */
294
comp->output_ptr[comp->num_output_ptr] =
295
(png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size);
296
png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
298
comp->num_output_ptr++;
300
/* and reset the buffer pointers */
301
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
302
png_ptr->zstream.next_out = png_ptr->zbuf;
305
else if (ret != Z_STREAM_END)
307
/* we got an error */
308
if (png_ptr->zstream.msg != NULL)
309
png_error(png_ptr, png_ptr->zstream.msg);
311
png_error(png_ptr, "zlib error");
313
} while (ret != Z_STREAM_END);
315
/* text length is number of buffers plus last buffer */
316
text_len = png_ptr->zbuf_size * comp->num_output_ptr;
317
if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
318
text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
320
return((int)text_len);
323
/* ship the compressed text out via chunk writes */
324
static void /* PRIVATE */
325
png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
329
/* handle the no-compression case */
332
png_write_chunk_data(png_ptr, (png_bytep)comp->input, comp->input_len);
336
/* write saved output buffers, if any */
337
for (i = 0; i < comp->num_output_ptr; i++)
339
png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],
341
png_free(png_ptr, comp->output_ptr[i]);
342
comp->output_ptr[i]=NULL;
344
if (comp->max_output_ptr != 0)
345
png_free(png_ptr, comp->output_ptr);
346
comp->output_ptr=NULL;
347
/* write anything left in zbuf */
348
if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
349
png_write_chunk_data(png_ptr, png_ptr->zbuf,
350
png_ptr->zbuf_size - png_ptr->zstream.avail_out);
352
/* reset zlib for another zTXt/iTXt or the image data */
353
deflateReset(&png_ptr->zstream);
358
/* Write the IHDR chunk, and update the png_struct with the necessary
359
* information. Note that the rest of this code depends upon this
360
* information being correct.
363
png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
364
int bit_depth, int color_type, int compression_type, int filter_type,
367
#ifdef PNG_USE_LOCAL_ARRAYS
370
png_byte buf[13]; /* buffer to store the IHDR info */
372
png_debug(1, "in png_write_IHDR\n");
373
/* Check that we have valid input data from the application info */
376
case PNG_COLOR_TYPE_GRAY:
383
case 16: png_ptr->channels = 1; break;
384
default: png_error(png_ptr,"Invalid bit depth for grayscale image");
387
case PNG_COLOR_TYPE_RGB:
388
if (bit_depth != 8 && bit_depth != 16)
389
png_error(png_ptr, "Invalid bit depth for RGB image");
390
png_ptr->channels = 3;
392
case PNG_COLOR_TYPE_PALETTE:
398
case 8: png_ptr->channels = 1; break;
399
default: png_error(png_ptr, "Invalid bit depth for paletted image");
402
case PNG_COLOR_TYPE_GRAY_ALPHA:
403
if (bit_depth != 8 && bit_depth != 16)
404
png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
405
png_ptr->channels = 2;
407
case PNG_COLOR_TYPE_RGB_ALPHA:
408
if (bit_depth != 8 && bit_depth != 16)
409
png_error(png_ptr, "Invalid bit depth for RGBA image");
410
png_ptr->channels = 4;
413
png_error(png_ptr, "Invalid image color type specified");
416
if (compression_type != PNG_COMPRESSION_TYPE_BASE)
418
png_warning(png_ptr, "Invalid compression type specified");
419
compression_type = PNG_COMPRESSION_TYPE_BASE;
422
if (filter_type != PNG_FILTER_TYPE_BASE)
424
png_warning(png_ptr, "Invalid filter type specified");
425
filter_type = PNG_FILTER_TYPE_BASE;
428
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
429
if (interlace_type != PNG_INTERLACE_NONE &&
430
interlace_type != PNG_INTERLACE_ADAM7)
432
png_warning(png_ptr, "Invalid interlace type specified");
433
interlace_type = PNG_INTERLACE_ADAM7;
436
interlace_type=PNG_INTERLACE_NONE;
439
/* save off the relevent information */
440
png_ptr->bit_depth = (png_byte)bit_depth;
441
png_ptr->color_type = (png_byte)color_type;
442
png_ptr->interlaced = (png_byte)interlace_type;
443
png_ptr->width = width;
444
png_ptr->height = height;
446
png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
447
png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3);
448
/* set the usr info, so any transformations can modify it */
449
png_ptr->usr_width = png_ptr->width;
450
png_ptr->usr_bit_depth = png_ptr->bit_depth;
451
png_ptr->usr_channels = png_ptr->channels;
453
/* pack the header information into the buffer */
454
png_save_uint_32(buf, width);
455
png_save_uint_32(buf + 4, height);
456
buf[8] = (png_byte)bit_depth;
457
buf[9] = (png_byte)color_type;
458
buf[10] = (png_byte)compression_type;
459
buf[11] = (png_byte)filter_type;
460
buf[12] = (png_byte)interlace_type;
462
/* write the chunk */
463
png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
465
/* initialize zlib with PNG info */
466
png_ptr->zstream.zalloc = png_zalloc;
467
png_ptr->zstream.zfree = png_zfree;
468
png_ptr->zstream.opaque = (voidpf)png_ptr;
469
if (!(png_ptr->do_filter))
471
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
472
png_ptr->bit_depth < 8)
473
png_ptr->do_filter = PNG_FILTER_NONE;
475
png_ptr->do_filter = PNG_ALL_FILTERS;
477
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
479
if (png_ptr->do_filter != PNG_FILTER_NONE)
480
png_ptr->zlib_strategy = Z_FILTERED;
482
png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
484
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
485
png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
486
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
487
png_ptr->zlib_mem_level = 8;
488
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
489
png_ptr->zlib_window_bits = 15;
490
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
491
png_ptr->zlib_method = 8;
492
deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
493
png_ptr->zlib_method, png_ptr->zlib_window_bits,
494
png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
495
png_ptr->zstream.next_out = png_ptr->zbuf;
496
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
498
png_ptr->mode = PNG_HAVE_IHDR;
501
/* write the palette. We are careful not to trust png_color to be in the
502
* correct order for PNG, so people can redefine it to any convenient
506
png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
508
#ifdef PNG_USE_LOCAL_ARRAYS
515
png_debug(1, "in png_write_PLTE\n");
517
#ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
518
!png_ptr->empty_plte_permitted &&
520
num_pal == 0) || num_pal > 256)
522
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
524
png_error(png_ptr, "Invalid number of colors in palette");
528
png_warning(png_ptr, "Invalid number of colors in palette");
533
png_ptr->num_palette = (png_uint_16)num_pal;
534
png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
536
png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, num_pal * 3);
537
#ifndef PNG_NO_POINTER_INDEXING
538
for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
540
buf[0] = pal_ptr->red;
541
buf[1] = pal_ptr->green;
542
buf[2] = pal_ptr->blue;
543
png_write_chunk_data(png_ptr, buf, (png_size_t)3);
546
/* This is a little slower but some buggy compilers need to do this instead */
548
for (i = 0; i < num_pal; i++)
550
buf[0] = pal_ptr[i].red;
551
buf[1] = pal_ptr[i].green;
552
buf[2] = pal_ptr[i].blue;
553
png_write_chunk_data(png_ptr, buf, (png_size_t)3);
556
png_write_chunk_end(png_ptr);
557
png_ptr->mode |= PNG_HAVE_PLTE;
560
/* write an IDAT chunk */
562
png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
564
#ifdef PNG_USE_LOCAL_ARRAYS
567
png_debug(1, "in png_write_IDAT\n");
568
png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
569
png_ptr->mode |= PNG_HAVE_IDAT;
572
/* write an IEND chunk */
574
png_write_IEND(png_structp png_ptr)
576
#ifdef PNG_USE_LOCAL_ARRAYS
579
png_debug(1, "in png_write_IEND\n");
580
png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, (png_size_t)0);
581
png_ptr->mode |= PNG_HAVE_IEND;
584
#if defined(PNG_WRITE_gAMA_SUPPORTED)
585
/* write a gAMA chunk */
586
#ifdef PNG_FLOATING_POINT_SUPPORTED
588
png_write_gAMA(png_structp png_ptr, double file_gamma)
590
#ifdef PNG_USE_LOCAL_ARRAYS
596
png_debug(1, "in png_write_gAMA\n");
597
/* file_gamma is saved in 1/100,000ths */
598
igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
599
png_save_uint_32(buf, igamma);
600
png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
603
#ifdef PNG_FIXED_POINT_SUPPORTED
605
png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
607
#ifdef PNG_USE_LOCAL_ARRAYS
612
png_debug(1, "in png_write_gAMA\n");
613
/* file_gamma is saved in 1/100,000ths */
614
png_save_uint_32(buf, file_gamma);
615
png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
620
#if defined(PNG_WRITE_sRGB_SUPPORTED)
621
/* write a sRGB chunk */
623
png_write_sRGB(png_structp png_ptr, int srgb_intent)
625
#ifdef PNG_USE_LOCAL_ARRAYS
630
png_debug(1, "in png_write_sRGB\n");
631
if(srgb_intent >= PNG_sRGB_INTENT_LAST)
633
"Invalid sRGB rendering intent specified");
634
buf[0]=(png_byte)srgb_intent;
635
png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
639
#if defined(PNG_WRITE_iCCP_SUPPORTED)
640
/* write an iCCP chunk */
642
png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
643
png_charp profile, int profile_len)
645
#ifdef PNG_USE_LOCAL_ARRAYS
650
compression_state comp;
652
png_debug(1, "in png_write_iCCP\n");
653
if (name == NULL || (name_len = png_check_keyword(png_ptr, name,
656
png_warning(png_ptr, "Empty keyword in iCCP chunk");
660
if (compression_type)
661
png_warning(png_ptr, "Unknown compression type in iCCP chunk");
667
profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len,
668
PNG_TEXT_COMPRESSION_zTXt, &comp);
670
/* make sure we include the NULL after the name and the compression type */
671
png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
672
(png_uint_32)name_len+profile_len+2);
673
png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2);
676
png_write_compressed_data_out(png_ptr, &comp);
678
png_write_chunk_end(png_ptr);
679
png_free(png_ptr, new_name);
683
#if defined(PNG_WRITE_sPLT_SUPPORTED)
684
/* write a sPLT chunk */
686
png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
688
#ifdef PNG_USE_LOCAL_ARRAYS
693
png_byte entrybuf[10];
694
int entry_size = (spalette->depth == 8 ? 6 : 10);
695
int palette_size = entry_size * spalette->nentries;
697
#ifdef PNG_NO_POINTER_INDEXING
701
png_debug(1, "in png_write_sPLT\n");
702
if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr,
703
spalette->name, &new_name))==0)
705
png_warning(png_ptr, "Empty keyword in sPLT chunk");
709
/* make sure we include the NULL after the name */
710
png_write_chunk_start(png_ptr, (png_bytep) png_sPLT,
711
(png_uint_32)(name_len + 2 + palette_size));
712
png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1);
713
png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1);
715
/* loop through each palette entry, writing appropriately */
716
#ifndef PNG_NO_POINTER_INDEXING
717
for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++)
719
if (spalette->depth == 8)
721
entrybuf[0] = (png_byte)ep->red;
722
entrybuf[1] = (png_byte)ep->green;
723
entrybuf[2] = (png_byte)ep->blue;
724
entrybuf[3] = (png_byte)ep->alpha;
725
png_save_uint_16(entrybuf + 4, ep->frequency);
729
png_save_uint_16(entrybuf + 0, ep->red);
730
png_save_uint_16(entrybuf + 2, ep->green);
731
png_save_uint_16(entrybuf + 4, ep->blue);
732
png_save_uint_16(entrybuf + 6, ep->alpha);
733
png_save_uint_16(entrybuf + 8, ep->frequency);
735
png_write_chunk_data(png_ptr, entrybuf, entry_size);
738
ep=spalette->entries;
739
for (i=0; i>spalette->nentries; i++)
741
if (spalette->depth == 8)
743
entrybuf[0] = (png_byte)ep[i].red;
744
entrybuf[1] = (png_byte)ep[i].green;
745
entrybuf[2] = (png_byte)ep[i].blue;
746
entrybuf[3] = (png_byte)ep[i].alpha;
747
png_save_uint_16(entrybuf + 4, ep[i].frequency);
751
png_save_uint_16(entrybuf + 0, ep[i].red);
752
png_save_uint_16(entrybuf + 2, ep[i].green);
753
png_save_uint_16(entrybuf + 4, ep[i].blue);
754
png_save_uint_16(entrybuf + 6, ep[i].alpha);
755
png_save_uint_16(entrybuf + 8, ep[i].frequency);
757
png_write_chunk_data(png_ptr, entrybuf, entry_size);
761
png_write_chunk_end(png_ptr);
762
png_free(png_ptr, new_name);
766
#if defined(PNG_WRITE_sBIT_SUPPORTED)
767
/* write the sBIT chunk */
769
png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
771
#ifdef PNG_USE_LOCAL_ARRAYS
777
png_debug(1, "in png_write_sBIT\n");
778
/* make sure we don't depend upon the order of PNG_COLOR_8 */
779
if (color_type & PNG_COLOR_MASK_COLOR)
783
maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
784
png_ptr->usr_bit_depth);
785
if (sbit->red == 0 || sbit->red > maxbits ||
786
sbit->green == 0 || sbit->green > maxbits ||
787
sbit->blue == 0 || sbit->blue > maxbits)
789
png_warning(png_ptr, "Invalid sBIT depth specified");
793
buf[1] = sbit->green;
799
if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
801
png_warning(png_ptr, "Invalid sBIT depth specified");
808
if (color_type & PNG_COLOR_MASK_ALPHA)
810
if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
812
png_warning(png_ptr, "Invalid sBIT depth specified");
815
buf[size++] = sbit->alpha;
818
png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
822
#if defined(PNG_WRITE_cHRM_SUPPORTED)
823
/* write the cHRM chunk */
824
#ifdef PNG_FLOATING_POINT_SUPPORTED
826
png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
827
double red_x, double red_y, double green_x, double green_y,
828
double blue_x, double blue_y)
830
#ifdef PNG_USE_LOCAL_ARRAYS
836
png_debug(1, "in png_write_cHRM\n");
837
/* each value is saved in 1/100,000ths */
838
if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
839
white_x + white_y > 1.0)
841
png_warning(png_ptr, "Invalid cHRM white point specified");
842
#if !defined(PNG_NO_CONSOLE_IO)
843
fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y);
847
itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
848
png_save_uint_32(buf, itemp);
849
itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
850
png_save_uint_32(buf + 4, itemp);
852
if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
855
png_warning(png_ptr, "Invalid cHRM red point specified");
858
itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
859
png_save_uint_32(buf + 8, itemp);
860
itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
861
png_save_uint_32(buf + 12, itemp);
863
if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
864
green_x + green_y > 1.0)
866
png_warning(png_ptr, "Invalid cHRM green point specified");
869
itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
870
png_save_uint_32(buf + 16, itemp);
871
itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
872
png_save_uint_32(buf + 20, itemp);
874
if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
875
blue_x + blue_y > 1.0)
877
png_warning(png_ptr, "Invalid cHRM blue point specified");
880
itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
881
png_save_uint_32(buf + 24, itemp);
882
itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
883
png_save_uint_32(buf + 28, itemp);
885
png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
888
#ifdef PNG_FIXED_POINT_SUPPORTED
890
png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
891
png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
892
png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
893
png_fixed_point blue_y)
895
#ifdef PNG_USE_LOCAL_ARRAYS
900
png_debug(1, "in png_write_cHRM\n");
901
/* each value is saved in 1/100,000ths */
902
if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L)
904
png_warning(png_ptr, "Invalid fixed cHRM white point specified");
905
#if !defined(PNG_NO_CONSOLE_IO)
906
fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y);
910
png_save_uint_32(buf, white_x);
911
png_save_uint_32(buf + 4, white_y);
913
if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L)
915
png_warning(png_ptr, "Invalid cHRM fixed red point specified");
918
png_save_uint_32(buf + 8, red_x);
919
png_save_uint_32(buf + 12, red_y);
921
if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L)
923
png_warning(png_ptr, "Invalid fixed cHRM green point specified");
926
png_save_uint_32(buf + 16, green_x);
927
png_save_uint_32(buf + 20, green_y);
929
if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L)
931
png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
934
png_save_uint_32(buf + 24, blue_x);
935
png_save_uint_32(buf + 28, blue_y);
937
png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
942
#if defined(PNG_WRITE_tRNS_SUPPORTED)
943
/* write the tRNS chunk */
945
png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
946
int num_trans, int color_type)
948
#ifdef PNG_USE_LOCAL_ARRAYS
953
png_debug(1, "in png_write_tRNS\n");
954
if (color_type == PNG_COLOR_TYPE_PALETTE)
956
if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
958
png_warning(png_ptr,"Invalid number of transparent colors specified");
961
/* write the chunk out as it is */
962
png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans);
964
else if (color_type == PNG_COLOR_TYPE_GRAY)
966
/* one 16 bit value */
967
png_save_uint_16(buf, tran->gray);
968
png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
970
else if (color_type == PNG_COLOR_TYPE_RGB)
972
/* three 16 bit values */
973
png_save_uint_16(buf, tran->red);
974
png_save_uint_16(buf + 2, tran->green);
975
png_save_uint_16(buf + 4, tran->blue);
976
png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
980
png_warning(png_ptr, "Can't write tRNS with an alpha channel");
985
#if defined(PNG_WRITE_bKGD_SUPPORTED)
986
/* write the background chunk */
988
png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
990
#ifdef PNG_USE_LOCAL_ARRAYS
995
png_debug(1, "in png_write_bKGD\n");
996
if (color_type == PNG_COLOR_TYPE_PALETTE)
999
#ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
1000
(!png_ptr->empty_plte_permitted ||
1001
(png_ptr->empty_plte_permitted && png_ptr->num_palette)) &&
1003
back->index > png_ptr->num_palette)
1005
png_warning(png_ptr, "Invalid background palette index");
1008
buf[0] = back->index;
1009
png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
1011
else if (color_type & PNG_COLOR_MASK_COLOR)
1013
png_save_uint_16(buf, back->red);
1014
png_save_uint_16(buf + 2, back->green);
1015
png_save_uint_16(buf + 4, back->blue);
1016
png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
1020
png_save_uint_16(buf, back->gray);
1021
png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
1026
#if defined(PNG_WRITE_hIST_SUPPORTED)
1027
/* write the histogram */
1029
png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
1031
#ifdef PNG_USE_LOCAL_ARRAYS
1037
png_debug(1, "in png_write_hIST\n");
1038
if (num_hist > (int)png_ptr->num_palette)
1040
png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
1041
png_ptr->num_palette);
1042
png_warning(png_ptr, "Invalid number of histogram entries specified");
1046
png_write_chunk_start(png_ptr, (png_bytep)png_hIST, (png_uint_32)(num_hist * 2));
1047
for (i = 0; i < num_hist; i++)
1049
png_save_uint_16(buf, hist[i]);
1050
png_write_chunk_data(png_ptr, buf, (png_size_t)2);
1052
png_write_chunk_end(png_ptr);
1056
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
1057
defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
1058
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
1059
* and if invalid, correct the keyword rather than discarding the entire
1060
* chunk. The PNG 1.0 specification requires keywords 1-79 characters in
1061
* length, forbids leading or trailing whitespace, multiple internal spaces,
1062
* and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
1064
* The new_key is allocated to hold the corrected keyword and must be freed
1065
* by the calling routine. This avoids problems with trying to write to
1066
* static keywords without having to have duplicate copies of the strings.
1068
png_size_t /* PRIVATE */
1069
png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
1075
png_debug(1, "in png_check_keyword\n");
1078
if (key == NULL || (key_len = png_strlen(key)) == 0)
1080
png_chunk_warning(png_ptr, "zero length keyword");
1081
return ((png_size_t)0);
1084
png_debug1(2, "Keyword to be checked is '%s'\n", key);
1086
*new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 1));
1088
/* Replace non-printing characters with a blank and print a warning */
1089
for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
1091
if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
1093
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1096
sprintf(msg, "invalid keyword character 0x%02X", *kp);
1097
png_chunk_warning(png_ptr, msg);
1099
png_chunk_warning(png_ptr, "invalid character in keyword");
1110
/* Remove any trailing white space. */
1111
kp = *new_key + key_len - 1;
1114
png_chunk_warning(png_ptr, "trailing spaces removed from keyword");
1123
/* Remove any leading white space. */
1127
png_chunk_warning(png_ptr, "leading spaces removed from keyword");
1136
png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
1138
/* Remove multiple internal spaces. */
1139
for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
1141
if (*kp == ' ' && kflag == 0)
1146
else if (*kp == ' ')
1160
png_free(png_ptr, *new_key);
1162
png_chunk_warning(png_ptr, "Zero length keyword");
1167
png_chunk_warning(png_ptr, "keyword length must be 1 - 79 characters");
1176
#if defined(PNG_WRITE_tEXt_SUPPORTED)
1177
/* write a tEXt chunk */
1179
png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
1180
png_size_t text_len)
1182
#ifdef PNG_USE_LOCAL_ARRAYS
1188
png_debug(1, "in png_write_tEXt\n");
1189
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1191
png_warning(png_ptr, "Empty keyword in tEXt chunk");
1195
if (text == NULL || *text == '\0')
1198
text_len = png_strlen(text);
1200
/* make sure we include the 0 after the key */
1201
png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1);
1203
* We leave it to the application to meet PNG-1.0 requirements on the
1204
* contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1205
* any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1206
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1208
png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
1210
png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
1212
png_write_chunk_end(png_ptr);
1213
png_free(png_ptr, new_key);
1217
#if defined(PNG_WRITE_zTXt_SUPPORTED)
1218
/* write a compressed text chunk */
1220
png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
1221
png_size_t text_len, int compression)
1223
#ifdef PNG_USE_LOCAL_ARRAYS
1229
compression_state comp;
1231
png_debug(1, "in png_write_zTXt\n");
1233
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1235
png_warning(png_ptr, "Empty keyword in zTXt chunk");
1239
if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
1241
png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
1242
png_free(png_ptr, new_key);
1246
text_len = png_strlen(text);
1248
png_free(png_ptr, new_key);
1250
/* compute the compressed data; do it now for the length */
1251
text_len = png_text_compress(png_ptr, text, text_len, compression,
1254
/* write start of chunk */
1255
png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32)
1256
(key_len+text_len+2));
1258
png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1);
1259
buf[0] = (png_byte)compression;
1260
/* write compression */
1261
png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
1262
/* write the compressed data */
1263
png_write_compressed_data_out(png_ptr, &comp);
1265
/* close the chunk */
1266
png_write_chunk_end(png_ptr);
1270
#if defined(PNG_WRITE_iTXt_SUPPORTED)
1271
/* write an iTXt chunk */
1273
png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
1274
png_charp lang, png_charp lang_key, png_charp text)
1276
#ifdef PNG_USE_LOCAL_ARRAYS
1279
png_size_t lang_len, key_len, lang_key_len, text_len;
1280
png_charp new_lang, new_key;
1282
compression_state comp;
1284
png_debug(1, "in png_write_iTXt\n");
1286
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1288
png_warning(png_ptr, "Empty keyword in iTXt chunk");
1291
if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang,
1294
png_warning(png_ptr, "Empty language field in iTXt chunk");
1297
lang_key_len = png_strlen(lang_key);
1298
text_len = png_strlen(text);
1300
if (text == NULL || *text == '\0')
1303
/* compute the compressed data; do it now for the length */
1304
text_len = png_text_compress(png_ptr, text, text_len, compression-2,
1307
/* make sure we include the compression flag, the compression byte,
1308
* and the NULs after the key, lang, and lang_key parts */
1310
png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
1312
5 /* comp byte, comp flag, terminators for key, lang and lang_key */
1319
* We leave it to the application to meet PNG-1.0 requirements on the
1320
* contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1321
* any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1322
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1324
png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
1326
/* set the compression flag */
1327
if (compression == PNG_ITXT_COMPRESSION_NONE || \
1328
compression == PNG_TEXT_COMPRESSION_NONE)
1330
else /* compression == PNG_ITXT_COMPRESSION_zTXt */
1332
/* set the compression method */
1334
png_write_chunk_data(png_ptr, cbuf, 2);
1336
png_write_chunk_data(png_ptr, (png_bytep)new_lang, lang_len + 1);
1337
png_write_chunk_data(png_ptr, (png_bytep)lang_key, lang_key_len+1);
1338
png_write_chunk_data(png_ptr, '\0', 1);
1340
png_write_compressed_data_out(png_ptr, &comp);
1342
png_write_chunk_end(png_ptr);
1343
png_free(png_ptr, new_key);
1344
png_free(png_ptr, new_lang);
1348
#if defined(PNG_WRITE_oFFs_SUPPORTED)
1349
/* write the oFFs chunk */
1351
png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset,
1352
png_uint_32 y_offset,
1355
#ifdef PNG_USE_LOCAL_ARRAYS
1360
png_debug(1, "in png_write_oFFs\n");
1361
if (unit_type >= PNG_OFFSET_LAST)
1362
png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
1364
png_save_uint_32(buf, x_offset);
1365
png_save_uint_32(buf + 4, y_offset);
1366
buf[8] = (png_byte)unit_type;
1368
png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
1372
#if defined(PNG_WRITE_pCAL_SUPPORTED)
1373
/* write the pCAL chunk (described in the PNG extensions document) */
1375
png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
1376
png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
1378
#ifdef PNG_USE_LOCAL_ARRAYS
1381
png_size_t purpose_len, units_len, total_len;
1382
png_uint_32p params_len;
1384
png_charp new_purpose;
1387
png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
1388
if (type >= PNG_EQUATION_LAST)
1389
png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1391
purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
1392
png_debug1(3, "pCAL purpose length = %d\n", purpose_len);
1393
units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
1394
png_debug1(3, "pCAL units length = %d\n", units_len);
1395
total_len = purpose_len + units_len + 10;
1397
params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
1398
*sizeof(png_uint_32)));
1400
/* Find the length of each parameter, making sure we don't count the
1401
null terminator for the last parameter. */
1402
for (i = 0; i < nparams; i++)
1404
params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1405
png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]);
1406
total_len += (png_size_t)params_len[i];
1409
png_debug1(3, "pCAL total length = %d\n", total_len);
1410
png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
1411
png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len);
1412
png_save_int_32(buf, X0);
1413
png_save_int_32(buf + 4, X1);
1414
buf[8] = (png_byte)type;
1415
buf[9] = (png_byte)nparams;
1416
png_write_chunk_data(png_ptr, buf, (png_size_t)10);
1417
png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
1419
png_free(png_ptr, new_purpose);
1421
for (i = 0; i < nparams; i++)
1423
png_write_chunk_data(png_ptr, (png_bytep)params[i],
1424
(png_size_t)params_len[i]);
1427
png_free(png_ptr, params_len);
1428
png_write_chunk_end(png_ptr);
1432
#if defined(PNG_WRITE_sCAL_SUPPORTED)
1433
/* write the sCAL chunk */
1434
#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
1436
png_write_sCAL(png_structp png_ptr, int unit, double width,double height)
1438
#ifdef PNG_USE_LOCAL_ARRAYS
1441
png_size_t total_len;
1442
char wbuf[32], hbuf[32];
1444
png_debug(1, "in png_write_sCAL\n");
1446
#if defined(_WIN32_WCE)
1447
/* sprintf() function is not supported on WindowsCE */
1450
swprintf(wc_buf, TEXT("%12.12e"), width);
1451
WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, wbuf, 32, NULL, NULL);
1452
swprintf(wc_buf, TEXT("%12.12e"), height);
1453
WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, hbuf, 32, NULL, NULL);
1456
sprintf(wbuf, "%12.12e", width);
1457
sprintf(hbuf, "%12.12e", height);
1459
total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
1461
png_debug1(3, "sCAL total length = %d\n", total_len);
1462
png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
1463
png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
1464
png_write_chunk_data(png_ptr, (png_bytep)wbuf, strlen(wbuf)+1);
1465
png_write_chunk_data(png_ptr, (png_bytep)hbuf, strlen(hbuf));
1467
png_write_chunk_end(png_ptr);
1470
#ifdef PNG_FIXED_POINT_SUPPORTED
1472
png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
1475
#ifdef PNG_USE_LOCAL_ARRAYS
1478
png_size_t total_len;
1479
char wbuf[32], hbuf[32];
1481
png_debug(1, "in png_write_sCAL_s\n");
1483
strcpy(wbuf,(const char *)width);
1484
strcpy(hbuf,(const char *)height);
1485
total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
1487
png_debug1(3, "sCAL total length = %d\n", total_len);
1488
png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
1489
png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
1490
png_write_chunk_data(png_ptr, (png_bytep)wbuf, strlen(wbuf)+1);
1491
png_write_chunk_data(png_ptr, (png_bytep)hbuf, strlen(hbuf));
1493
png_write_chunk_end(png_ptr);
1499
#if defined(PNG_WRITE_pHYs_SUPPORTED)
1500
/* write the pHYs chunk */
1502
png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1503
png_uint_32 y_pixels_per_unit,
1506
#ifdef PNG_USE_LOCAL_ARRAYS
1511
png_debug(1, "in png_write_pHYs\n");
1512
if (unit_type >= PNG_RESOLUTION_LAST)
1513
png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
1515
png_save_uint_32(buf, x_pixels_per_unit);
1516
png_save_uint_32(buf + 4, y_pixels_per_unit);
1517
buf[8] = (png_byte)unit_type;
1519
png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
1523
#if defined(PNG_WRITE_tIME_SUPPORTED)
1524
/* Write the tIME chunk. Use either png_convert_from_struct_tm()
1525
* or png_convert_from_time_t(), or fill in the structure yourself.
1528
png_write_tIME(png_structp png_ptr, png_timep mod_time)
1530
#ifdef PNG_USE_LOCAL_ARRAYS
1535
png_debug(1, "in png_write_tIME\n");
1536
if (mod_time->month > 12 || mod_time->month < 1 ||
1537
mod_time->day > 31 || mod_time->day < 1 ||
1538
mod_time->hour > 23 || mod_time->second > 60)
1540
png_warning(png_ptr, "Invalid time specified for tIME chunk");
1544
png_save_uint_16(buf, mod_time->year);
1545
buf[2] = mod_time->month;
1546
buf[3] = mod_time->day;
1547
buf[4] = mod_time->hour;
1548
buf[5] = mod_time->minute;
1549
buf[6] = mod_time->second;
1551
png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
1555
/* initializes the row writing capability of libpng */
1557
png_write_start_row(png_structp png_ptr)
1559
#ifdef PNG_USE_LOCAL_ARRAYS
1560
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1562
/* start of interlace block */
1563
int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1565
/* offset to next interlace block */
1566
int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1568
/* start of interlace block in the y direction */
1569
int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1571
/* offset to next interlace block in the y direction */
1572
int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1575
png_size_t buf_size;
1577
png_debug(1, "in png_write_start_row\n");
1578
buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels *
1579
png_ptr->usr_bit_depth + 7) >> 3) + 1);
1581
/* set up row buffer */
1582
png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
1583
png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
1585
/* set up filtering buffer, if using this filter */
1586
if (png_ptr->do_filter & PNG_FILTER_SUB)
1588
png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
1589
(png_ptr->rowbytes + 1));
1590
png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
1593
/* We only need to keep the previous row if we are using one of these. */
1594
if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
1596
/* set up previous row buffer */
1597
png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
1598
png_memset(png_ptr->prev_row, 0, buf_size);
1600
if (png_ptr->do_filter & PNG_FILTER_UP)
1602
png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
1603
(png_ptr->rowbytes + 1));
1604
png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
1607
if (png_ptr->do_filter & PNG_FILTER_AVG)
1609
png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
1610
(png_ptr->rowbytes + 1));
1611
png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
1614
if (png_ptr->do_filter & PNG_FILTER_PAETH)
1616
png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
1617
(png_ptr->rowbytes + 1));
1618
png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
1622
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1623
/* if interlaced, we need to set up width and height of pass */
1624
if (png_ptr->interlaced)
1626
if (!(png_ptr->transformations & PNG_INTERLACE))
1628
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
1629
png_pass_ystart[0]) / png_pass_yinc[0];
1630
png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
1631
png_pass_start[0]) / png_pass_inc[0];
1635
png_ptr->num_rows = png_ptr->height;
1636
png_ptr->usr_width = png_ptr->width;
1642
png_ptr->num_rows = png_ptr->height;
1643
png_ptr->usr_width = png_ptr->width;
1645
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1646
png_ptr->zstream.next_out = png_ptr->zbuf;
1649
/* Internal use only. Called when finished processing a row of data. */
1651
png_write_finish_row(png_structp png_ptr)
1653
#ifdef PNG_USE_LOCAL_ARRAYS
1654
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1656
/* start of interlace block */
1657
int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1659
/* offset to next interlace block */
1660
int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1662
/* start of interlace block in the y direction */
1663
int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1665
/* offset to next interlace block in the y direction */
1666
int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1671
png_debug(1, "in png_write_finish_row\n");
1673
png_ptr->row_number++;
1675
/* see if we are done */
1676
if (png_ptr->row_number < png_ptr->num_rows)
1679
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1680
/* if interlaced, go to next pass */
1681
if (png_ptr->interlaced)
1683
png_ptr->row_number = 0;
1684
if (png_ptr->transformations & PNG_INTERLACE)
1690
/* loop until we find a non-zero width or height pass */
1694
if (png_ptr->pass >= 7)
1696
png_ptr->usr_width = (png_ptr->width +
1697
png_pass_inc[png_ptr->pass] - 1 -
1698
png_pass_start[png_ptr->pass]) /
1699
png_pass_inc[png_ptr->pass];
1700
png_ptr->num_rows = (png_ptr->height +
1701
png_pass_yinc[png_ptr->pass] - 1 -
1702
png_pass_ystart[png_ptr->pass]) /
1703
png_pass_yinc[png_ptr->pass];
1704
if (png_ptr->transformations & PNG_INTERLACE)
1706
} while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
1710
/* reset the row above the image for the next pass */
1711
if (png_ptr->pass < 7)
1713
if (png_ptr->prev_row != NULL)
1714
png_memset(png_ptr->prev_row, 0,
1715
(png_size_t) (((png_uint_32)png_ptr->usr_channels *
1716
(png_uint_32)png_ptr->usr_bit_depth *
1717
png_ptr->width + 7) >> 3) + 1);
1723
/* if we get here, we've just written the last row, so we need
1724
to flush the compressor */
1727
/* tell the compressor we are done */
1728
ret = deflate(&png_ptr->zstream, Z_FINISH);
1729
/* check for an error */
1732
/* check to see if we need more room */
1733
if (!(png_ptr->zstream.avail_out))
1735
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
1736
png_ptr->zstream.next_out = png_ptr->zbuf;
1737
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1740
else if (ret != Z_STREAM_END)
1742
if (png_ptr->zstream.msg != NULL)
1743
png_error(png_ptr, png_ptr->zstream.msg);
1745
png_error(png_ptr, "zlib error");
1747
} while (ret != Z_STREAM_END);
1749
/* write any extra space */
1750
if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
1752
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
1753
png_ptr->zstream.avail_out);
1756
deflateReset(&png_ptr->zstream);
1759
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
1760
/* Pick out the correct pixels for the interlace pass.
1761
* The basic idea here is to go through the row with a source
1762
* pointer and a destination pointer (sp and dp), and copy the
1763
* correct pixels for the pass. As the row gets compacted,
1764
* sp will always be >= dp, so we should never overwrite anything.
1765
* See the default: case for the easiest code to understand.
1768
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
1770
#ifdef PNG_USE_LOCAL_ARRAYS
1771
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1773
/* start of interlace block */
1774
int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1776
/* offset to next interlace block */
1777
int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1780
png_debug(1, "in png_do_write_interlace\n");
1781
/* we don't have to do anything on the last pass (6) */
1782
#if defined(PNG_USELESS_TESTS_SUPPORTED)
1783
if (row != NULL && row_info != NULL && pass < 6)
1788
/* each pixel depth is handled separately */
1789
switch (row_info->pixel_depth)
1799
png_uint_32 row_width = row_info->width;
1804
for (i = png_pass_start[pass]; i < row_width;
1805
i += png_pass_inc[pass])
1807
sp = row + (png_size_t)(i >> 3);
1808
value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
1809
d |= (value << shift);
1814
*dp++ = (png_byte)d;
1833
png_uint_32 row_width = row_info->width;
1838
for (i = png_pass_start[pass]; i < row_width;
1839
i += png_pass_inc[pass])
1841
sp = row + (png_size_t)(i >> 2);
1842
value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
1843
d |= (value << shift);
1848
*dp++ = (png_byte)d;
1866
png_uint_32 row_width = row_info->width;
1871
for (i = png_pass_start[pass]; i < row_width;
1872
i += png_pass_inc[pass])
1874
sp = row + (png_size_t)(i >> 1);
1875
value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
1876
d |= (value << shift);
1881
*dp++ = (png_byte)d;
1896
png_uint_32 row_width = row_info->width;
1897
png_size_t pixel_bytes;
1899
/* start at the beginning */
1901
/* find out how many bytes each pixel takes up */
1902
pixel_bytes = (row_info->pixel_depth >> 3);
1903
/* loop through the row, only looking at the pixels that
1905
for (i = png_pass_start[pass]; i < row_width;
1906
i += png_pass_inc[pass])
1908
/* find out where the original pixel is */
1909
sp = row + (png_size_t)i * pixel_bytes;
1910
/* move the pixel */
1912
png_memcpy(dp, sp, pixel_bytes);
1919
/* set new row width */
1920
row_info->width = (row_info->width +
1921
png_pass_inc[pass] - 1 -
1922
png_pass_start[pass]) /
1924
row_info->rowbytes = ((row_info->width *
1925
row_info->pixel_depth + 7) >> 3);
1930
/* This filters the row, chooses which filter to use, if it has not already
1931
* been specified by the application, and then writes the row out with the
1934
#define PNG_MAXSUM (~((png_uint_32)0) >> 1)
1935
#define PNG_HISHIFT 10
1936
#define PNG_LOMASK ((png_uint_32)0xffffL)
1937
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
1939
png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
1941
png_bytep prev_row, best_row, row_buf;
1942
png_uint_32 mins, bpp;
1943
png_byte filter_to_do = png_ptr->do_filter;
1944
png_uint_32 row_bytes = row_info->rowbytes;
1945
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1946
int num_p_filters = (int)png_ptr->num_prev_filters;
1949
png_debug(1, "in png_write_find_filter\n");
1950
/* find out how many bytes offset each pixel is */
1951
bpp = (row_info->pixel_depth + 7) / 8;
1953
prev_row = png_ptr->prev_row;
1954
best_row = row_buf = png_ptr->row_buf;
1957
/* The prediction method we use is to find which method provides the
1958
* smallest value when summing the absolute values of the distances
1959
* from zero, using anything >= 128 as negative numbers. This is known
1960
* as the "minimum sum of absolute differences" heuristic. Other
1961
* heuristics are the "weighted minimum sum of absolute differences"
1962
* (experimental and can in theory improve compression), and the "zlib
1963
* predictive" method (not implemented yet), which does test compressions
1964
* of lines using different filter methods, and then chooses the
1965
* (series of) filter(s) that give minimum compressed data size (VERY
1966
* computationally expensive).
1968
* GRR 980525: consider also
1969
* (1) minimum sum of absolute differences from running average (i.e.,
1970
* keep running sum of non-absolute differences & count of bytes)
1971
* [track dispersion, too? restart average if dispersion too large?]
1972
* (1b) minimum sum of absolute differences from sliding average, probably
1973
* with window size <= deflate window (usually 32K)
1974
* (2) minimum sum of squared differences from zero or running average
1975
* (i.e., ~ root-mean-square approach)
1979
/* We don't need to test the 'no filter' case if this is the only filter
1980
* that has been chosen, as it doesn't actually do anything to the data.
1982
if ((filter_to_do & PNG_FILTER_NONE) &&
1983
filter_to_do != PNG_FILTER_NONE)
1986
png_uint_32 sum = 0;
1990
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
1993
sum += (v < 128) ? v : 256 - v;
1996
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1997
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1999
png_uint_32 sumhi, sumlo;
2001
sumlo = sum & PNG_LOMASK;
2002
sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
2004
/* Reduce the sum if we match any of the previous rows */
2005
for (j = 0; j < num_p_filters; j++)
2007
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2009
sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2011
sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2016
/* Factor in the cost of this filter (this is here for completeness,
2017
* but it makes no sense to have a "cost" for the NONE filter, as
2018
* it has the minimum possible computational cost - none).
2020
sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2022
sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2025
if (sumhi > PNG_HIMASK)
2028
sum = (sumhi << PNG_HISHIFT) + sumlo;
2035
if (filter_to_do == PNG_FILTER_SUB)
2036
/* it's the only filter so no testing is needed */
2038
png_bytep rp, lp, dp;
2040
for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2045
for (lp = row_buf + 1; i < row_bytes;
2046
i++, rp++, lp++, dp++)
2048
*dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2050
best_row = png_ptr->sub_row;
2053
else if (filter_to_do & PNG_FILTER_SUB)
2055
png_bytep rp, dp, lp;
2056
png_uint_32 sum = 0, lmins = mins;
2060
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2061
/* We temporarily increase the "minimum sum" by the factor we
2062
* would reduce the sum of this filter, so that we can do the
2063
* early exit comparison without scaling the sum each time.
2065
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2068
png_uint_32 lmhi, lmlo;
2069
lmlo = lmins & PNG_LOMASK;
2070
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2072
for (j = 0; j < num_p_filters; j++)
2074
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2076
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2078
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2083
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2085
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2088
if (lmhi > PNG_HIMASK)
2091
lmins = (lmhi << PNG_HISHIFT) + lmlo;
2095
for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2100
sum += (v < 128) ? v : 256 - v;
2102
for (lp = row_buf + 1; i < row_info->rowbytes;
2103
i++, rp++, lp++, dp++)
2105
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2107
sum += (v < 128) ? v : 256 - v;
2109
if (sum > lmins) /* We are already worse, don't continue. */
2113
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2114
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2117
png_uint_32 sumhi, sumlo;
2118
sumlo = sum & PNG_LOMASK;
2119
sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2121
for (j = 0; j < num_p_filters; j++)
2123
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2125
sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
2127
sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
2132
sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2134
sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2137
if (sumhi > PNG_HIMASK)
2140
sum = (sumhi << PNG_HISHIFT) + sumlo;
2147
best_row = png_ptr->sub_row;
2152
if (filter_to_do == PNG_FILTER_UP)
2154
png_bytep rp, dp, pp;
2157
for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2158
pp = prev_row + 1; i < row_bytes;
2159
i++, rp++, pp++, dp++)
2161
*dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2163
best_row = png_ptr->up_row;
2166
else if (filter_to_do & PNG_FILTER_UP)
2168
png_bytep rp, dp, pp;
2169
png_uint_32 sum = 0, lmins = mins;
2174
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2175
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2178
png_uint_32 lmhi, lmlo;
2179
lmlo = lmins & PNG_LOMASK;
2180
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2182
for (j = 0; j < num_p_filters; j++)
2184
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2186
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2188
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2193
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2195
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2198
if (lmhi > PNG_HIMASK)
2201
lmins = (lmhi << PNG_HISHIFT) + lmlo;
2205
for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2206
pp = prev_row + 1; i < row_bytes; i++)
2208
v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2210
sum += (v < 128) ? v : 256 - v;
2212
if (sum > lmins) /* We are already worse, don't continue. */
2216
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2217
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2220
png_uint_32 sumhi, sumlo;
2221
sumlo = sum & PNG_LOMASK;
2222
sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2224
for (j = 0; j < num_p_filters; j++)
2226
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2228
sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2230
sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2235
sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2237
sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2240
if (sumhi > PNG_HIMASK)
2243
sum = (sumhi << PNG_HISHIFT) + sumlo;
2250
best_row = png_ptr->up_row;
2255
if (filter_to_do == PNG_FILTER_AVG)
2257
png_bytep rp, dp, pp, lp;
2259
for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2260
pp = prev_row + 1; i < bpp; i++)
2262
*dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2264
for (lp = row_buf + 1; i < row_bytes; i++)
2266
*dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
2269
best_row = png_ptr->avg_row;
2272
else if (filter_to_do & PNG_FILTER_AVG)
2274
png_bytep rp, dp, pp, lp;
2275
png_uint_32 sum = 0, lmins = mins;
2279
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2280
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2283
png_uint_32 lmhi, lmlo;
2284
lmlo = lmins & PNG_LOMASK;
2285
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2287
for (j = 0; j < num_p_filters; j++)
2289
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
2291
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2293
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2298
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2300
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2303
if (lmhi > PNG_HIMASK)
2306
lmins = (lmhi << PNG_HISHIFT) + lmlo;
2310
for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2311
pp = prev_row + 1; i < bpp; i++)
2313
v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2315
sum += (v < 128) ? v : 256 - v;
2317
for (lp = row_buf + 1; i < row_bytes; i++)
2320
(png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
2322
sum += (v < 128) ? v : 256 - v;
2324
if (sum > lmins) /* We are already worse, don't continue. */
2328
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2329
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2332
png_uint_32 sumhi, sumlo;
2333
sumlo = sum & PNG_LOMASK;
2334
sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2336
for (j = 0; j < num_p_filters; j++)
2338
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2340
sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2342
sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2347
sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2349
sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2352
if (sumhi > PNG_HIMASK)
2355
sum = (sumhi << PNG_HISHIFT) + sumlo;
2362
best_row = png_ptr->avg_row;
2367
if (filter_to_do == PNG_FILTER_PAETH)
2369
png_bytep rp, dp, pp, cp, lp;
2371
for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2372
pp = prev_row + 1; i < bpp; i++)
2374
*dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2377
for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2379
int a, b, c, pa, pb, pc, p;
2393
pa = p < 0 ? -p : p;
2394
pb = pc < 0 ? -pc : pc;
2395
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2398
p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2400
*dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2402
best_row = png_ptr->paeth_row;
2405
else if (filter_to_do & PNG_FILTER_PAETH)
2407
png_bytep rp, dp, pp, cp, lp;
2408
png_uint_32 sum = 0, lmins = mins;
2412
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2413
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2416
png_uint_32 lmhi, lmlo;
2417
lmlo = lmins & PNG_LOMASK;
2418
lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2420
for (j = 0; j < num_p_filters; j++)
2422
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
2424
lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2426
lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2431
lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2433
lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2436
if (lmhi > PNG_HIMASK)
2439
lmins = (lmhi << PNG_HISHIFT) + lmlo;
2443
for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2444
pp = prev_row + 1; i < bpp; i++)
2446
v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2448
sum += (v < 128) ? v : 256 - v;
2451
for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2453
int a, b, c, pa, pb, pc, p;
2459
#ifndef PNG_SLOW_PAETH
2467
pa = p < 0 ? -p : p;
2468
pb = pc < 0 ? -pc : pc;
2469
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2471
p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2472
#else /* PNG_SLOW_PAETH */
2477
if (pa <= pb && pa <= pc)
2483
#endif /* PNG_SLOW_PAETH */
2485
v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2487
sum += (v < 128) ? v : 256 - v;
2489
if (sum > lmins) /* We are already worse, don't continue. */
2493
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2494
if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2497
png_uint_32 sumhi, sumlo;
2498
sumlo = sum & PNG_LOMASK;
2499
sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2501
for (j = 0; j < num_p_filters; j++)
2503
if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
2505
sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2507
sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2512
sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2514
sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2517
if (sumhi > PNG_HIMASK)
2520
sum = (sumhi << PNG_HISHIFT) + sumlo;
2526
best_row = png_ptr->paeth_row;
2530
/* Do the actual writing of the filtered row data from the chosen filter. */
2532
png_write_filtered_row(png_ptr, best_row);
2534
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2535
/* Save the type of filter we picked this time for future calculations */
2536
if (png_ptr->num_prev_filters > 0)
2539
for (j = 1; j < num_p_filters; j++)
2541
png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
2543
png_ptr->prev_filters[j] = best_row[0];
2549
/* Do the actual writing of a previously filtered row. */
2551
png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
2553
png_debug(1, "in png_write_filtered_row\n");
2554
png_debug1(2, "filter = %d\n", filtered_row[0]);
2555
/* set up the zlib input buffer */
2556
png_ptr->zstream.next_in = filtered_row;
2557
png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
2558
/* repeat until we have compressed all the data */
2561
int ret; /* return of zlib */
2563
/* compress the data */
2564
ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
2565
/* check for compression errors */
2568
if (png_ptr->zstream.msg != NULL)
2569
png_error(png_ptr, png_ptr->zstream.msg);
2571
png_error(png_ptr, "zlib error");
2574
/* see if it is time to write another IDAT */
2575
if (!(png_ptr->zstream.avail_out))
2577
/* write the IDAT and reset the zlib output buffer */
2578
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
2579
png_ptr->zstream.next_out = png_ptr->zbuf;
2580
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2582
/* repeat until all data has been compressed */
2583
} while (png_ptr->zstream.avail_in);
2585
/* swap the current and previous rows */
2586
if (png_ptr->prev_row != NULL)
2590
tptr = png_ptr->prev_row;
2591
png_ptr->prev_row = png_ptr->row_buf;
2592
png_ptr->row_buf = tptr;
2595
/* finish row - updates counters and flushes zlib if last row */
2596
png_write_finish_row(png_ptr);
2598
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
2599
png_ptr->flush_rows++;
2601
if (png_ptr->flush_dist > 0 &&
2602
png_ptr->flush_rows >= png_ptr->flush_dist)
2604
png_write_flush(png_ptr);