blob: 198f3e4a90b6782b7218295d7fcf0eda30c207f9 [file] [log] [blame]
John Bowler8de49d02012-09-27 09:26:49 -05001
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002/* png.c - location for general purpose libpng functions
3 *
Glenn Randers-Pehrson399430d2013-04-25 09:52:00 -05004 * Last changed in libpng 1.6.2 [April 25, 2013]
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06005 * Copyright (c) 1998-2013 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -05008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060012 */
Guy Schalnat0d580581995-07-20 02:43:20 -050013
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050014#include "pngpriv.h"
Guy Schalnat0d580581995-07-20 02:43:20 -050015
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -060016/* Generate a compiler error if there is an old png.h in the search path. */
Glenn Randers-Pehrsonf2b89612013-11-14 12:56:50 -060017typedef png_libpng_version_1_6_8beta01 Your_png_h_is_not_version_1_6_8beta01;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -060018
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060019/* Tells libpng that we have already handled the first "num_bytes" bytes
20 * of the PNG file signature. If the PNG data is embedded into another
21 * stream we can set num_bytes = 8 so that libpng will not attempt to read
22 * or write any of the magic bytes before it starts on the IHDR.
23 */
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -050024
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060025#ifdef PNG_READ_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050026void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060027png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060028{
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -050029 png_debug(1, "in png_set_sig_bytes");
30
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050031 if (png_ptr == NULL)
32 return;
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050033
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060034 if (num_bytes > 8)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050035 png_error(png_ptr, "Too many bytes for PNG signature");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060036
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -050037 png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060038}
39
40/* Checks whether the supplied bytes match the PNG signature. We allow
41 * checking less than the full 8-byte signature so that those apps that
42 * already read the first few bytes of a file to determine the file type
43 * can simply check the remaining bytes for extra assurance. Returns
44 * an integer less than, equal to, or greater than zero if sig is found,
45 * respectively, to be less than, to match, or be greater than the correct
Glenn Randers-Pehrson6d62ef12011-08-25 18:17:50 -050046 * PNG signature (this is the same behavior as strcmp, memcmp, etc).
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060047 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050048int PNGAPI
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -050049png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060050{
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -060051 png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050052
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060053 if (num_to_check > 8)
54 num_to_check = 8;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050055
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060056 else if (num_to_check < 1)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060057 return (-1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060058
Andreas Dilger47a0c421997-05-16 02:46:07 -050059 if (start > 7)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060060 return (-1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060061
62 if (start + num_to_check > 8)
63 num_to_check = 8 - start;
64
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -060065 return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060066}
67
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060068#endif /* PNG_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050069
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060070#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrsonc5080812010-10-23 08:26:26 -050071/* Function to allocate memory for zlib */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -050072PNG_FUNCTION(voidpf /* PRIVATE */,
73png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
Guy Schalnat0d580581995-07-20 02:43:20 -050074{
John Bowlerd332c672011-12-21 17:36:12 -060075 png_alloc_size_t num_bytes = size;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050076
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050077 if (png_ptr == NULL)
John Bowlerd332c672011-12-21 17:36:12 -060078 return NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050079
John Bowlerd332c672011-12-21 17:36:12 -060080 if (items >= (~(png_alloc_size_t)0)/size)
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050081 {
John Bowler5d567862011-12-24 09:12:00 -060082 png_warning (png_voidcast(png_structrp, png_ptr),
John Bowlerd332c672011-12-21 17:36:12 -060083 "Potential overflow in png_zalloc()");
84 return NULL;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050085 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -060086
John Bowlerd332c672011-12-21 17:36:12 -060087 num_bytes *= items;
John Bowler5d567862011-12-24 09:12:00 -060088 return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050089}
90
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050091/* Function to free memory for zlib */
Glenn Randers-Pehrson3f705ba2009-07-23 12:53:06 -050092void /* PRIVATE */
Guy Schalnat51f0eb41995-09-26 05:22:39 -050093png_zfree(voidpf png_ptr, voidpf ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050094{
John Bowler5d567862011-12-24 09:12:00 -060095 png_free(png_voidcast(png_const_structrp,png_ptr), ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -050096}
97
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060098/* Reset the CRC variable to 32 bits of 1's. Care must be taken
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060099 * in case CRC is > 32 bits to leave the top bits 0.
100 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500101void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600102png_reset_crc(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500103{
John Bowlerf3f7e142011-09-09 07:32:37 -0500104 /* The cast is safe because the crc is a 32 bit value. */
105 png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500106}
107
Andreas Dilger47a0c421997-05-16 02:46:07 -0500108/* Calculate the CRC over a section of data. We can only pass as
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600109 * much data to this routine as the largest single buffer size. We
110 * also check that this data will actually be used before going to the
111 * trouble of calculating it.
112 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500113void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600114png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500115{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500116 int need_crc = 1;
117
Glenn Randers-Pehrson67a289f2013-04-19 19:03:34 -0500118 if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))
Andreas Dilger47a0c421997-05-16 02:46:07 -0500119 {
120 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
121 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
122 need_crc = 0;
123 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500124
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500125 else /* critical */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500126 {
127 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
128 need_crc = 0;
129 }
130
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600131 /* 'uLong' is defined in zlib.h as unsigned long; this means that on some
132 * systems it is a 64 bit value. crc32, however, returns 32 bits so the
133 * following cast is safe. 'uInt' may be no more than 16 bits, so it is
134 * necessary to perform a loop here.
John Bowlerf3f7e142011-09-09 07:32:37 -0500135 */
136 if (need_crc && length > 0)
137 {
138 uLong crc = png_ptr->crc; /* Should never issue a warning */
139
140 do
141 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600142 uInt safe_length = (uInt)length;
143 if (safe_length == 0)
144 safe_length = (uInt)-1; /* evil, but safe */
John Bowlerf3f7e142011-09-09 07:32:37 -0500145
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600146 crc = crc32(crc, ptr, safe_length);
John Bowlerf3f7e142011-09-09 07:32:37 -0500147
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600148 /* The following should never issue compiler warnings; if they do the
John Bowlerf3f7e142011-09-09 07:32:37 -0500149 * target system has characteristics that will probably violate other
150 * assumptions within the libpng code.
151 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600152 ptr += safe_length;
153 length -= safe_length;
John Bowlerf3f7e142011-09-09 07:32:37 -0500154 }
155 while (length > 0);
156
157 /* And the following is always safe because the crc is only 32 bits. */
158 png_ptr->crc = (png_uint_32)crc;
159 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500160}
Guy Schalnate5a37791996-06-05 15:50:50 -0500161
John Bowler88b77cc2011-05-05 06:49:55 -0500162/* Check a user supplied version number, called from both read and write
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600163 * functions that create a png_struct.
John Bowler88b77cc2011-05-05 06:49:55 -0500164 */
165int
John Bowler5d567862011-12-24 09:12:00 -0600166png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
John Bowler88b77cc2011-05-05 06:49:55 -0500167{
168 if (user_png_ver)
169 {
170 int i = 0;
171
172 do
173 {
174 if (user_png_ver[i] != png_libpng_ver[i])
175 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
176 } while (png_libpng_ver[i++]);
177 }
178
179 else
180 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
181
182 if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
183 {
184 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
185 * we must recompile any applications that use any older library version.
186 * For versions after libpng 1.0, we will be compatible, so we need
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600187 * only check the first and third digits (note that when we reach version
188 * 1.10 we will need to check the fourth symbol, namely user_png_ver[3]).
John Bowler88b77cc2011-05-05 06:49:55 -0500189 */
190 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600191 (user_png_ver[0] == '1' && (user_png_ver[2] != png_libpng_ver[2] ||
192 user_png_ver[3] != png_libpng_ver[3])) ||
John Bowler88b77cc2011-05-05 06:49:55 -0500193 (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
194 {
195#ifdef PNG_WARNINGS_SUPPORTED
196 size_t pos = 0;
197 char m[128];
198
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600199 pos = png_safecat(m, (sizeof m), pos,
200 "Application built with libpng-");
201 pos = png_safecat(m, (sizeof m), pos, user_png_ver);
202 pos = png_safecat(m, (sizeof m), pos, " but running with ");
203 pos = png_safecat(m, (sizeof m), pos, png_libpng_ver);
John Bowler88b77cc2011-05-05 06:49:55 -0500204
205 png_warning(png_ptr, m);
206#endif
207
208#ifdef PNG_ERROR_NUMBERS_SUPPORTED
209 png_ptr->flags = 0;
210#endif
211
212 return 0;
213 }
214 }
215
216 /* Success return. */
217 return 1;
218}
219
John Bowlerd332c672011-12-21 17:36:12 -0600220/* Generic function to create a png_struct for either read or write - this
221 * contains the common initialization.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600222 */
John Bowlerd332c672011-12-21 17:36:12 -0600223PNG_FUNCTION(png_structp /* PRIVATE */,
224png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
225 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
226 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
227{
228 png_struct create_struct;
229# ifdef PNG_SETJMP_SUPPORTED
230 jmp_buf create_jmp_buf;
231# endif
232
233 /* This temporary stack-allocated structure is used to provide a place to
234 * build enough context to allow the user provided memory allocator (if any)
235 * to be called.
236 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600237 memset(&create_struct, 0, (sizeof create_struct));
John Bowlerd332c672011-12-21 17:36:12 -0600238
239 /* Added at libpng-1.2.6 */
240# ifdef PNG_USER_LIMITS_SUPPORTED
241 create_struct.user_width_max = PNG_USER_WIDTH_MAX;
242 create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
243
244# ifdef PNG_USER_CHUNK_CACHE_MAX
245 /* Added at libpng-1.2.43 and 1.4.0 */
246 create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
247# endif
248
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600249# ifdef PNG_USER_CHUNK_MALLOC_MAX
John Bowlerd332c672011-12-21 17:36:12 -0600250 /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
251 * in png_struct regardless.
252 */
253 create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
254# endif
255# endif
256
257 /* The following two API calls simply set fields in png_struct, so it is safe
258 * to do them now even though error handling is not yet set up.
259 */
260# ifdef PNG_USER_MEM_SUPPORTED
261 png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
262# endif
263
264 /* (*error_fn) can return control to the caller after the error_ptr is set,
265 * this will result in a memory leak unless the error_fn does something
266 * extremely sophisticated. The design lacks merit but is implicit in the
267 * API.
268 */
269 png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
270
271# ifdef PNG_SETJMP_SUPPORTED
272 if (!setjmp(create_jmp_buf))
273 {
274 /* Temporarily fake out the longjmp information until we have
275 * successfully completed this function. This only works if we have
276 * setjmp() support compiled in, but it is safe - this stuff should
277 * never happen.
278 */
279 create_struct.jmp_buf_ptr = &create_jmp_buf;
280 create_struct.jmp_buf_size = 0; /*stack allocation*/
281 create_struct.longjmp_fn = longjmp;
282# else
283 {
284# endif
285 /* Call the general version checker (shared with read and write code):
286 */
287 if (png_user_version_check(&create_struct, user_png_ver))
288 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600289 png_structrp png_ptr = png_voidcast(png_structrp,
290 png_malloc_warn(&create_struct, (sizeof *png_ptr)));
John Bowlerd332c672011-12-21 17:36:12 -0600291
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600292 if (png_ptr != NULL)
John Bowlerd332c672011-12-21 17:36:12 -0600293 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600294 /* png_ptr->zstream holds a back-pointer to the png_struct, so
295 * this can only be done now:
296 */
297 create_struct.zstream.zalloc = png_zalloc;
298 create_struct.zstream.zfree = png_zfree;
299 create_struct.zstream.opaque = png_ptr;
John Bowlerd332c672011-12-21 17:36:12 -0600300
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600301# ifdef PNG_SETJMP_SUPPORTED
302 /* Eliminate the local error handling: */
303 create_struct.jmp_buf_ptr = NULL;
304 create_struct.jmp_buf_size = 0;
305 create_struct.longjmp_fn = 0;
306# endif
John Bowlerd332c672011-12-21 17:36:12 -0600307
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600308 *png_ptr = create_struct;
John Bowlerd332c672011-12-21 17:36:12 -0600309
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600310 /* This is the successful return point */
311 return png_ptr;
John Bowlerd332c672011-12-21 17:36:12 -0600312 }
313 }
314 }
315
316 /* A longjmp because of a bug in the application storage allocator or a
317 * simple failure to allocate the png_struct.
318 */
John Bowlerd332c672011-12-21 17:36:12 -0600319 return NULL;
320}
321
322/* Allocate the memory for an info_struct for the application. */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -0500323PNG_FUNCTION(png_infop,PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600324png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500325{
John Bowler5d567862011-12-24 09:12:00 -0600326 png_inforp info_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500327
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500328 png_debug(1, "in png_create_info_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500329
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500330 if (png_ptr == NULL)
John Bowlerd332c672011-12-21 17:36:12 -0600331 return NULL;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500332
John Bowlerd332c672011-12-21 17:36:12 -0600333 /* Use the internal API that does not (or at least should not) error out, so
334 * that this call always returns ok. The application typically sets up the
335 * error handling *after* creating the info_struct because this is the way it
336 * has always been done in 'example.c'.
337 */
John Bowler5d567862011-12-24 09:12:00 -0600338 info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600339 (sizeof *info_ptr)));
John Bowlerd332c672011-12-21 17:36:12 -0600340
Glenn Randers-Pehrson5cded0b2001-11-07 07:10:08 -0600341 if (info_ptr != NULL)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600342 memset(info_ptr, 0, (sizeof *info_ptr));
Guy Schalnate5a37791996-06-05 15:50:50 -0500343
John Bowlerd332c672011-12-21 17:36:12 -0600344 return info_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500345}
346
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600347/* This function frees the memory associated with a single info struct.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600348 * Normally, one would use either png_destroy_read_struct() or
349 * png_destroy_write_struct() to free an info struct, but this may be
John Bowlerd332c672011-12-21 17:36:12 -0600350 * useful for some applications. From libpng 1.6.0 this function is also used
351 * internally to implement the png_info release part of the 'struct' destroy
352 * APIs. This ensures that all possible approaches free the same data (all of
353 * it).
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600354 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500355void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600356png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600357{
John Bowler5d567862011-12-24 09:12:00 -0600358 png_inforp info_ptr = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600359
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500360 png_debug(1, "in png_destroy_info_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500361
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500362 if (png_ptr == NULL)
363 return;
364
Andreas Dilger47a0c421997-05-16 02:46:07 -0500365 if (info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600366 info_ptr = *info_ptr_ptr;
367
Andreas Dilger47a0c421997-05-16 02:46:07 -0500368 if (info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600369 {
John Bowlerd332c672011-12-21 17:36:12 -0600370 /* Do this first in case of an error below; if the app implements its own
371 * memory management this can lead to png_free calling png_error, which
372 * will abort this routine and return control to the app error handler.
373 * An infinite loop may result if it then tries to free the same info
374 * ptr.
375 */
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -0500376 *info_ptr_ptr = NULL;
John Bowlerd332c672011-12-21 17:36:12 -0600377
John Bowlerdf477e42011-12-24 07:47:02 -0600378 png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600379 memset(info_ptr, 0, (sizeof *info_ptr));
John Bowlerd332c672011-12-21 17:36:12 -0600380 png_free(png_ptr, info_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600381 }
382}
383
384/* Initialize the info structure. This is now an internal function (0.89)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600385 * and applications using it are urged to use png_create_info_struct()
John Bowlerd332c672011-12-21 17:36:12 -0600386 * instead. Use deprecated in 1.6.0, internal use removed (used internally it
387 * is just a memset).
388 *
389 * NOTE: it is almost inconceivable that this API is used because it bypasses
390 * the user-memory mechanism and the user error handling/warning mechanisms in
391 * those cases where it does anything other than a memset.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600392 */
John Bowlerd332c672011-12-21 17:36:12 -0600393PNG_FUNCTION(void,PNGAPI
394png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
395 PNG_DEPRECATED)
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500396{
John Bowler5d567862011-12-24 09:12:00 -0600397 png_inforp info_ptr = *ptr_ptr;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500398
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500399 png_debug(1, "in png_info_init_3");
400
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500401 if (info_ptr == NULL)
402 return;
Glenn Randers-Pehrson6b12c082006-11-14 10:53:30 -0600403
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600404 if ((sizeof (png_info)) > png_info_struct_size)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500405 {
John Bowlerd332c672011-12-21 17:36:12 -0600406 *ptr_ptr = NULL;
407 /* The following line is why this API should not be used: */
408 free(info_ptr);
John Bowler5d567862011-12-24 09:12:00 -0600409 info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600410 (sizeof *info_ptr)));
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500411 *ptr_ptr = info_ptr;
412 }
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500413
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500414 /* Set everything to 0 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600415 memset(info_ptr, 0, (sizeof *info_ptr));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600416}
417
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600418/* The following API is not called internally */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500419void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600420png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500421 int freer, png_uint_32 mask)
422{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500423 png_debug(1, "in png_data_freer");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500424
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500425 if (png_ptr == NULL || info_ptr == NULL)
426 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500427
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500428 if (freer == PNG_DESTROY_WILL_FREE_DATA)
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500429 info_ptr->free_me |= mask;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500430
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500431 else if (freer == PNG_USER_WILL_FREE_DATA)
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500432 info_ptr->free_me &= ~mask;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500433
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500434 else
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600435 png_error(png_ptr, "Unknown freer parameter in png_data_freer");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500436}
437
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500438void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600439png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500440 int num)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600441{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500442 png_debug(1, "in png_free_data");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500443
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600444 if (png_ptr == NULL || info_ptr == NULL)
445 return;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600446
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500447#ifdef PNG_TEXT_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500448 /* Free text item num or (if num == -1) all text items */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500449 if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600450 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500451 if (num != -1)
452 {
453 if (info_ptr->text && info_ptr->text[num].key)
454 {
455 png_free(png_ptr, info_ptr->text[num].key);
456 info_ptr->text[num].key = NULL;
457 }
458 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500459
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500460 else
461 {
462 int i;
463 for (i = 0; i < info_ptr->num_text; i++)
464 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
465 png_free(png_ptr, info_ptr->text);
466 info_ptr->text = NULL;
467 info_ptr->num_text=0;
468 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600469 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600470#endif
471
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500472#ifdef PNG_tRNS_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500473 /* Free any tRNS entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500474 if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500475 {
Glenn Randers-Pehrson6abea752009-08-08 16:52:06 -0500476 png_free(png_ptr, info_ptr->trans_alpha);
477 info_ptr->trans_alpha = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500478 info_ptr->valid &= ~PNG_INFO_tRNS;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500479 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600480#endif
481
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500482#ifdef PNG_sCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500483 /* Free any sCAL entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500484 if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500485 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500486 png_free(png_ptr, info_ptr->scal_s_width);
487 png_free(png_ptr, info_ptr->scal_s_height);
488 info_ptr->scal_s_width = NULL;
489 info_ptr->scal_s_height = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500490 info_ptr->valid &= ~PNG_INFO_sCAL;
491 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600492#endif
493
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500494#ifdef PNG_pCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500495 /* Free any pCAL entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500496 if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500497 {
498 png_free(png_ptr, info_ptr->pcal_purpose);
499 png_free(png_ptr, info_ptr->pcal_units);
500 info_ptr->pcal_purpose = NULL;
501 info_ptr->pcal_units = NULL;
502 if (info_ptr->pcal_params != NULL)
503 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600504 unsigned int i;
505 for (i = 0; i < info_ptr->pcal_nparams; i++)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500506 {
507 png_free(png_ptr, info_ptr->pcal_params[i]);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600508 info_ptr->pcal_params[i] = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500509 }
510 png_free(png_ptr, info_ptr->pcal_params);
511 info_ptr->pcal_params = NULL;
512 }
513 info_ptr->valid &= ~PNG_INFO_pCAL;
514 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600515#endif
516
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500517#ifdef PNG_iCCP_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600518 /* Free any profile entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500519 if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500520 {
521 png_free(png_ptr, info_ptr->iccp_name);
522 png_free(png_ptr, info_ptr->iccp_profile);
523 info_ptr->iccp_name = NULL;
524 info_ptr->iccp_profile = NULL;
525 info_ptr->valid &= ~PNG_INFO_iCCP;
526 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600527#endif
528
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500529#ifdef PNG_sPLT_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500530 /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500531 if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600532 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500533 if (num != -1)
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500534 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500535 if (info_ptr->splt_palettes)
536 {
537 png_free(png_ptr, info_ptr->splt_palettes[num].name);
538 png_free(png_ptr, info_ptr->splt_palettes[num].entries);
539 info_ptr->splt_palettes[num].name = NULL;
540 info_ptr->splt_palettes[num].entries = NULL;
541 }
542 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500543
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500544 else
545 {
546 if (info_ptr->splt_palettes_num)
547 {
Glenn Randers-Pehrson45679352013-01-20 00:44:29 -0600548 int i;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600549 for (i = 0; i < info_ptr->splt_palettes_num; i++)
550 png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, (int)i);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500551
552 png_free(png_ptr, info_ptr->splt_palettes);
553 info_ptr->splt_palettes = NULL;
554 info_ptr->splt_palettes_num = 0;
555 }
556 info_ptr->valid &= ~PNG_INFO_sPLT;
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500557 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600558 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600559#endif
560
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600561#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500562 if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600563 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500564 if (num != -1)
565 {
566 if (info_ptr->unknown_chunks)
567 {
568 png_free(png_ptr, info_ptr->unknown_chunks[num].data);
569 info_ptr->unknown_chunks[num].data = NULL;
570 }
571 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500572
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500573 else
574 {
Glenn Randers-Pehrson45679352013-01-20 00:44:29 -0600575 int i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600576
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500577 if (info_ptr->unknown_chunks_num)
578 {
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -0500579 for (i = 0; i < info_ptr->unknown_chunks_num; i++)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600580 png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, (int)i);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600581
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500582 png_free(png_ptr, info_ptr->unknown_chunks);
583 info_ptr->unknown_chunks = NULL;
584 info_ptr->unknown_chunks_num = 0;
585 }
586 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600587 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600588#endif
589
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500590#ifdef PNG_hIST_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500591 /* Free any hIST entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500592 if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500593 {
594 png_free(png_ptr, info_ptr->hist);
595 info_ptr->hist = NULL;
596 info_ptr->valid &= ~PNG_INFO_hIST;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500597 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600598#endif
599
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500600 /* Free any PLTE entry that was internally allocated */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500601 if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500602 {
John Bowler40b26032011-12-22 08:09:15 -0600603 png_free(png_ptr, info_ptr->palette);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500604 info_ptr->palette = NULL;
605 info_ptr->valid &= ~PNG_INFO_PLTE;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500606 info_ptr->num_palette = 0;
607 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600608
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500609#ifdef PNG_INFO_IMAGE_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500610 /* Free any image bits attached to the info structure */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500611 if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500612 {
613 if (info_ptr->row_pointers)
614 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600615 png_uint_32 row;
616 for (row = 0; row < info_ptr->height; row++)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500617 {
618 png_free(png_ptr, info_ptr->row_pointers[row]);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600619 info_ptr->row_pointers[row] = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500620 }
621 png_free(png_ptr, info_ptr->row_pointers);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600622 info_ptr->row_pointers = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500623 }
624 info_ptr->valid &= ~PNG_INFO_IDAT;
625 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600626#endif
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500627
John Bowler56a739b2010-12-19 16:33:20 -0600628 if (num != -1)
629 mask &= ~PNG_FREE_MUL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500630
John Bowler56a739b2010-12-19 16:33:20 -0600631 info_ptr->free_me &= ~mask;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600632}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600633#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500634
Guy Schalnate5a37791996-06-05 15:50:50 -0500635/* This function returns a pointer to the io_ptr associated with the user
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600636 * functions. The application should free any memory associated with this
637 * pointer before png_write_destroy() or png_read_destroy() are called.
638 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500639png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600640png_get_io_ptr(png_const_structrp png_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500641{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500642 if (png_ptr == NULL)
643 return (NULL);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500644
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600645 return (png_ptr->io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500646}
Andreas Dilger47a0c421997-05-16 02:46:07 -0500647
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600648#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600649# ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500650/* Initialize the default input/output functions for the PNG file. If you
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600651 * use your own read or write routines, you can call either png_set_read_fn()
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500652 * or png_set_write_fn() instead of png_init_io(). If you have defined
Glenn Randers-Pehrsonce775cc2011-07-13 06:28:26 -0500653 * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
654 * function of your own because "FILE *" isn't necessarily available.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600655 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500656void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600657png_init_io(png_structrp png_ptr, png_FILE_p fp)
Guy Schalnate5a37791996-06-05 15:50:50 -0500658{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500659 png_debug(1, "in png_init_io");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500660
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500661 if (png_ptr == NULL)
662 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500663
Guy Schalnate5a37791996-06-05 15:50:50 -0500664 png_ptr->io_ptr = (png_voidp)fp;
665}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600666# endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500667
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600668#ifdef PNG_SAVE_INT_32_SUPPORTED
669/* The png_save_int_32 function assumes integers are stored in two's
670 * complement format. If this isn't the case, then this routine needs to
671 * be modified to write data in two's complement format. Note that,
672 * the following works correctly even if png_int_32 has more than 32 bits
673 * (compare the more complex code required on read for sign extension.)
674 */
675void PNGAPI
676png_save_int_32(png_bytep buf, png_int_32 i)
677{
678 buf[0] = (png_byte)((i >> 24) & 0xff);
679 buf[1] = (png_byte)((i >> 16) & 0xff);
680 buf[2] = (png_byte)((i >> 8) & 0xff);
681 buf[3] = (png_byte)(i & 0xff);
682}
683#endif
684
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600685# ifdef PNG_TIME_RFC1123_SUPPORTED
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500686/* Convert the supplied time into an RFC 1123 string suitable for use in
687 * a "Creation Time" or other text-based time string.
688 */
John Bowler40b26032011-12-22 08:09:15 -0600689int PNGAPI
690png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500691{
692 static PNG_CONST char short_months[12][4] =
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600693 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
694 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500695
John Bowler40b26032011-12-22 08:09:15 -0600696 if (out == NULL)
697 return 0;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500698
Glenn Randers-Pehrson925a6022011-11-19 18:04:01 -0600699 if (ptime->year > 9999 /* RFC1123 limitation */ ||
700 ptime->month == 0 || ptime->month > 12 ||
701 ptime->day == 0 || ptime->day > 31 ||
702 ptime->hour > 23 || ptime->minute > 59 ||
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600703 ptime->second > 60)
John Bowler40b26032011-12-22 08:09:15 -0600704 return 0;
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600705
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500706 {
John Bowler88b77cc2011-05-05 06:49:55 -0500707 size_t pos = 0;
Glenn Randers-Pehrson925a6022011-11-19 18:04:01 -0600708 char number_buf[5]; /* enough for a four-digit year */
John Bowler88b77cc2011-05-05 06:49:55 -0500709
John Bowler40b26032011-12-22 08:09:15 -0600710# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
John Bowler88b77cc2011-05-05 06:49:55 -0500711# define APPEND_NUMBER(format, value)\
712 APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
John Bowler40b26032011-12-22 08:09:15 -0600713# define APPEND(ch) if (pos < 28) out[pos++] = (ch)
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500714
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600715 APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
John Bowler88b77cc2011-05-05 06:49:55 -0500716 APPEND(' ');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600717 APPEND_STRING(short_months[(ptime->month - 1)]);
John Bowler88b77cc2011-05-05 06:49:55 -0500718 APPEND(' ');
719 APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
720 APPEND(' ');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600721 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
John Bowler88b77cc2011-05-05 06:49:55 -0500722 APPEND(':');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600723 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
John Bowler88b77cc2011-05-05 06:49:55 -0500724 APPEND(':');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600725 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
John Bowler88b77cc2011-05-05 06:49:55 -0500726 APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
727
728# undef APPEND
729# undef APPEND_NUMBER
730# undef APPEND_STRING
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500731 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500732
John Bowler40b26032011-12-22 08:09:15 -0600733 return 1;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500734}
John Bowler40b26032011-12-22 08:09:15 -0600735
736# if PNG_LIBPNG_VER < 10700
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600737/* To do: remove the following from libpng-1.7 */
John Bowler40b26032011-12-22 08:09:15 -0600738/* Original API that uses a private buffer in png_struct.
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600739 * Deprecated because it causes png_struct to carry a spurious temporary
John Bowler40b26032011-12-22 08:09:15 -0600740 * buffer (png_struct::time_buffer), better to have the caller pass this in.
741 */
742png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600743png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
John Bowler40b26032011-12-22 08:09:15 -0600744{
745 if (png_ptr != NULL)
746 {
747 /* The only failure above if png_ptr != NULL is from an invalid ptime */
748 if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime))
749 png_warning(png_ptr, "Ignoring invalid time value");
750
751 else
752 return png_ptr->time_buffer;
753 }
754
755 return NULL;
756}
757# endif
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600758# endif /* PNG_TIME_RFC1123_SUPPORTED */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600759
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600760#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600761
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500762png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600763png_get_copyright(png_const_structrp png_ptr)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600764{
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600765 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500766#ifdef PNG_STRING_COPYRIGHT
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600767 return PNG_STRING_COPYRIGHT
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500768#else
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600769# ifdef __STDC__
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500770 return PNG_STRING_NEWLINE \
Glenn Randers-Pehrsonf2b89612013-11-14 12:56:50 -0600771 "libpng version 1.6.8beta01 - November 14, 2013" PNG_STRING_NEWLINE \
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600772 "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
Glenn Randers-Pehrson43aaf6e2008-08-05 22:17:03 -0500773 "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
774 "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500775 PNG_STRING_NEWLINE;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600776# else
Glenn Randers-Pehrsonf2b89612013-11-14 12:56:50 -0600777 return "libpng version 1.6.8beta01 - November 14, 2013\
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600778 Copyright (c) 1998-2013 Glenn Randers-Pehrson\
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500779 Copyright (c) 1996-1997 Andreas Dilger\
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500780 Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600781# endif
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500782#endif
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600783}
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -0500784
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600785/* The following return the library version as a short string in the
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500786 * format 1.0.0 through 99.99.99zz. To get the version of *.h files
787 * used with your application, print out PNG_LIBPNG_VER_STRING, which
788 * is defined in png.h.
789 * Note: now there is no difference between png_get_libpng_ver() and
790 * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
791 * it is guaranteed that png.c uses the correct version of png.h.
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600792 */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500793png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600794png_get_libpng_ver(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600795{
796 /* Version of *.c files used when building libpng */
Glenn Randers-Pehrson4c8f7262010-03-16 19:30:01 -0500797 return png_get_header_ver(png_ptr);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600798}
799
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500800png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600801png_get_header_ver(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600802{
803 /* Version of *.h files used when building libpng */
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600804 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500805 return PNG_LIBPNG_VER_STRING;
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600806}
807
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500808png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600809png_get_header_version(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600810{
811 /* Returns longer string containing both version and date */
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600812 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500813#ifdef __STDC__
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500814 return PNG_HEADER_VERSION_STRING
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600815# ifndef PNG_READ_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500816 " (NO READ SUPPORT)"
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600817# endif
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500818 PNG_STRING_NEWLINE;
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500819#else
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500820 return PNG_HEADER_VERSION_STRING;
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500821#endif
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600822}
823
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600824#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrsonc1bfe682002-03-06 22:08:00 -0600825int PNGAPI
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600826png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600827{
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500828 /* Check chunk_name and return "keep" value if it's on the list, else 0 */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500829 png_const_bytep p, p_end;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500830
John Bowlerfcd301d2011-12-28 21:34:27 -0600831 if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500832 return PNG_HANDLE_CHUNK_AS_DEFAULT;
833
834 p_end = png_ptr->chunk_list;
835 p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
836
837 /* The code is the fifth byte after each four byte string. Historically this
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600838 * code was always searched from the end of the list, this is no longer
839 * necessary because the 'set' routine handles duplicate entries correcty.
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500840 */
841 do /* num_chunk_list > 0, so at least one */
842 {
843 p -= 5;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600844
845 if (!memcmp(chunk_name, p, 4))
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500846 return p[4];
847 }
848 while (p > p_end);
849
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600850 /* This means that known chunks should be processed and unknown chunks should
851 * be handled according to the value of png_ptr->unknown_default; this can be
852 * confusing because, as a result, there are two levels of defaulting for
853 * unknown chunks.
854 */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500855 return PNG_HANDLE_CHUNK_AS_DEFAULT;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600856}
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500857
John Bowler15a80442013-09-21 10:06:32 -0500858#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
859 defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500860int /* PRIVATE */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600861png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500862{
863 png_byte chunk_string[5];
864
865 PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
866 return png_handle_as_unknown(png_ptr, chunk_string);
867}
John Bowler15a80442013-09-21 10:06:32 -0500868#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600869#endif /* SET_UNKNOWN_CHUNKS */
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500870
Glenn Randers-Pehrsonf10fa3c2010-04-29 08:25:29 -0500871#ifdef PNG_READ_SUPPORTED
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500872/* This function, added to libpng-1.0.6g, is untested. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500873int PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600874png_reset_zstream(png_structrp png_ptr)
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500875{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500876 if (png_ptr == NULL)
877 return Z_STREAM_ERROR;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500878
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600879 /* WARNING: this resets the window bits to the maximum! */
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500880 return (inflateReset(&png_ptr->zstream));
881}
Glenn Randers-Pehrson2b8bef12010-04-29 11:50:24 -0500882#endif /* PNG_READ_SUPPORTED */
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500883
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -0600884/* This function was added to libpng-1.0.7 */
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500885png_uint_32 PNGAPI
886png_access_version_number(void)
887{
888 /* Version of *.c files used when building libpng */
Glenn Randers-Pehrsond2332872010-10-12 19:19:28 -0500889 return((png_uint_32)PNG_LIBPNG_VER);
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500890}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600891
Glenn Randers-Pehrson1fd5fb32001-05-06 05:34:26 -0500892
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500893
894#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600895/* Ensure that png_ptr->zstream.msg holds some appropriate error message string.
896 * If it doesn't 'ret' is used to set it to something appropriate, even in cases
897 * like Z_OK or Z_STREAM_END where the error code is apparently a success code.
898 */
899void /* PRIVATE */
900png_zstream_error(png_structrp png_ptr, int ret)
901{
902 /* Translate 'ret' into an appropriate error string, priority is given to the
903 * one in zstream if set. This always returns a string, even in cases like
904 * Z_OK or Z_STREAM_END where the error code is a success code.
905 */
906 if (png_ptr->zstream.msg == NULL) switch (ret)
907 {
908 default:
909 case Z_OK:
910 png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");
911 break;
912
913 case Z_STREAM_END:
914 /* Normal exit */
915 png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");
916 break;
917
918 case Z_NEED_DICT:
919 /* This means the deflate stream did not have a dictionary; this
920 * indicates a bogus PNG.
921 */
922 png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");
923 break;
924
925 case Z_ERRNO:
926 /* gz APIs only: should not happen */
927 png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");
928 break;
929
930 case Z_STREAM_ERROR:
931 /* internal libpng error */
932 png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");
933 break;
934
935 case Z_DATA_ERROR:
936 png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");
937 break;
938
939 case Z_MEM_ERROR:
940 png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");
941 break;
942
943 case Z_BUF_ERROR:
944 /* End of input or output; not a problem if the caller is doing
945 * incremental read or write.
946 */
947 png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");
948 break;
949
950 case Z_VERSION_ERROR:
951 png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");
952 break;
953
954 case PNG_UNEXPECTED_ZLIB_RETURN:
955 /* Compile errors here mean that zlib now uses the value co-opted in
956 * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
957 * and change pngpriv.h. Note that this message is "... return",
958 * whereas the default/Z_OK one is "... return code".
959 */
960 png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");
961 break;
962 }
963}
964
John Bowler736f40f2011-08-25 16:19:44 -0500965/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
966 * at libpng 1.5.5!
967 */
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600968
Glenn Randers-Pehrson02a5e332008-11-24 22:10:23 -0600969/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600970#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
971static int
972png_colorspace_check_gamma(png_const_structrp png_ptr,
973 png_colorspacerp colorspace, png_fixed_point gAMA, int from)
974 /* This is called to check a new gamma value against an existing one. The
975 * routine returns false if the new gamma value should not be written.
976 *
977 * 'from' says where the new gamma value comes from:
978 *
979 * 0: the new gamma value is the libpng estimate for an ICC profile
980 * 1: the new gamma value comes from a gAMA chunk
981 * 2: the new gamma value comes from an sRGB chunk
John Bowlerb98681b2012-09-04 11:19:00 -0500982 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600983{
984 png_fixed_point gtest;
985
986 if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
987 (!png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) ||
988 png_gamma_significant(gtest)))
John Bowlerb11b31a2012-03-21 07:55:46 -0500989 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600990 /* Either this is an sRGB image, in which case the calculated gamma
991 * approximation should match, or this is an image with a profile and the
992 * value libpng calculates for the gamma of the profile does not match the
993 * value recorded in the file. The former, sRGB, case is an error, the
994 * latter is just a warning.
995 */
996 if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
997 {
998 png_chunk_report(png_ptr, "gamma value does not match sRGB",
999 PNG_CHUNK_ERROR);
1000 /* Do not overwrite an sRGB value */
1001 return from == 2;
1002 }
1003
1004 else /* sRGB tag not involved */
1005 {
1006 png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
1007 PNG_CHUNK_WARNING);
1008 return from == 1;
1009 }
John Bowlerb11b31a2012-03-21 07:55:46 -05001010 }
1011
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001012 return 1;
John Bowlerb11b31a2012-03-21 07:55:46 -05001013}
1014
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001015void /* PRIVATE */
1016png_colorspace_set_gamma(png_const_structrp png_ptr,
1017 png_colorspacerp colorspace, png_fixed_point gAMA)
1018{
1019 /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
1020 * occur. Since the fixed point representation is assymetrical it is
1021 * possible for 1/gamma to overflow the limit of 21474 and this means the
1022 * gamma value must be at least 5/100000 and hence at most 20000.0. For
1023 * safety the limits here are a little narrower. The values are 0.00016 to
1024 * 6250.0, which are truly ridiculous gamma values (and will produce
1025 * displays that are all black or all white.)
1026 *
1027 * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
1028 * handling code, which only required the value to be >0.
1029 */
1030 png_const_charp errmsg;
1031
1032 if (gAMA < 16 || gAMA > 625000000)
1033 errmsg = "gamma value out of range";
1034
1035# ifdef PNG_READ_gAMA_SUPPORTED
1036 /* Allow the application to set the gamma value more than once */
1037 else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
1038 (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
1039 errmsg = "duplicate";
1040# endif
1041
1042 /* Do nothing if the colorspace is already invalid */
1043 else if (colorspace->flags & PNG_COLORSPACE_INVALID)
1044 return;
1045
1046 else
1047 {
1048 if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, 1/*from gAMA*/))
1049 {
1050 /* Store this gamma value. */
1051 colorspace->gamma = gAMA;
1052 colorspace->flags |=
1053 (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
1054 }
1055
1056 /* At present if the check_gamma test fails the gamma of the colorspace is
1057 * not updated however the colorspace is not invalidated. This
1058 * corresponds to the case where the existing gamma comes from an sRGB
1059 * chunk or profile. An error message has already been output.
1060 */
1061 return;
1062 }
1063
1064 /* Error exit - errmsg has been set. */
1065 colorspace->flags |= PNG_COLORSPACE_INVALID;
1066 png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
1067}
1068
1069void /* PRIVATE */
1070png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
1071{
1072 if (info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID)
1073 {
1074 /* Everything is invalid */
1075 info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
1076 PNG_INFO_iCCP);
1077
1078# ifdef PNG_COLORSPACE_SUPPORTED
1079 /* Clean up the iCCP profile now if it won't be used. */
1080 png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
1081# else
1082 PNG_UNUSED(png_ptr)
1083# endif
1084 }
1085
1086 else
1087 {
1088# ifdef PNG_COLORSPACE_SUPPORTED
1089 /* Leave the INFO_iCCP flag set if the pngset.c code has already set
1090 * it; this allows a PNG to contain a profile which matches sRGB and
1091 * yet still have that profile retrievable by the application.
1092 */
1093 if (info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB)
1094 info_ptr->valid |= PNG_INFO_sRGB;
1095
1096 else
1097 info_ptr->valid &= ~PNG_INFO_sRGB;
1098
1099 if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)
1100 info_ptr->valid |= PNG_INFO_cHRM;
1101
1102 else
1103 info_ptr->valid &= ~PNG_INFO_cHRM;
1104# endif
1105
1106 if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA)
1107 info_ptr->valid |= PNG_INFO_gAMA;
1108
1109 else
1110 info_ptr->valid &= ~PNG_INFO_gAMA;
1111 }
1112}
1113
1114#ifdef PNG_READ_SUPPORTED
1115void /* PRIVATE */
1116png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
1117{
1118 if (info_ptr == NULL) /* reduce code size; check here not in the caller */
1119 return;
1120
1121 info_ptr->colorspace = png_ptr->colorspace;
1122 png_colorspace_sync_info(png_ptr, info_ptr);
1123}
1124#endif
1125#endif
1126
1127#ifdef PNG_COLORSPACE_SUPPORTED
John Bowler736f40f2011-08-25 16:19:44 -05001128/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
1129 * cHRM, as opposed to using chromaticities. These internal APIs return
1130 * non-zero on a parameter error. The X, Y and Z values are required to be
1131 * positive and less than 1.0.
1132 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001133static int
1134png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
John Bowler736f40f2011-08-25 16:19:44 -05001135{
1136 png_int_32 d, dwhite, whiteX, whiteY;
1137
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001138 d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
1139 if (!png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d)) return 1;
1140 if (!png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d)) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001141 dwhite = d;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001142 whiteX = XYZ->red_X;
1143 whiteY = XYZ->red_Y;
John Bowler736f40f2011-08-25 16:19:44 -05001144
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001145 d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
1146 if (!png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d)) return 1;
1147 if (!png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d)) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001148 dwhite += d;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001149 whiteX += XYZ->green_X;
1150 whiteY += XYZ->green_Y;
John Bowler736f40f2011-08-25 16:19:44 -05001151
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001152 d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
1153 if (!png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d)) return 1;
1154 if (!png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d)) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001155 dwhite += d;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001156 whiteX += XYZ->blue_X;
1157 whiteY += XYZ->blue_Y;
John Bowler736f40f2011-08-25 16:19:44 -05001158
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001159 /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
John Bowler736f40f2011-08-25 16:19:44 -05001160 * thus:
1161 */
1162 if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;
1163 if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;
1164
1165 return 0;
1166}
1167
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001168static int
1169png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
John Bowler736f40f2011-08-25 16:19:44 -05001170{
1171 png_fixed_point red_inverse, green_inverse, blue_scale;
1172 png_fixed_point left, right, denominator;
1173
1174 /* Check xy and, implicitly, z. Note that wide gamut color spaces typically
1175 * have end points with 0 tristimulus values (these are impossible end
1176 * points, but they are used to cover the possible colors.)
1177 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001178 if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
1179 if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
1180 if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
1181 if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
1182 if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
1183 if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
1184 if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
1185 if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001186
1187 /* The reverse calculation is more difficult because the original tristimulus
1188 * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
1189 * derived values were recorded in the cHRM chunk;
1190 * (red,green,blue,white)x(x,y). This loses one degree of freedom and
1191 * therefore an arbitrary ninth value has to be introduced to undo the
1192 * original transformations.
1193 *
1194 * Think of the original end-points as points in (X,Y,Z) space. The
1195 * chromaticity values (c) have the property:
1196 *
1197 * C
1198 * c = ---------
1199 * X + Y + Z
1200 *
1201 * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the
1202 * three chromaticity values (x,y,z) for each end-point obey the
1203 * relationship:
1204 *
1205 * x + y + z = 1
1206 *
1207 * This describes the plane in (X,Y,Z) space that intersects each axis at the
1208 * value 1.0; call this the chromaticity plane. Thus the chromaticity
1209 * calculation has scaled each end-point so that it is on the x+y+z=1 plane
1210 * and chromaticity is the intersection of the vector from the origin to the
1211 * (X,Y,Z) value with the chromaticity plane.
1212 *
1213 * To fully invert the chromaticity calculation we would need the three
1214 * end-point scale factors, (red-scale, green-scale, blue-scale), but these
1215 * were not recorded. Instead we calculated the reference white (X,Y,Z) and
1216 * recorded the chromaticity of this. The reference white (X,Y,Z) would have
1217 * given all three of the scale factors since:
1218 *
1219 * color-C = color-c * color-scale
1220 * white-C = red-C + green-C + blue-C
1221 * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
1222 *
1223 * But cHRM records only white-x and white-y, so we have lost the white scale
1224 * factor:
1225 *
1226 * white-C = white-c*white-scale
1227 *
1228 * To handle this the inverse transformation makes an arbitrary assumption
1229 * about white-scale:
1230 *
1231 * Assume: white-Y = 1.0
1232 * Hence: white-scale = 1/white-y
1233 * Or: red-Y + green-Y + blue-Y = 1.0
1234 *
1235 * Notice the last statement of the assumption gives an equation in three of
1236 * the nine values we want to calculate. 8 more equations come from the
1237 * above routine as summarised at the top above (the chromaticity
1238 * calculation):
1239 *
1240 * Given: color-x = color-X / (color-X + color-Y + color-Z)
1241 * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
1242 *
1243 * This is 9 simultaneous equations in the 9 variables "color-C" and can be
1244 * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix
1245 * determinants, however this is not as bad as it seems because only 28 of
1246 * the total of 90 terms in the various matrices are non-zero. Nevertheless
1247 * Cramer's rule is notoriously numerically unstable because the determinant
1248 * calculation involves the difference of large, but similar, numbers. It is
1249 * difficult to be sure that the calculation is stable for real world values
1250 * and it is certain that it becomes unstable where the end points are close
1251 * together.
1252 *
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001253 * So this code uses the perhaps slightly less optimal but more
1254 * understandable and totally obvious approach of calculating color-scale.
John Bowler736f40f2011-08-25 16:19:44 -05001255 *
1256 * This algorithm depends on the precision in white-scale and that is
1257 * (1/white-y), so we can immediately see that as white-y approaches 0 the
1258 * accuracy inherent in the cHRM chunk drops off substantially.
1259 *
1260 * libpng arithmetic: a simple invertion of the above equations
1261 * ------------------------------------------------------------
1262 *
1263 * white_scale = 1/white-y
1264 * white-X = white-x * white-scale
1265 * white-Y = 1.0
1266 * white-Z = (1 - white-x - white-y) * white_scale
1267 *
1268 * white-C = red-C + green-C + blue-C
1269 * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
1270 *
1271 * This gives us three equations in (red-scale,green-scale,blue-scale) where
1272 * all the coefficients are now known:
1273 *
1274 * red-x*red-scale + green-x*green-scale + blue-x*blue-scale
1275 * = white-x/white-y
1276 * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
1277 * red-z*red-scale + green-z*green-scale + blue-z*blue-scale
1278 * = (1 - white-x - white-y)/white-y
1279 *
1280 * In the last equation color-z is (1 - color-x - color-y) so we can add all
1281 * three equations together to get an alternative third:
1282 *
1283 * red-scale + green-scale + blue-scale = 1/white-y = white-scale
1284 *
1285 * So now we have a Cramer's rule solution where the determinants are just
1286 * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve
1287 * multiplication of three coefficients so we can't guarantee to avoid
1288 * overflow in the libpng fixed point representation. Using Cramer's rule in
1289 * floating point is probably a good choice here, but it's not an option for
1290 * fixed point. Instead proceed to simplify the first two equations by
1291 * eliminating what is likely to be the largest value, blue-scale:
1292 *
1293 * blue-scale = white-scale - red-scale - green-scale
1294 *
1295 * Hence:
1296 *
1297 * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
1298 * (white-x - blue-x)*white-scale
1299 *
1300 * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
1301 * 1 - blue-y*white-scale
1302 *
1303 * And now we can trivially solve for (red-scale,green-scale):
1304 *
1305 * green-scale =
1306 * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
1307 * -----------------------------------------------------------
1308 * green-x - blue-x
1309 *
1310 * red-scale =
1311 * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale
1312 * ---------------------------------------------------------
1313 * red-y - blue-y
1314 *
1315 * Hence:
1316 *
1317 * red-scale =
1318 * ( (green-x - blue-x) * (white-y - blue-y) -
1319 * (green-y - blue-y) * (white-x - blue-x) ) / white-y
1320 * -------------------------------------------------------------------------
1321 * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
1322 *
1323 * green-scale =
1324 * ( (red-y - blue-y) * (white-x - blue-x) -
1325 * (red-x - blue-x) * (white-y - blue-y) ) / white-y
1326 * -------------------------------------------------------------------------
1327 * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
1328 *
1329 * Accuracy:
1330 * The input values have 5 decimal digits of accuracy. The values are all in
1331 * the range 0 < value < 1, so simple products are in the same range but may
1332 * need up to 10 decimal digits to preserve the original precision and avoid
1333 * underflow. Because we are using a 32-bit signed representation we cannot
1334 * match this; the best is a little over 9 decimal digits, less than 10.
1335 *
1336 * The approach used here is to preserve the maximum precision within the
1337 * signed representation. Because the red-scale calculation above uses the
1338 * difference between two products of values that must be in the range -1..+1
1339 * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The
1340 * factor is irrelevant in the calculation because it is applied to both
1341 * numerator and denominator.
1342 *
1343 * Note that the values of the differences of the products of the
1344 * chromaticities in the above equations tend to be small, for example for
1345 * the sRGB chromaticities they are:
1346 *
1347 * red numerator: -0.04751
1348 * green numerator: -0.08788
1349 * denominator: -0.2241 (without white-y multiplication)
1350 *
1351 * The resultant Y coefficients from the chromaticities of some widely used
1352 * color space definitions are (to 15 decimal places):
1353 *
1354 * sRGB
1355 * 0.212639005871510 0.715168678767756 0.072192315360734
1356 * Kodak ProPhoto
1357 * 0.288071128229293 0.711843217810102 0.000085653960605
1358 * Adobe RGB
1359 * 0.297344975250536 0.627363566255466 0.075291458493998
1360 * Adobe Wide Gamut RGB
1361 * 0.258728243040113 0.724682314948566 0.016589442011321
1362 */
1363 /* By the argument, above overflow should be impossible here. The return
1364 * value of 2 indicates an internal error to the caller.
1365 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001366 if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7))
1367 return 2;
1368 if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7))
1369 return 2;
John Bowler736f40f2011-08-25 16:19:44 -05001370 denominator = left - right;
1371
1372 /* Now find the red numerator. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001373 if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7))
1374 return 2;
1375 if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7))
1376 return 2;
John Bowler736f40f2011-08-25 16:19:44 -05001377
1378 /* Overflow is possible here and it indicates an extreme set of PNG cHRM
1379 * chunk values. This calculation actually returns the reciprocal of the
1380 * scale value because this allows us to delay the multiplication of white-y
1381 * into the denominator, which tends to produce a small number.
1382 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001383 if (!png_muldiv(&red_inverse, xy->whitey, denominator, left-right) ||
1384 red_inverse <= xy->whitey /* r+g+b scales = white scale */)
John Bowler736f40f2011-08-25 16:19:44 -05001385 return 1;
1386
1387 /* Similarly for green_inverse: */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001388 if (!png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7))
1389 return 2;
1390 if (!png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7))
1391 return 2;
1392 if (!png_muldiv(&green_inverse, xy->whitey, denominator, left-right) ||
1393 green_inverse <= xy->whitey)
John Bowler736f40f2011-08-25 16:19:44 -05001394 return 1;
1395
1396 /* And the blue scale, the checks above guarantee this can't overflow but it
1397 * can still produce 0 for extreme cHRM values.
1398 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001399 blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
John Bowler736f40f2011-08-25 16:19:44 -05001400 png_reciprocal(green_inverse);
1401 if (blue_scale <= 0) return 1;
1402
1403
1404 /* And fill in the png_XYZ: */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001405 if (!png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse)) return 1;
1406 if (!png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse)) return 1;
1407 if (!png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
John Bowler736f40f2011-08-25 16:19:44 -05001408 red_inverse))
1409 return 1;
1410
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001411 if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse))
1412 return 1;
1413 if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse))
1414 return 1;
1415 if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
John Bowler736f40f2011-08-25 16:19:44 -05001416 green_inverse))
1417 return 1;
1418
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001419 if (!png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1)) return 1;
1420 if (!png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1)) return 1;
1421 if (!png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
John Bowler736f40f2011-08-25 16:19:44 -05001422 PNG_FP_1))
1423 return 1;
1424
1425 return 0; /*success*/
1426}
1427
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001428static int
1429png_XYZ_normalize(png_XYZ *XYZ)
John Bowler736f40f2011-08-25 16:19:44 -05001430{
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001431 png_int_32 Y;
1432
1433 if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
1434 XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
1435 XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
1436 return 1;
1437
1438 /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
1439 * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
1440 * relying on addition of two positive values producing a negative one is not
1441 * safe.
1442 */
1443 Y = XYZ->red_Y;
1444 if (0x7fffffff - Y < XYZ->green_X) return 1;
1445 Y += XYZ->green_Y;
1446 if (0x7fffffff - Y < XYZ->blue_X) return 1;
1447 Y += XYZ->blue_Y;
1448
1449 if (Y != PNG_FP_1)
1450 {
1451 if (!png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y)) return 1;
1452 if (!png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y)) return 1;
1453 if (!png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y)) return 1;
1454
1455 if (!png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y)) return 1;
1456 if (!png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y)) return 1;
1457 if (!png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y)) return 1;
1458
1459 if (!png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y)) return 1;
1460 if (!png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y)) return 1;
1461 if (!png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y)) return 1;
1462 }
1463
1464 return 0;
1465}
1466
1467static int
1468png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
1469{
1470 /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
1471 return !(PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
1472 PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
1473 PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) ||
1474 PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) ||
1475 PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
1476 PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
1477 PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) ||
1478 PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta));
1479}
1480
1481/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
1482 * chunk chromaticities. Earlier checks used to simply look for the overflow
1483 * condition (where the determinant of the matrix to solve for XYZ ends up zero
1484 * because the chromaticity values are not all distinct.) Despite this it is
1485 * theoretically possible to produce chromaticities that are apparently valid
1486 * but that rapidly degrade to invalid, potentially crashing, sets because of
1487 * arithmetic inaccuracies when calculations are performed on them. The new
1488 * check is to round-trip xy -> XYZ -> xy and then check that the result is
1489 * within a small percentage of the original.
1490 */
1491static int
1492png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
1493{
1494 int result;
1495 png_xy xy_test;
1496
1497 /* As a side-effect this routine also returns the XYZ endpoints. */
1498 result = png_XYZ_from_xy(XYZ, xy);
1499 if (result) return result;
1500
1501 result = png_xy_from_XYZ(&xy_test, XYZ);
1502 if (result) return result;
1503
1504 if (png_colorspace_endpoints_match(xy, &xy_test,
1505 5/*actually, the math is pretty accurate*/))
1506 return 0;
1507
1508 /* Too much slip */
1509 return 1;
1510}
1511
1512/* This is the check going the other way. The XYZ is modified to normalize it
1513 * (another side-effect) and the xy chromaticities are returned.
1514 */
1515static int
1516png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
1517{
1518 int result;
1519 png_XYZ XYZtemp;
1520
1521 result = png_XYZ_normalize(XYZ);
1522 if (result) return result;
1523
1524 result = png_xy_from_XYZ(xy, XYZ);
1525 if (result) return result;
1526
1527 XYZtemp = *XYZ;
1528 return png_colorspace_check_xy(&XYZtemp, xy);
1529}
1530
1531/* Used to check for an endpoint match against sRGB */
1532static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
1533{
1534 /* color x y */
1535 /* red */ 64000, 33000,
1536 /* green */ 30000, 60000,
1537 /* blue */ 15000, 6000,
1538 /* white */ 31270, 32900
1539};
1540
1541static int
1542png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
1543 png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
1544 int preferred)
1545{
1546 if (colorspace->flags & PNG_COLORSPACE_INVALID)
1547 return 0;
1548
1549 /* The consistency check is performed on the chromaticities; this factors out
1550 * variations because of the normalization (or not) of the end point Y
1551 * values.
1552 */
1553 if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS))
1554 {
1555 /* The end points must be reasonably close to any we already have. The
1556 * following allows an error of up to +/-.001
1557 */
1558 if (!png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 100))
1559 {
1560 colorspace->flags |= PNG_COLORSPACE_INVALID;
1561 png_benign_error(png_ptr, "inconsistent chromaticities");
1562 return 0; /* failed */
1563 }
1564
1565 /* Only overwrite with preferred values */
1566 if (!preferred)
1567 return 1; /* ok, but no change */
1568 }
1569
1570 colorspace->end_points_xy = *xy;
1571 colorspace->end_points_XYZ = *XYZ;
1572 colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
1573
1574 /* The end points are normally quoted to two decimal digits, so allow +/-0.01
1575 * on this test.
1576 */
1577 if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000))
1578 colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
1579
1580 else
1581 colorspace->flags &= PNG_COLORSPACE_CANCEL(
1582 PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
1583
1584 return 2; /* ok and changed */
1585}
1586
1587int /* PRIVATE */
1588png_colorspace_set_chromaticities(png_const_structrp png_ptr,
1589 png_colorspacerp colorspace, const png_xy *xy, int preferred)
1590{
1591 /* We must check the end points to ensure they are reasonable - in the past
1592 * color management systems have crashed as a result of getting bogus
1593 * colorant values, while this isn't the fault of libpng it is the
1594 * responsibility of libpng because PNG carries the bomb and libpng is in a
1595 * position to protect against it.
1596 */
1597 png_XYZ XYZ;
1598
1599 switch (png_colorspace_check_xy(&XYZ, xy))
John Bowler736f40f2011-08-25 16:19:44 -05001600 {
1601 case 0: /* success */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001602 return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
1603 preferred);
John Bowler736f40f2011-08-25 16:19:44 -05001604
1605 case 1:
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001606 /* We can't invert the chromaticities so we can't produce value XYZ
1607 * values. Likely as not a color management system will fail too.
John Bowler736f40f2011-08-25 16:19:44 -05001608 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001609 colorspace->flags |= PNG_COLORSPACE_INVALID;
1610 png_benign_error(png_ptr, "invalid chromaticities");
John Bowler736f40f2011-08-25 16:19:44 -05001611 break;
1612
1613 default:
1614 /* libpng is broken; this should be a warning but if it happens we
1615 * want error reports so for the moment it is an error.
1616 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001617 colorspace->flags |= PNG_COLORSPACE_INVALID;
1618 png_error(png_ptr, "internal error checking chromaticities");
John Bowler736f40f2011-08-25 16:19:44 -05001619 break;
1620 }
1621
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001622 return 0; /* failed */
1623}
1624
1625int /* PRIVATE */
1626png_colorspace_set_endpoints(png_const_structrp png_ptr,
1627 png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
1628{
1629 png_XYZ XYZ = *XYZ_in;
1630 png_xy xy;
1631
1632 switch (png_colorspace_check_XYZ(&xy, &XYZ))
1633 {
1634 case 0:
1635 return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
1636 preferred);
1637
1638 case 1:
1639 /* End points are invalid. */
1640 colorspace->flags |= PNG_COLORSPACE_INVALID;
1641 png_benign_error(png_ptr, "invalid end points");
1642 break;
1643
1644 default:
1645 colorspace->flags |= PNG_COLORSPACE_INVALID;
1646 png_error(png_ptr, "internal error checking chromaticities");
1647 break;
1648 }
1649
1650 return 0; /* failed */
1651}
1652
1653#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
1654/* Error message generation */
1655static char
1656png_icc_tag_char(png_uint_32 byte)
1657{
1658 byte &= 0xff;
1659 if (byte >= 32 && byte <= 126)
1660 return (char)byte;
1661 else
1662 return '?';
1663}
1664
1665static void
1666png_icc_tag_name(char *name, png_uint_32 tag)
1667{
1668 name[0] = '\'';
1669 name[1] = png_icc_tag_char(tag >> 24);
1670 name[2] = png_icc_tag_char(tag >> 16);
1671 name[3] = png_icc_tag_char(tag >> 8);
1672 name[4] = png_icc_tag_char(tag );
1673 name[5] = '\'';
1674}
1675
1676static int
1677is_ICC_signature_char(png_alloc_size_t it)
1678{
1679 return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
1680 (it >= 97 && it <= 122);
1681}
1682
1683static int is_ICC_signature(png_alloc_size_t it)
1684{
1685 return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
1686 is_ICC_signature_char((it >> 16) & 0xff) &&
1687 is_ICC_signature_char((it >> 8) & 0xff) &&
1688 is_ICC_signature_char(it & 0xff);
1689}
1690
1691static int
1692png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
1693 png_const_charp name, png_alloc_size_t value, png_const_charp reason)
1694{
1695 size_t pos;
1696 char message[196]; /* see below for calculation */
1697
1698 if (colorspace != NULL)
1699 colorspace->flags |= PNG_COLORSPACE_INVALID;
1700
1701 pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
1702 pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
1703 pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
1704 if (is_ICC_signature(value))
1705 {
1706 /* So 'value' is at most 4 bytes and the following cast is safe */
1707 png_icc_tag_name(message+pos, (png_uint_32)value);
1708 pos += 6; /* total +8; less than the else clause */
1709 message[pos++] = ':';
1710 message[pos++] = ' ';
1711 }
1712# ifdef PNG_WARNINGS_SUPPORTED
1713 else
1714 {
1715 char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
1716
1717 pos = png_safecat(message, (sizeof message), pos,
1718 png_format_number(number, number+(sizeof number),
1719 PNG_NUMBER_FORMAT_x, value));
1720 pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
1721 }
1722# endif
1723 /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
1724 pos = png_safecat(message, (sizeof message), pos, reason);
1725
1726 /* This is recoverable, but make it unconditionally an app_error on write to
1727 * avoid writing invalid ICC profiles into PNG files. (I.e. we handle them
1728 * on read, with a warning, but on write unless the app turns off
1729 * application errors the PNG won't be written.)
1730 */
1731 png_chunk_report(png_ptr, message,
1732 (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
1733
John Bowler736f40f2011-08-25 16:19:44 -05001734 return 0;
1735}
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001736#endif /* sRGB || iCCP */
1737
1738#ifdef PNG_sRGB_SUPPORTED
1739int /* PRIVATE */
1740png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
1741 int intent)
1742{
1743 /* sRGB sets known gamma, end points and (from the chunk) intent. */
1744 /* IMPORTANT: these are not necessarily the values found in an ICC profile
1745 * because ICC profiles store values adapted to a D50 environment; it is
1746 * expected that the ICC profile mediaWhitePointTag will be D50, see the
1747 * checks and code elsewhere to understand this better.
1748 *
1749 * These XYZ values, which are accurate to 5dp, produce rgb to gray
1750 * coefficients of (6968,23435,2366), which are reduced (because they add up
1751 * to 32769 not 32768) to (6968,23434,2366). These are the values that
1752 * libpng has traditionally used (and are the best values given the 15bit
1753 * algorithm used by the rgb to gray code.)
1754 */
1755 static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
1756 {
1757 /* color X Y Z */
1758 /* red */ 41239, 21264, 1933,
1759 /* green */ 35758, 71517, 11919,
1760 /* blue */ 18048, 7219, 95053
1761 };
1762
1763 /* Do nothing if the colorspace is already invalidated. */
1764 if (colorspace->flags & PNG_COLORSPACE_INVALID)
1765 return 0;
1766
1767 /* Check the intent, then check for existing settings. It is valid for the
1768 * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
1769 * be consistent with the correct values. If, however, this function is
1770 * called below because an iCCP chunk matches sRGB then it is quite
1771 * conceivable that an older app recorded incorrect gAMA and cHRM because of
1772 * an incorrect calculation based on the values in the profile - this does
1773 * *not* invalidate the profile (though it still produces an error, which can
1774 * be ignored.)
1775 */
1776 if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
1777 return png_icc_profile_error(png_ptr, colorspace, "sRGB",
1778 (unsigned)intent, "invalid sRGB rendering intent");
1779
1780 if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
1781 colorspace->rendering_intent != intent)
1782 return png_icc_profile_error(png_ptr, colorspace, "sRGB",
1783 (unsigned)intent, "inconsistent rendering intents");
1784
1785 if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
1786 {
1787 png_benign_error(png_ptr, "duplicate sRGB information ignored");
1788 return 0;
1789 }
1790
1791 /* If the standard sRGB cHRM chunk does not match the one from the PNG file
1792 * warn but overwrite the value with the correct one.
1793 */
1794 if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
1795 !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
1796 100))
1797 png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
1798 PNG_CHUNK_ERROR);
1799
1800 /* This check is just done for the error reporting - the routine always
1801 * returns true when the 'from' argument corresponds to sRGB (2).
1802 */
1803 (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
1804 2/*from sRGB*/);
1805
1806 /* intent: bugs in GCC force 'int' to be used as the parameter type. */
1807 colorspace->rendering_intent = (png_uint_16)intent;
1808 colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
1809
1810 /* endpoints */
1811 colorspace->end_points_xy = sRGB_xy;
1812 colorspace->end_points_XYZ = sRGB_XYZ;
1813 colorspace->flags |=
1814 (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
1815
1816 /* gamma */
1817 colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
1818 colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
1819
1820 /* Finally record that we have an sRGB profile */
1821 colorspace->flags |=
1822 (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
1823
1824 return 1; /* set */
1825}
1826#endif /* sRGB */
1827
1828#ifdef PNG_iCCP_SUPPORTED
1829/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value
1830 * is XYZ(0.9642,1.0,0.8249), which scales to:
1831 *
1832 * (63189.8112, 65536, 54060.6464)
1833 */
1834static const png_byte D50_nCIEXYZ[12] =
1835 { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
1836
1837int /* PRIVATE */
1838png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
1839 png_const_charp name, png_uint_32 profile_length)
1840{
1841 if (profile_length < 132)
1842 return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
1843 "too short");
1844
1845 if (profile_length & 3)
1846 return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
1847 "invalid length");
1848
1849 return 1;
1850}
1851
1852int /* PRIVATE */
1853png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
1854 png_const_charp name, png_uint_32 profile_length,
1855 png_const_bytep profile/* first 132 bytes only */, int color_type)
1856{
1857 png_uint_32 temp;
1858
1859 /* Length check; this cannot be ignored in this code because profile_length
1860 * is used later to check the tag table, so even if the profile seems over
1861 * long profile_length from the caller must be correct. The caller can fix
1862 * this up on read or write by just passing in the profile header length.
1863 */
1864 temp = png_get_uint_32(profile);
1865 if (temp != profile_length)
1866 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1867 "length does not match profile");
1868
1869 temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
Glenn Randers-Pehrson67a289f2013-04-19 19:03:34 -05001870 if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001871 profile_length < 132+12*temp) /* truncated tag table */
1872 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1873 "tag count too large");
1874
1875 /* The 'intent' must be valid or we can't store it, ICC limits the intent to
1876 * 16 bits.
1877 */
1878 temp = png_get_uint_32(profile+64);
1879 if (temp >= 0xffff) /* The ICC limit */
1880 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1881 "invalid rendering intent");
1882
1883 /* This is just a warning because the profile may be valid in future
1884 * versions.
1885 */
1886 if (temp >= PNG_sRGB_INTENT_LAST)
1887 (void)png_icc_profile_error(png_ptr, NULL, name, temp,
1888 "intent outside defined range");
1889
1890 /* At this point the tag table can't be checked because it hasn't necessarily
1891 * been loaded; however, various header fields can be checked. These checks
1892 * are for values permitted by the PNG spec in an ICC profile; the PNG spec
1893 * restricts the profiles that can be passed in an iCCP chunk (they must be
1894 * appropriate to processing PNG data!)
1895 */
1896
1897 /* Data checks (could be skipped). These checks must be independent of the
1898 * version number; however, the version number doesn't accomodate changes in
1899 * the header fields (just the known tags and the interpretation of the
1900 * data.)
1901 */
1902 temp = png_get_uint_32(profile+36); /* signature 'ascp' */
1903 if (temp != 0x61637370)
1904 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1905 "invalid signature");
1906
1907 /* Currently the PCS illuminant/adopted white point (the computational
1908 * white point) are required to be D50,
1909 * however the profile contains a record of the illuminant so perhaps ICC
1910 * expects to be able to change this in the future (despite the rationale in
1911 * the introduction for using a fixed PCS adopted white.) Consequently the
1912 * following is just a warning.
1913 */
1914 if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
1915 (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
1916 "PCS illuminant is not D50");
1917
1918 /* The PNG spec requires this:
1919 * "If the iCCP chunk is present, the image samples conform to the colour
1920 * space represented by the embedded ICC profile as defined by the
1921 * International Color Consortium [ICC]. The colour space of the ICC profile
1922 * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
1923 * 6), or a greyscale colour space for greyscale images (PNG colour types 0
1924 * and 4)."
1925 *
1926 * This checking code ensures the embedded profile (on either read or write)
1927 * conforms to the specification requirements. Notice that an ICC 'gray'
1928 * color-space profile contains the information to transform the monochrome
1929 * data to XYZ or L*a*b (according to which PCS the profile uses) and this
1930 * should be used in preference to the standard libpng K channel replication
1931 * into R, G and B channels.
1932 *
1933 * Previously it was suggested that an RGB profile on grayscale data could be
1934 * handled. However it it is clear that using an RGB profile in this context
1935 * must be an error - there is no specification of what it means. Thus it is
1936 * almost certainly more correct to ignore the profile.
1937 */
1938 temp = png_get_uint_32(profile+16); /* data colour space field */
1939 switch (temp)
1940 {
1941 case 0x52474220: /* 'RGB ' */
1942 if (!(color_type & PNG_COLOR_MASK_COLOR))
1943 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1944 "RGB color space not permitted on grayscale PNG");
1945 break;
1946
1947 case 0x47524159: /* 'GRAY' */
1948 if (color_type & PNG_COLOR_MASK_COLOR)
1949 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1950 "Gray color space not permitted on RGB PNG");
1951 break;
1952
1953 default:
1954 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1955 "invalid ICC profile color space");
1956 }
1957
1958 /* It is up to the application to check that the profile class matches the
1959 * application requirements; the spec provides no guidance, but it's pretty
1960 * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
1961 * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these
1962 * cases. Issue an error for device link or abstract profiles - these don't
1963 * contain the records necessary to transform the color-space to anything
1964 * other than the target device (and not even that for an abstract profile).
1965 * Profiles of these classes may not be embedded in images.
1966 */
1967 temp = png_get_uint_32(profile+12); /* profile/device class */
1968 switch (temp)
1969 {
1970 case 0x73636E72: /* 'scnr' */
1971 case 0x6D6E7472: /* 'mntr' */
1972 case 0x70727472: /* 'prtr' */
1973 case 0x73706163: /* 'spac' */
1974 /* All supported */
1975 break;
1976
1977 case 0x61627374: /* 'abst' */
1978 /* May not be embedded in an image */
1979 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1980 "invalid embedded Abstract ICC profile");
1981
1982 case 0x6C696E6B: /* 'link' */
1983 /* DeviceLink profiles cannnot be interpreted in a non-device specific
1984 * fashion, if an app uses the AToB0Tag in the profile the results are
1985 * undefined unless the result is sent to the intended device,
1986 * therefore a DeviceLink profile should not be found embedded in a
1987 * PNG.
1988 */
1989 return png_icc_profile_error(png_ptr, colorspace, name, temp,
1990 "unexpected DeviceLink ICC profile class");
1991
1992 case 0x6E6D636C: /* 'nmcl' */
1993 /* A NamedColor profile is also device specific, however it doesn't
1994 * contain an AToB0 tag that is open to misintrepretation. Almost
1995 * certainly it will fail the tests below.
1996 */
1997 (void)png_icc_profile_error(png_ptr, NULL, name, temp,
1998 "unexpected NamedColor ICC profile class");
1999 break;
2000
2001 default:
2002 /* To allow for future enhancements to the profile accept unrecognized
2003 * profile classes with a warning, these then hit the test below on the
2004 * tag content to ensure they are backward compatible with one of the
2005 * understood profiles.
2006 */
2007 (void)png_icc_profile_error(png_ptr, NULL, name, temp,
2008 "unrecognized ICC profile class");
2009 break;
2010 }
2011
2012 /* For any profile other than a device link one the PCS must be encoded
2013 * either in XYZ or Lab.
2014 */
2015 temp = png_get_uint_32(profile+20);
2016 switch (temp)
2017 {
2018 case 0x58595A20: /* 'XYZ ' */
2019 case 0x4C616220: /* 'Lab ' */
2020 break;
2021
2022 default:
2023 return png_icc_profile_error(png_ptr, colorspace, name, temp,
2024 "unexpected ICC PCS encoding");
2025 }
2026
2027 return 1;
2028}
2029
2030int /* PRIVATE */
2031png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
2032 png_const_charp name, png_uint_32 profile_length,
2033 png_const_bytep profile /* header plus whole tag table */)
2034{
2035 png_uint_32 tag_count = png_get_uint_32(profile+128);
2036 png_uint_32 itag;
2037 png_const_bytep tag = profile+132; /* The first tag */
2038
2039 /* First scan all the tags in the table and add bits to the icc_info value
2040 * (temporarily in 'tags').
2041 */
2042 for (itag=0; itag < tag_count; ++itag, tag += 12)
2043 {
2044 png_uint_32 tag_id = png_get_uint_32(tag+0);
2045 png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
2046 png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
2047
2048 /* The ICC specification does not exclude zero length tags, therefore the
2049 * start might actually be anywhere if there is no data, but this would be
2050 * a clear abuse of the intent of the standard so the start is checked for
2051 * being in range. All defined tag types have an 8 byte header - a 4 byte
2052 * type signature then 0.
2053 */
2054 if ((tag_start & 3) != 0)
2055 {
2056 /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
2057 * only a warning here because libpng does not care about the
2058 * alignment.
2059 */
2060 (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
2061 "ICC profile tag start not a multiple of 4");
2062 }
2063
2064 /* This is a hard error; potentially it can cause read outside the
2065 * profile.
2066 */
2067 if (tag_start > profile_length || tag_length > profile_length - tag_start)
2068 return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
2069 "ICC profile tag outside profile");
2070 }
2071
2072 return 1; /* success, maybe with warnings */
2073}
2074
2075#ifdef PNG_sRGB_SUPPORTED
2076/* Information about the known ICC sRGB profiles */
2077static const struct
2078{
2079 png_uint_32 adler, crc, length;
2080 png_uint_32 md5[4];
2081 png_byte have_md5;
2082 png_byte is_broken;
2083 png_uint_16 intent;
2084
2085# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
2086# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
2087 { adler, crc, length, md5, broke, intent },
2088
2089} png_sRGB_checks[] =
2090{
2091 /* This data comes from contrib/tools/checksum-icc run on downloads of
2092 * all four ICC sRGB profiles from www.color.org.
2093 */
2094 /* adler32, crc32, MD5[4], intent, date, length, file-name */
2095 PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
2096 PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
2097 "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
2098
2099 /* ICC sRGB v2 perceptual no black-compensation: */
2100 PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
2101 PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
2102 "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
2103
2104 PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
2105 PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
2106 "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
2107
2108 /* ICC sRGB v4 perceptual */
2109 PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
2110 PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
2111 "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
2112
2113 /* The following profiles have no known MD5 checksum. If there is a match
2114 * on the (empty) MD5 the other fields are used to attempt a match and
2115 * a warning is produced. The first two of these profiles have a 'cprt' tag
2116 * which suggests that they were also made by Hewlett Packard.
2117 */
2118 PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
2119 PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
2120 "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
2121
2122 /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
2123 * match the D50 PCS illuminant in the header (it is in fact the D65 values,
2124 * so the white point is recorded as the un-adapted value.) The profiles
2125 * below only differ in one byte - the intent - and are basically the same as
2126 * the previous profile except for the mediaWhitePointTag error and a missing
2127 * chromaticAdaptationTag.
2128 */
2129 PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
2130 PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
2131 "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
2132
2133 PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
2134 PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
2135 "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
2136};
2137
2138static int
2139png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
2140 png_const_bytep profile, uLong adler)
2141{
2142 /* The quick check is to verify just the MD5 signature and trust the
2143 * rest of the data. Because the profile has already been verified for
2144 * correctness this is safe. png_colorspace_set_sRGB will check the 'intent'
2145 * field too, so if the profile has been edited with an intent not defined
2146 * by sRGB (but maybe defined by a later ICC specification) the read of
2147 * the profile will fail at that point.
2148 */
2149 png_uint_32 length = 0;
2150 png_uint_32 intent = 0x10000; /* invalid */
2151#if PNG_sRGB_PROFILE_CHECKS > 1
2152 uLong crc = 0; /* the value for 0 length data */
John Bowler921648a2012-03-28 23:36:12 -05002153#endif
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06002154 unsigned int i;
2155
2156 for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
2157 {
2158 if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
2159 png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
2160 png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
2161 png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
2162 {
2163 /* This may be one of the old HP profiles without an MD5, in that
2164 * case we can only use the length and Adler32 (note that these
2165 * are not used by default if there is an MD5!)
2166 */
2167# if PNG_sRGB_PROFILE_CHECKS == 0
2168 if (png_sRGB_checks[i].have_md5)
2169 return 1+png_sRGB_checks[i].is_broken;
2170# endif
2171
2172 /* Profile is unsigned or more checks have been configured in. */
2173 if (length == 0)
2174 {
2175 length = png_get_uint_32(profile);
2176 intent = png_get_uint_32(profile+64);
2177 }
2178
2179 /* Length *and* intent must match */
2180 if (length == png_sRGB_checks[i].length &&
2181 intent == png_sRGB_checks[i].intent)
2182 {
Glenn Randers-Pehrson1f24cb72013-03-04 21:58:02 -06002183 /* Now calculate the adler32 if not done already. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06002184 if (adler == 0)
2185 {
2186 adler = adler32(0, NULL, 0);
2187 adler = adler32(adler, profile, length);
2188 }
2189
2190 if (adler == png_sRGB_checks[i].adler)
2191 {
2192 /* These basic checks suggest that the data has not been
2193 * modified, but if the check level is more than 1 perform
2194 * our own crc32 checksum on the data.
2195 */
2196# if PNG_sRGB_PROFILE_CHECKS > 1
2197 if (crc == 0)
2198 {
2199 crc = crc32(0, NULL, 0);
2200 crc = crc32(crc, profile, length);
2201 }
2202
2203 /* So this check must pass for the 'return' below to happen.
2204 */
2205 if (crc == png_sRGB_checks[i].crc)
2206# endif
2207 {
2208 if (png_sRGB_checks[i].is_broken)
2209 {
2210 /* These profiles are known to have bad data that may cause
2211 * problems if they are used, therefore attempt to
2212 * discourage their use, skip the 'have_md5' warning below,
2213 * which is made irrelevant by this error.
2214 */
2215 png_chunk_report(png_ptr, "known incorrect sRGB profile",
2216 PNG_CHUNK_ERROR);
2217 }
2218
2219 /* Warn that this being done; this isn't even an error since
2220 * the profile is perfectly valid, but it would be nice if
2221 * people used the up-to-date ones.
2222 */
2223 else if (!png_sRGB_checks[i].have_md5)
2224 {
2225 png_chunk_report(png_ptr,
2226 "out-of-date sRGB profile with no signature",
2227 PNG_CHUNK_WARNING);
2228 }
2229
2230 return 1+png_sRGB_checks[i].is_broken;
2231 }
2232 }
2233 }
2234
2235# if PNG_sRGB_PROFILE_CHECKS > 0
2236 /* The signature matched, but the profile had been changed in some
2237 * way. This is an apparent violation of the ICC terms of use and,
2238 * anyway, probably indicates a data error or uninformed hacking.
2239 */
2240 if (png_sRGB_checks[i].have_md5)
2241 png_benign_error(png_ptr,
2242 "copyright violation: edited ICC profile ignored");
2243# endif
2244 }
2245 }
2246
2247 return 0; /* no match */
2248}
2249#endif
2250
2251#ifdef PNG_sRGB_SUPPORTED
2252void /* PRIVATE */
2253png_icc_set_sRGB(png_const_structrp png_ptr,
2254 png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
2255{
2256 /* Is this profile one of the known ICC sRGB profiles? If it is, just set
2257 * the sRGB information.
2258 */
2259 if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler))
2260 (void)png_colorspace_set_sRGB(png_ptr, colorspace,
2261 (int)/*already checked*/png_get_uint_32(profile+64));
2262}
2263#endif /* PNG_READ_sRGB_SUPPORTED */
2264
2265int /* PRIVATE */
2266png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
2267 png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
2268 int color_type)
2269{
2270 if (colorspace->flags & PNG_COLORSPACE_INVALID)
2271 return 0;
2272
2273 if (png_icc_check_length(png_ptr, colorspace, name, profile_length) &&
2274 png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
2275 color_type) &&
2276 png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
2277 profile))
2278 {
John Bowlere4413a72013-04-17 21:27:47 -05002279# ifdef PNG_sRGB_SUPPORTED
2280 /* If no sRGB support, don't try storing sRGB information */
2281 png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
2282# endif
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06002283 return 1;
2284 }
2285
2286 /* Failure case */
2287 return 0;
2288}
2289#endif /* iCCP */
2290
2291#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2292void /* PRIVATE */
2293png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
2294{
2295 /* Set the rgb_to_gray coefficients from the colorspace. */
2296 if (!png_ptr->rgb_to_gray_coefficients_set &&
2297 (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
2298 {
2299 /* png_set_background has not been called, get the coefficients from the Y
2300 * values of the colorspace colorants.
2301 */
2302 png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
2303 png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
2304 png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
2305 png_fixed_point total = r+g+b;
2306
2307 if (total > 0 &&
2308 r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
2309 g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
2310 b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
2311 r+g+b <= 32769)
2312 {
2313 /* We allow 0 coefficients here. r+g+b may be 32769 if two or
2314 * all of the coefficients were rounded up. Handle this by
2315 * reducing the *largest* coefficient by 1; this matches the
2316 * approach used for the default coefficients in pngrtran.c
2317 */
2318 int add = 0;
2319
2320 if (r+g+b > 32768)
2321 add = -1;
2322 else if (r+g+b < 32768)
2323 add = 1;
2324
2325 if (add != 0)
2326 {
2327 if (g >= r && g >= b)
2328 g += add;
2329 else if (r >= g && r >= b)
2330 r += add;
2331 else
2332 b += add;
2333 }
2334
2335 /* Check for an internal error. */
2336 if (r+g+b != 32768)
2337 png_error(png_ptr,
2338 "internal error handling cHRM coefficients");
2339
2340 else
2341 {
2342 png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r;
2343 png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
2344 }
2345 }
2346
2347 /* This is a png_error at present even though it could be ignored -
2348 * it should never happen, but it is important that if it does, the
2349 * bug is fixed.
2350 */
2351 else
2352 png_error(png_ptr, "internal error handling cHRM->XYZ");
2353 }
2354}
2355#endif
2356
2357#endif /* COLORSPACE */
John Bowlerb11b31a2012-03-21 07:55:46 -05002358
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002359void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06002360png_check_IHDR(png_const_structrp png_ptr,
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002361 png_uint_32 width, png_uint_32 height, int bit_depth,
2362 int color_type, int interlace_type, int compression_type,
2363 int filter_type)
2364{
2365 int error = 0;
2366
2367 /* Check for width and height valid values */
2368 if (width == 0)
2369 {
2370 png_warning(png_ptr, "Image width is zero in IHDR");
2371 error = 1;
2372 }
2373
2374 if (height == 0)
2375 {
2376 png_warning(png_ptr, "Image height is zero in IHDR");
2377 error = 1;
2378 }
2379
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002380# ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonb7040362011-06-11 14:20:22 -05002381 if (width > png_ptr->user_width_max)
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002382
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002383# else
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002384 if (width > PNG_USER_WIDTH_MAX)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002385# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002386 {
2387 png_warning(png_ptr, "Image width exceeds user limit in IHDR");
2388 error = 1;
2389 }
2390
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002391# ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonb7040362011-06-11 14:20:22 -05002392 if (height > png_ptr->user_height_max)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002393# else
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002394 if (height > PNG_USER_HEIGHT_MAX)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002395# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002396 {
2397 png_warning(png_ptr, "Image height exceeds user limit in IHDR");
2398 error = 1;
2399 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002400
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002401 if (width > PNG_UINT_31_MAX)
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002402 {
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002403 png_warning(png_ptr, "Invalid image width in IHDR");
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002404 error = 1;
2405 }
2406
Glenn Randers-Pehrsonbc363ec2010-10-12 21:17:00 -05002407 if (height > PNG_UINT_31_MAX)
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002408 {
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002409 png_warning(png_ptr, "Invalid image height in IHDR");
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002410 error = 1;
2411 }
2412
Glenn Randers-Pehrsonbc363ec2010-10-12 21:17:00 -05002413 if (width > (PNG_UINT_32_MAX
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002414 >> 3) /* 8-byte RGBA pixels */
Glenn Randers-Pehrsonc5080812010-10-23 08:26:26 -05002415 - 48 /* bigrowbuf hack */
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002416 - 1 /* filter byte */
2417 - 7*8 /* rounding of width to multiple of 8 pixels */
2418 - 8) /* extra max_pixel_depth pad */
2419 png_warning(png_ptr, "Width is too large for libpng to process pixels");
2420
2421 /* Check other values */
2422 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
2423 bit_depth != 8 && bit_depth != 16)
2424 {
2425 png_warning(png_ptr, "Invalid bit depth in IHDR");
2426 error = 1;
2427 }
2428
2429 if (color_type < 0 || color_type == 1 ||
2430 color_type == 5 || color_type > 6)
2431 {
2432 png_warning(png_ptr, "Invalid color type in IHDR");
2433 error = 1;
2434 }
2435
2436 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
2437 ((color_type == PNG_COLOR_TYPE_RGB ||
2438 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
2439 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
2440 {
2441 png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
2442 error = 1;
2443 }
2444
2445 if (interlace_type >= PNG_INTERLACE_LAST)
2446 {
2447 png_warning(png_ptr, "Unknown interlace method in IHDR");
2448 error = 1;
2449 }
2450
2451 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
2452 {
2453 png_warning(png_ptr, "Unknown compression method in IHDR");
2454 error = 1;
2455 }
2456
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002457# ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002458 /* Accept filter_method 64 (intrapixel differencing) only if
2459 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
2460 * 2. Libpng did not read a PNG signature (this filter_method is only
2461 * used in PNG datastreams that are embedded in MNG datastreams) and
2462 * 3. The application called png_permit_mng_features with a mask that
2463 * included PNG_FLAG_MNG_FILTER_64 and
2464 * 4. The filter_method is 64 and
2465 * 5. The color_type is RGB or RGBA
2466 */
2467 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
2468 png_ptr->mng_features_permitted)
2469 png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
2470
2471 if (filter_type != PNG_FILTER_TYPE_BASE)
2472 {
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05002473 if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002474 (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
2475 ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
2476 (color_type == PNG_COLOR_TYPE_RGB ||
2477 color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05002478 {
2479 png_warning(png_ptr, "Unknown filter method in IHDR");
2480 error = 1;
2481 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002482
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05002483 if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
2484 {
2485 png_warning(png_ptr, "Invalid filter method in IHDR");
2486 error = 1;
2487 }
2488 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002489
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002490# else
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002491 if (filter_type != PNG_FILTER_TYPE_BASE)
2492 {
2493 png_warning(png_ptr, "Unknown filter method in IHDR");
2494 error = 1;
2495 }
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002496# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002497
2498 if (error == 1)
2499 png_error(png_ptr, "Invalid IHDR data");
2500}
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002501
2502#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
2503/* ASCII to fp functions */
2504/* Check an ASCII formated floating point value, see the more detailed
2505 * comments in pngpriv.h
2506 */
John Bowler8d261262011-06-18 13:37:11 -05002507/* The following is used internally to preserve the sticky flags */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002508#define png_fp_add(state, flags) ((state) |= (flags))
John Bowler8d261262011-06-18 13:37:11 -05002509#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002510
2511int /* PRIVATE */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002512png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002513 png_size_tp whereami)
2514{
2515 int state = *statep;
2516 png_size_t i = *whereami;
2517
2518 while (i < size)
2519 {
2520 int type;
2521 /* First find the type of the next character */
John Bowler8d261262011-06-18 13:37:11 -05002522 switch (string[i])
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002523 {
John Bowler8d261262011-06-18 13:37:11 -05002524 case 43: type = PNG_FP_SAW_SIGN; break;
2525 case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
2526 case 46: type = PNG_FP_SAW_DOT; break;
2527 case 48: type = PNG_FP_SAW_DIGIT; break;
2528 case 49: case 50: case 51: case 52:
2529 case 53: case 54: case 55: case 56:
2530 case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
2531 case 69:
2532 case 101: type = PNG_FP_SAW_E; break;
2533 default: goto PNG_FP_End;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002534 }
2535
2536 /* Now deal with this type according to the current
2537 * state, the type is arranged to not overlap the
2538 * bits of the PNG_FP_STATE.
2539 */
John Bowler8d261262011-06-18 13:37:11 -05002540 switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002541 {
John Bowler8d261262011-06-18 13:37:11 -05002542 case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002543 if (state & PNG_FP_SAW_ANY)
2544 goto PNG_FP_End; /* not a part of the number */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002545
John Bowler8d261262011-06-18 13:37:11 -05002546 png_fp_add(state, type);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002547 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002548
John Bowler8d261262011-06-18 13:37:11 -05002549 case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002550 /* Ok as trailer, ok as lead of fraction. */
2551 if (state & PNG_FP_SAW_DOT) /* two dots */
2552 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002553
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002554 else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
John Bowler8d261262011-06-18 13:37:11 -05002555 png_fp_add(state, type);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002556
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002557 else
John Bowler8d261262011-06-18 13:37:11 -05002558 png_fp_set(state, PNG_FP_FRACTION | type);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002559
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002560 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002561
John Bowler8d261262011-06-18 13:37:11 -05002562 case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002563 if (state & PNG_FP_SAW_DOT) /* delayed fraction */
2564 png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002565
John Bowler8d261262011-06-18 13:37:11 -05002566 png_fp_add(state, type | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002567
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002568 break;
John Bowler8d261262011-06-18 13:37:11 -05002569
2570 case PNG_FP_INTEGER + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002571 if ((state & PNG_FP_SAW_DIGIT) == 0)
2572 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002573
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002574 png_fp_set(state, PNG_FP_EXPONENT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002575
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002576 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002577
John Bowler8d261262011-06-18 13:37:11 -05002578 /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:
2579 goto PNG_FP_End; ** no sign in fraction */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002580
John Bowler8d261262011-06-18 13:37:11 -05002581 /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002582 goto PNG_FP_End; ** Because SAW_DOT is always set */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002583
John Bowler8d261262011-06-18 13:37:11 -05002584 case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
2585 png_fp_add(state, type | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002586 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002587
John Bowler8d261262011-06-18 13:37:11 -05002588 case PNG_FP_FRACTION + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002589 /* This is correct because the trailing '.' on an
2590 * integer is handled above - so we can only get here
2591 * with the sequence ".E" (with no preceding digits).
2592 */
2593 if ((state & PNG_FP_SAW_DIGIT) == 0)
2594 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002595
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002596 png_fp_set(state, PNG_FP_EXPONENT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002597
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002598 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002599
John Bowler8d261262011-06-18 13:37:11 -05002600 case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002601 if (state & PNG_FP_SAW_ANY)
2602 goto PNG_FP_End; /* not a part of the number */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002603
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002604 png_fp_add(state, PNG_FP_SAW_SIGN);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002605
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002606 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002607
John Bowler8d261262011-06-18 13:37:11 -05002608 /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002609 goto PNG_FP_End; */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002610
John Bowler8d261262011-06-18 13:37:11 -05002611 case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
2612 png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002613
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002614 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002615
John Bowler8d261262011-06-18 13:37:11 -05002616 /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002617 goto PNG_FP_End; */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002618
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002619 default: goto PNG_FP_End; /* I.e. break 2 */
2620 }
2621
2622 /* The character seems ok, continue. */
2623 ++i;
2624 }
2625
2626PNG_FP_End:
2627 /* Here at the end, update the state and return the correct
2628 * return code.
2629 */
2630 *statep = state;
2631 *whereami = i;
2632
2633 return (state & PNG_FP_SAW_DIGIT) != 0;
2634}
2635
2636
2637/* The same but for a complete string. */
2638int
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002639png_check_fp_string(png_const_charp string, png_size_t size)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002640{
2641 int state=0;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002642 png_size_t char_index=0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002643
John Bowler8d261262011-06-18 13:37:11 -05002644 if (png_check_fp_number(string, size, &state, &char_index) &&
2645 (char_index == size || string[char_index] == 0))
2646 return state /* must be non-zero - see above */;
2647
2648 return 0; /* i.e. fail */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002649}
2650#endif /* pCAL or sCAL */
2651
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06002652#ifdef PNG_sCAL_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002653# ifdef PNG_FLOATING_POINT_SUPPORTED
2654/* Utility used below - a simple accurate power of ten from an integral
2655 * exponent.
2656 */
2657static double
2658png_pow10(int power)
2659{
2660 int recip = 0;
2661 double d = 1;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002662
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002663 /* Handle negative exponent with a reciprocal at the end because
2664 * 10 is exact whereas .1 is inexact in base 2
2665 */
2666 if (power < 0)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002667 {
2668 if (power < DBL_MIN_10_EXP) return 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002669 recip = 1, power = -power;
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002670 }
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002671
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002672 if (power > 0)
2673 {
2674 /* Decompose power bitwise. */
2675 double mult = 10;
2676 do
2677 {
2678 if (power & 1) d *= mult;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002679 mult *= mult;
2680 power >>= 1;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002681 }
2682 while (power > 0);
2683
2684 if (recip) d = 1/d;
2685 }
2686 /* else power is 0 and d is 1 */
2687
2688 return d;
2689}
2690
2691/* Function to format a floating point value in ASCII with a given
2692 * precision.
2693 */
2694void /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -06002695png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002696 double fp, unsigned int precision)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002697{
2698 /* We use standard functions from math.h, but not printf because
2699 * that would require stdio. The caller must supply a buffer of
2700 * sufficient size or we will png_error. The tests on size and
2701 * the space in ascii[] consumed are indicated below.
2702 */
2703 if (precision < 1)
2704 precision = DBL_DIG;
2705
2706 /* Enforce the limit of the implementation precision too. */
2707 if (precision > DBL_DIG+1)
2708 precision = DBL_DIG+1;
2709
2710 /* Basic sanity checks */
2711 if (size >= precision+5) /* See the requirements below. */
2712 {
2713 if (fp < 0)
2714 {
2715 fp = -fp;
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05002716 *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002717 --size;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002718 }
2719
2720 if (fp >= DBL_MIN && fp <= DBL_MAX)
2721 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002722 int exp_b10; /* A base 10 exponent */
2723 double base; /* 10^exp_b10 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002724
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002725 /* First extract a base 10 exponent of the number,
2726 * the calculation below rounds down when converting
2727 * from base 2 to base 10 (multiply by log10(2) -
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002728 * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002729 * be increased. Note that the arithmetic shift
2730 * performs a floor() unlike C arithmetic - using a
2731 * C multiply would break the following for negative
2732 * exponents.
2733 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002734 (void)frexp(fp, &exp_b10); /* exponent to base 2 */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002735
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002736 exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002737
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002738 /* Avoid underflow here. */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002739 base = png_pow10(exp_b10); /* May underflow */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002740
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002741 while (base < DBL_MIN || base < fp)
2742 {
2743 /* And this may overflow. */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002744 double test = png_pow10(exp_b10+1);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002745
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002746 if (test <= DBL_MAX)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002747 ++exp_b10, base = test;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002748
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002749 else
2750 break;
2751 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002752
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002753 /* Normalize fp and correct exp_b10, after this fp is in the
2754 * range [.1,1) and exp_b10 is both the exponent and the digit
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002755 * *before* which the decimal point should be inserted
2756 * (starting with 0 for the first digit). Note that this
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002757 * works even if 10^exp_b10 is out of range because of the
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002758 * test on DBL_MAX above.
2759 */
2760 fp /= base;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002761 while (fp >= 1) fp /= 10, ++exp_b10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002762
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002763 /* Because of the code above fp may, at this point, be
2764 * less than .1, this is ok because the code below can
2765 * handle the leading zeros this generates, so no attempt
2766 * is made to correct that here.
2767 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002768
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002769 {
2770 int czero, clead, cdigits;
2771 char exponent[10];
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002772
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002773 /* Allow up to two leading zeros - this will not lengthen
2774 * the number compared to using E-n.
2775 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002776 if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002777 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002778 czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */
2779 exp_b10 = 0; /* Dot added below before first output. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002780 }
2781 else
2782 czero = 0; /* No zeros to add */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002783
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002784 /* Generate the digit list, stripping trailing zeros and
2785 * inserting a '.' before a digit if the exponent is 0.
2786 */
2787 clead = czero; /* Count of leading zeros */
2788 cdigits = 0; /* Count of digits in list. */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002789
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002790 do
2791 {
2792 double d;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002793
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002794 fp *= 10;
2795 /* Use modf here, not floor and subtract, so that
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002796 * the separation is done in one step. At the end
2797 * of the loop don't break the number into parts so
2798 * that the final digit is rounded.
2799 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002800 if (cdigits+czero-clead+1 < (int)precision)
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002801 fp = modf(fp, &d);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002802
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002803 else
2804 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002805 d = floor(fp + .5);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002806
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002807 if (d > 9)
2808 {
2809 /* Rounding up to 10, handle that here. */
2810 if (czero > 0)
2811 {
2812 --czero, d = 1;
2813 if (cdigits == 0) --clead;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002814 }
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002815 else
2816 {
2817 while (cdigits > 0 && d > 9)
2818 {
2819 int ch = *--ascii;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002820
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002821 if (exp_b10 != (-1))
2822 ++exp_b10;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002823
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002824 else if (ch == 46)
2825 {
2826 ch = *--ascii, ++size;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002827 /* Advance exp_b10 to '1', so that the
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002828 * decimal point happens after the
2829 * previous digit.
2830 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002831 exp_b10 = 1;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002832 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002833
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002834 --cdigits;
2835 d = ch - 47; /* I.e. 1+(ch-48) */
2836 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002837
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002838 /* Did we reach the beginning? If so adjust the
2839 * exponent but take into account the leading
2840 * decimal point.
2841 */
2842 if (d > 9) /* cdigits == 0 */
2843 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002844 if (exp_b10 == (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002845 {
2846 /* Leading decimal point (plus zeros?), if
2847 * we lose the decimal point here it must
2848 * be reentered below.
2849 */
2850 int ch = *--ascii;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002851
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002852 if (ch == 46)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002853 ++size, exp_b10 = 1;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002854
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002855 /* Else lost a leading zero, so 'exp_b10' is
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002856 * still ok at (-1)
2857 */
2858 }
2859 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002860 ++exp_b10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002861
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002862 /* In all cases we output a '1' */
2863 d = 1;
2864 }
2865 }
2866 }
2867 fp = 0; /* Guarantees termination below. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002868 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002869
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002870 if (d == 0)
2871 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002872 ++czero;
2873 if (cdigits == 0) ++clead;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002874 }
2875 else
2876 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002877 /* Included embedded zeros in the digit count. */
2878 cdigits += czero - clead;
2879 clead = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002880
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002881 while (czero > 0)
2882 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002883 /* exp_b10 == (-1) means we just output the decimal
2884 * place - after the DP don't adjust 'exp_b10' any
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002885 * more!
2886 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002887 if (exp_b10 != (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002888 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002889 if (exp_b10 == 0) *ascii++ = 46, --size;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002890 /* PLUS 1: TOTAL 4 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002891 --exp_b10;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002892 }
2893 *ascii++ = 48, --czero;
2894 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002895
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002896 if (exp_b10 != (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002897 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002898 if (exp_b10 == 0) *ascii++ = 46, --size; /* counted
2899 above */
2900 --exp_b10;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002901 }
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002902 *ascii++ = (char)(48 + (int)d), ++cdigits;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002903 }
2904 }
2905 while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002906
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002907 /* The total output count (max) is now 4+precision */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002908
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002909 /* Check for an exponent, if we don't need one we are
2910 * done and just need to terminate the string. At
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002911 * this point exp_b10==(-1) is effectively if flag - it got
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002912 * to '-1' because of the decrement after outputing
2913 * the decimal point above (the exponent required is
2914 * *not* -1!)
2915 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002916 if (exp_b10 >= (-1) && exp_b10 <= 2)
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002917 {
2918 /* The following only happens if we didn't output the
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002919 * leading zeros above for negative exponent, so this
2920 * doest add to the digit requirement. Note that the
2921 * two zeros here can only be output if the two leading
2922 * zeros were *not* output, so this doesn't increase
2923 * the output count.
2924 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002925 while (--exp_b10 >= 0) *ascii++ = 48;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002926
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002927 *ascii = 0;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002928
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002929 /* Total buffer requirement (including the '\0') is
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002930 * 5+precision - see check at the start.
2931 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002932 return;
2933 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002934
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002935 /* Here if an exponent is required, adjust size for
2936 * the digits we output but did not count. The total
2937 * digit output here so far is at most 1+precision - no
2938 * decimal point and no leading or trailing zeros have
2939 * been output.
2940 */
2941 size -= cdigits;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002942
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05002943 *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002944
John Bowler75156122011-09-09 17:21:44 -05002945 /* The following use of an unsigned temporary avoids ambiguities in
2946 * the signed arithmetic on exp_b10 and permits GCC at least to do
2947 * better optimization.
2948 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002949 {
John Bowler75156122011-09-09 17:21:44 -05002950 unsigned int uexp_b10;
2951
2952 if (exp_b10 < 0)
2953 {
2954 *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
2955 uexp_b10 = -exp_b10;
2956 }
2957
2958 else
2959 uexp_b10 = exp_b10;
2960
2961 cdigits = 0;
2962
2963 while (uexp_b10 > 0)
2964 {
2965 exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
2966 uexp_b10 /= 10;
2967 }
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002968 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002969
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002970 /* Need another size check here for the exponent digits, so
2971 * this need not be considered above.
2972 */
2973 if ((int)size > cdigits)
2974 {
2975 while (cdigits > 0) *ascii++ = exponent[--cdigits];
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002976
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002977 *ascii = 0;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002978
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002979 return;
2980 }
2981 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002982 }
2983 else if (!(fp >= DBL_MIN))
2984 {
2985 *ascii++ = 48; /* '0' */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002986 *ascii = 0;
2987 return;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002988 }
2989 else
2990 {
2991 *ascii++ = 105; /* 'i' */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002992 *ascii++ = 110; /* 'n' */
2993 *ascii++ = 102; /* 'f' */
2994 *ascii = 0;
2995 return;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002996 }
2997 }
2998
2999 /* Here on buffer too small. */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003000 png_error(png_ptr, "ASCII conversion buffer too small");
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003001}
3002
3003# endif /* FLOATING_POINT */
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003004
3005# ifdef PNG_FIXED_POINT_SUPPORTED
3006/* Function to format a fixed point value in ASCII.
3007 */
3008void /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -06003009png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
3010 png_size_t size, png_fixed_point fp)
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003011{
3012 /* Require space for 10 decimal digits, a decimal point, a minus sign and a
3013 * trailing \0, 13 characters:
3014 */
3015 if (size > 12)
3016 {
3017 png_uint_32 num;
3018
3019 /* Avoid overflow here on the minimum integer. */
3020 if (fp < 0)
3021 *ascii++ = 45, --size, num = -fp;
3022 else
3023 num = fp;
3024
John Bowler75156122011-09-09 17:21:44 -05003025 if (num <= 0x80000000) /* else overflowed */
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003026 {
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05003027 unsigned int ndigits = 0, first = 16 /* flag value */;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003028 char digits[10];
3029
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003030 while (num)
3031 {
3032 /* Split the low digit off num: */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003033 unsigned int tmp = num/10;
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003034 num -= tmp*10;
3035 digits[ndigits++] = (char)(48 + num);
3036 /* Record the first non-zero digit, note that this is a number
3037 * starting at 1, it's not actually the array index.
3038 */
3039 if (first == 16 && num > 0)
3040 first = ndigits;
3041 num = tmp;
3042 }
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003043
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003044 if (ndigits > 0)
3045 {
3046 while (ndigits > 5) *ascii++ = digits[--ndigits];
3047 /* The remaining digits are fractional digits, ndigits is '5' or
3048 * smaller at this point. It is certainly not zero. Check for a
3049 * non-zero fractional digit:
3050 */
3051 if (first <= 5)
3052 {
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003053 unsigned int i;
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003054 *ascii++ = 46; /* decimal point */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05003055 /* ndigits may be <5 for small numbers, output leading zeros
3056 * then ndigits digits to first:
3057 */
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003058 i = 5;
3059 while (ndigits < i) *ascii++ = 48, --i;
3060 while (ndigits >= first) *ascii++ = digits[--ndigits];
3061 /* Don't output the trailing zeros! */
3062 }
3063 }
3064 else
3065 *ascii++ = 48;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003066
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003067 /* And null terminate the string: */
3068 *ascii = 0;
3069 return;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003070 }
3071 }
3072
3073 /* Here on buffer too small. */
3074 png_error(png_ptr, "ASCII conversion buffer too small");
3075}
3076# endif /* FIXED_POINT */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003077#endif /* READ_SCAL */
3078
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05003079#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003080 !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
3081 (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
3082 defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3083 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
3084 (defined(PNG_sCAL_SUPPORTED) && \
3085 defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003086png_fixed_point
John Bowler5d567862011-12-24 09:12:00 -06003087png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003088{
3089 double r = floor(100000 * fp + .5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003090
Glenn Randers-Pehrson77c3bf12011-01-20 15:56:31 -06003091 if (r > 2147483647. || r < -2147483648.)
3092 png_fixed_error(png_ptr, text);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003093
Glenn Randers-Pehrson77c3bf12011-01-20 15:56:31 -06003094 return (png_fixed_point)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003095}
3096#endif
3097
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05003098#if defined(PNG_READ_GAMMA_SUPPORTED) || \
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003099 defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003100/* muldiv functions */
3101/* This API takes signed arguments and rounds the result to the nearest
3102 * integer (or, for a fixed point number - the standard argument - to
3103 * the nearest .00001). Overflow and divide by zero are signalled in
3104 * the result, a boolean - true on success, false on overflow.
3105 */
3106int
3107png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003108 png_int_32 divisor)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003109{
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003110 /* Return a * times / divisor, rounded. */
3111 if (divisor != 0)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003112 {
3113 if (a == 0 || times == 0)
3114 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003115 *res = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003116 return 1;
3117 }
3118 else
3119 {
3120#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003121 double r = a;
3122 r *= times;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003123 r /= divisor;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003124 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003125
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003126 /* A png_fixed_point is a 32-bit integer. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003127 if (r <= 2147483647. && r >= -2147483648.)
3128 {
3129 *res = (png_fixed_point)r;
3130 return 1;
3131 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003132#else
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003133 int negative = 0;
3134 png_uint_32 A, T, D;
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05003135 png_uint_32 s16, s32, s00;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003136
3137 if (a < 0)
3138 negative = 1, A = -a;
3139 else
3140 A = a;
3141
3142 if (times < 0)
3143 negative = !negative, T = -times;
3144 else
3145 T = times;
3146
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003147 if (divisor < 0)
3148 negative = !negative, D = -divisor;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003149 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003150 D = divisor;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003151
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003152 /* Following can't overflow because the arguments only
3153 * have 31 bits each, however the result may be 32 bits.
3154 */
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05003155 s16 = (A >> 16) * (T & 0xffff) +
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05003156 (A & 0xffff) * (T >> 16);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003157 /* Can't overflow because the a*times bit is only 30
3158 * bits at most.
3159 */
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05003160 s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
3161 s00 = (A & 0xffff) * (T & 0xffff);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003162
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003163 s16 = (s16 & 0xffff) << 16;
3164 s00 += s16;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003165
3166 if (s00 < s16)
3167 ++s32; /* carry */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003168
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003169 if (s32 < D) /* else overflow */
3170 {
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003171 /* s32.s00 is now the 64-bit product, do a standard
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003172 * division, we know that s32 < D, so the maximum
3173 * required shift is 31.
3174 */
3175 int bitshift = 32;
3176 png_fixed_point result = 0; /* NOTE: signed */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003177
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003178 while (--bitshift >= 0)
3179 {
3180 png_uint_32 d32, d00;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003181
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003182 if (bitshift > 0)
3183 d32 = D >> (32-bitshift), d00 = D << bitshift;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003184
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003185 else
3186 d32 = 0, d00 = D;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003187
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003188 if (s32 > d32)
3189 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05003190 if (s00 < d00) --s32; /* carry */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003191 s32 -= d32, s00 -= d00, result += 1<<bitshift;
3192 }
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003193
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003194 else
3195 if (s32 == d32 && s00 >= d00)
3196 s32 = 0, s00 -= d00, result += 1<<bitshift;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003197 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003198
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003199 /* Handle the rounding. */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003200 if (s00 >= (D >> 1))
3201 ++result;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003202
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003203 if (negative)
3204 result = -result;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003205
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003206 /* Check for overflow. */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003207 if ((negative && result <= 0) || (!negative && result >= 0))
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003208 {
3209 *res = result;
3210 return 1;
3211 }
3212 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003213#endif
3214 }
3215 }
3216
3217 return 0;
3218}
3219#endif /* READ_GAMMA || INCH_CONVERSIONS */
3220
3221#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
3222/* The following is for when the caller doesn't much care about the
3223 * result.
3224 */
3225png_fixed_point
John Bowler5d567862011-12-24 09:12:00 -06003226png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003227 png_int_32 divisor)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003228{
3229 png_fixed_point result;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003230
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003231 if (png_muldiv(&result, a, times, divisor))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003232 return result;
3233
3234 png_warning(png_ptr, "fixed point overflow ignored");
3235 return 0;
3236}
3237#endif
3238
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003239#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003240/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
3241png_fixed_point
3242png_reciprocal(png_fixed_point a)
3243{
3244#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
3245 double r = floor(1E10/a+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003246
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003247 if (r <= 2147483647. && r >= -2147483648.)
3248 return (png_fixed_point)r;
3249#else
3250 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003251
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003252 if (png_muldiv(&res, 100000, 100000, a))
3253 return res;
3254#endif
3255
3256 return 0; /* error/overflow */
3257}
3258
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003259/* This is the shared test on whether a gamma value is 'significant' - whether
3260 * it is worth doing gamma correction.
3261 */
3262int /* PRIVATE */
3263png_gamma_significant(png_fixed_point gamma_val)
3264{
3265 return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
3266 gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
3267}
3268#endif
3269
3270#ifdef PNG_READ_GAMMA_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003271/* A local convenience routine. */
3272static png_fixed_point
3273png_product2(png_fixed_point a, png_fixed_point b)
3274{
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -05003275 /* The required result is 1/a * 1/b; the following preserves accuracy. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003276#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
3277 double r = a * 1E-5;
3278 r *= b;
3279 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003280
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003281 if (r <= 2147483647. && r >= -2147483648.)
3282 return (png_fixed_point)r;
3283#else
3284 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003285
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003286 if (png_muldiv(&res, a, b, 100000))
3287 return res;
3288#endif
3289
3290 return 0; /* overflow */
3291}
3292
3293/* The inverse of the above. */
3294png_fixed_point
3295png_reciprocal2(png_fixed_point a, png_fixed_point b)
3296{
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -05003297 /* The required result is 1/a * 1/b; the following preserves accuracy. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003298#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
3299 double r = 1E15/a;
3300 r /= b;
3301 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003302
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003303 if (r <= 2147483647. && r >= -2147483648.)
3304 return (png_fixed_point)r;
3305#else
3306 /* This may overflow because the range of png_fixed_point isn't symmetric,
3307 * but this API is only used for the product of file and screen gamma so it
3308 * doesn't matter that the smallest number it can produce is 1/21474, not
3309 * 1/100000
3310 */
3311 png_fixed_point res = png_product2(a, b);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003312
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003313 if (res != 0)
3314 return png_reciprocal(res);
3315#endif
3316
3317 return 0; /* overflow */
3318}
3319#endif /* READ_GAMMA */
3320
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003321#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
3322#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
3323/* Fixed point gamma.
3324 *
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003325 * The code to calculate the tables used below can be found in the shell script
3326 * contrib/tools/intgamma.sh
3327 *
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003328 * To calculate gamma this code implements fast log() and exp() calls using only
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003329 * fixed point arithmetic. This code has sufficient precision for either 8-bit
3330 * or 16-bit sample values.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003331 *
3332 * The tables used here were calculated using simple 'bc' programs, but C double
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003333 * precision floating point arithmetic would work fine.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003334 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003335 * 8-bit log table
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003336 * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003337 * 255, so it's the base 2 logarithm of a normalized 8-bit floating point
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003338 * mantissa. The numbers are 32-bit fractions.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003339 */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003340static const png_uint_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003341png_8bit_l2[128] =
3342{
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003343 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
3344 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
3345 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
3346 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
3347 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
3348 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
3349 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
3350 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
3351 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
3352 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
3353 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
3354 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
3355 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
3356 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
3357 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
3358 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
3359 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
3360 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
3361 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
3362 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
3363 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
3364 24347096U, 0U
Glenn Randers-Pehrson8888ea42011-11-28 11:29:10 -06003365
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003366#if 0
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003367 /* The following are the values for 16-bit tables - these work fine for the
3368 * 8-bit conversions but produce very slightly larger errors in the 16-bit
3369 * log (about 1.2 as opposed to 0.7 absolute error in the final value). To
3370 * use these all the shifts below must be adjusted appropriately.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003371 */
3372 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
3373 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
3374 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
3375 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
3376 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
3377 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
3378 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
3379 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
3380 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
3381 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
3382 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
3383 1119, 744, 372
3384#endif
3385};
3386
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003387static png_int_32
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003388png_log8bit(unsigned int x)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003389{
John Bowler168a4332011-01-16 19:32:22 -06003390 unsigned int lg2 = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003391 /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
3392 * because the log is actually negate that means adding 1. The final
3393 * returned value thus has the range 0 (for 255 input) to 7.994 (for 1
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003394 * input), return -1 for the overflow (log 0) case, - so the result is
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003395 * always at most 19 bits.
3396 */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003397 if ((x &= 0xff) == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003398 return -1;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003399
3400 if ((x & 0xf0) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003401 lg2 = 4, x <<= 4;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003402
3403 if ((x & 0xc0) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003404 lg2 += 2, x <<= 2;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003405
3406 if ((x & 0x80) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003407 lg2 += 1, x <<= 1;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003408
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003409 /* result is at most 19 bits, so this cast is safe: */
John Bowler168a4332011-01-16 19:32:22 -06003410 return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003411}
3412
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003413/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
3414 * for 16-bit images we use the most significant 8 bits of the 16-bit value to
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003415 * get an approximation then multiply the approximation by a correction factor
3416 * determined by the remaining up to 8 bits. This requires an additional step
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003417 * in the 16-bit case.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003418 *
3419 * We want log2(value/65535), we have log2(v'/255), where:
3420 *
3421 * value = v' * 256 + v''
3422 * = v' * f
3423 *
3424 * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
3425 * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003426 * than 258. The final factor also needs to correct for the fact that our 8-bit
3427 * value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003428 *
3429 * This gives a final formula using a calculated value 'x' which is value/v' and
3430 * scaling by 65536 to match the above table:
3431 *
3432 * log2(x/257) * 65536
3433 *
3434 * Since these numbers are so close to '1' we can use simple linear
3435 * interpolation between the two end values 256/257 (result -368.61) and 258/257
3436 * (result 367.179). The values used below are scaled by a further 64 to give
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003437 * 16-bit precision in the interpolation:
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003438 *
3439 * Start (256): -23591
3440 * Zero (257): 0
3441 * End (258): 23499
3442 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003443static png_int_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003444png_log16bit(png_uint_32 x)
3445{
John Bowler168a4332011-01-16 19:32:22 -06003446 unsigned int lg2 = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003447
3448 /* As above, but now the input has 16 bits. */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003449 if ((x &= 0xffff) == 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003450 return -1;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003451
3452 if ((x & 0xff00) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003453 lg2 = 8, x <<= 8;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003454
3455 if ((x & 0xf000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003456 lg2 += 4, x <<= 4;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003457
3458 if ((x & 0xc000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003459 lg2 += 2, x <<= 2;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003460
3461 if ((x & 0x8000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003462 lg2 += 1, x <<= 1;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003463
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003464 /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003465 * value.
3466 */
John Bowler168a4332011-01-16 19:32:22 -06003467 lg2 <<= 28;
3468 lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003469
3470 /* Now we need to interpolate the factor, this requires a division by the top
3471 * 8 bits. Do this with maximum precision.
3472 */
3473 x = ((x << 16) + (x >> 9)) / (x >> 8);
3474
3475 /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
3476 * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
3477 * 16 bits to interpolate to get the low bits of the result. Round the
3478 * answer. Note that the end point values are scaled by 64 to retain overall
John Bowler168a4332011-01-16 19:32:22 -06003479 * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003480 * the overall scaling by 6-12. Round at every step.
3481 */
3482 x -= 1U << 24;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003483
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003484 if (x <= 65536U) /* <= '257' */
John Bowler168a4332011-01-16 19:32:22 -06003485 lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003486
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003487 else
John Bowler168a4332011-01-16 19:32:22 -06003488 lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003489
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003490 /* Safe, because the result can't have more than 20 bits: */
John Bowler168a4332011-01-16 19:32:22 -06003491 return (png_int_32)((lg2 + 2048) >> 12);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003492}
3493
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003494/* The 'exp()' case must invert the above, taking a 20-bit fixed point
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003495 * logarithmic value and returning a 16 or 8-bit number as appropriate. In
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003496 * each case only the low 16 bits are relevant - the fraction - since the
3497 * integer bits (the top 4) simply determine a shift.
3498 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003499 * The worst case is the 16-bit distinction between 65535 and 65534, this
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003500 * requires perhaps spurious accuracty in the decoding of the logarithm to
3501 * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
3502 * of getting this accuracy in practice.
3503 *
3504 * To deal with this the following exp() function works out the exponent of the
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003505 * frational part of the logarithm by using an accurate 32-bit value from the
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003506 * top four fractional bits then multiplying in the remaining bits.
3507 */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003508static const png_uint_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003509png_32bit_exp[16] =
3510{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003511 /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003512 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
3513 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
3514 2553802834U, 2445529972U, 2341847524U, 2242560872U
3515};
3516
3517/* Adjustment table; provided to explain the numbers in the code below. */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003518#if 0
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003519for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
3520 11 44937.64284865548751208448
3521 10 45180.98734845585101160448
3522 9 45303.31936980687359311872
3523 8 45364.65110595323018870784
3524 7 45395.35850361789624614912
3525 6 45410.72259715102037508096
3526 5 45418.40724413220722311168
3527 4 45422.25021786898173001728
3528 3 45424.17186732298419044352
3529 2 45425.13273269940811464704
3530 1 45425.61317555035558641664
3531 0 45425.85339951654943850496
3532#endif
3533
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003534static png_uint_32
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003535png_exp(png_fixed_point x)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003536{
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003537 if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003538 {
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003539 /* Obtain a 4-bit approximation */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003540 png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
3541
3542 /* Incorporate the low 12 bits - these decrease the returned value by
3543 * multiplying by a number less than 1 if the bit is set. The multiplier
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003544 * is determined by the above table and the shift. Notice that the values
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003545 * converge on 45426 and this is used to allow linear interpolation of the
3546 * low bits.
3547 */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003548 if (x & 0x800)
3549 e -= (((e >> 16) * 44938U) + 16U) >> 5;
3550
3551 if (x & 0x400)
3552 e -= (((e >> 16) * 45181U) + 32U) >> 6;
3553
3554 if (x & 0x200)
3555 e -= (((e >> 16) * 45303U) + 64U) >> 7;
3556
3557 if (x & 0x100)
3558 e -= (((e >> 16) * 45365U) + 128U) >> 8;
3559
3560 if (x & 0x080)
3561 e -= (((e >> 16) * 45395U) + 256U) >> 9;
3562
3563 if (x & 0x040)
3564 e -= (((e >> 16) * 45410U) + 512U) >> 10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003565
3566 /* And handle the low 6 bits in a single block. */
3567 e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
3568
3569 /* Handle the upper bits of x. */
3570 e >>= x >> 16;
3571 return e;
3572 }
3573
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003574 /* Check for overflow */
3575 if (x <= 0)
3576 return png_32bit_exp[0];
3577
3578 /* Else underflow */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003579 return 0;
3580}
3581
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003582static png_byte
John Bowler168a4332011-01-16 19:32:22 -06003583png_exp8bit(png_fixed_point lg2)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003584{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003585 /* Get a 32-bit value: */
John Bowler168a4332011-01-16 19:32:22 -06003586 png_uint_32 x = png_exp(lg2);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003587
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003588 /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003589 * second, rounding, step can't overflow because of the first, subtraction,
3590 * step.
3591 */
3592 x -= x >> 8;
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003593 return (png_byte)((x + 0x7fffffU) >> 24);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003594}
3595
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003596static png_uint_16
John Bowler168a4332011-01-16 19:32:22 -06003597png_exp16bit(png_fixed_point lg2)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003598{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003599 /* Get a 32-bit value: */
John Bowler168a4332011-01-16 19:32:22 -06003600 png_uint_32 x = png_exp(lg2);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003601
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003602 /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003603 x -= x >> 16;
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003604 return (png_uint_16)((x + 32767U) >> 16);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003605}
3606#endif /* FLOATING_ARITHMETIC */
3607
3608png_byte
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003609png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003610{
3611 if (value > 0 && value < 255)
3612 {
3613# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003614 double r = floor(255*pow(value/255.,gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003615 return (png_byte)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003616# else
John Bowler168a4332011-01-16 19:32:22 -06003617 png_int_32 lg2 = png_log8bit(value);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003618 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003619
John Bowler168a4332011-01-16 19:32:22 -06003620 if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003621 return png_exp8bit(res);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003622
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003623 /* Overflow. */
3624 value = 0;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003625# endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003626 }
3627
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003628 return (png_byte)value;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003629}
3630
3631png_uint_16
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003632png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003633{
3634 if (value > 0 && value < 65535)
3635 {
3636# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003637 double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003638 return (png_uint_16)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003639# else
John Bowler168a4332011-01-16 19:32:22 -06003640 png_int_32 lg2 = png_log16bit(value);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003641 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003642
John Bowler168a4332011-01-16 19:32:22 -06003643 if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003644 return png_exp16bit(res);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003645
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003646 /* Overflow. */
3647 value = 0;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003648# endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003649 }
3650
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003651 return (png_uint_16)value;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003652}
3653
3654/* This does the right thing based on the bit_depth field of the
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003655 * png_struct, interpreting values as 8-bit or 16-bit. While the result
3656 * is nominally a 16-bit value if bit depth is 8 then the result is
3657 * 8-bit (as are the arguments.)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003658 */
3659png_uint_16 /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06003660png_gamma_correct(png_structrp png_ptr, unsigned int value,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003661 png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003662{
3663 if (png_ptr->bit_depth == 8)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003664 return png_gamma_8bit_correct(value, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003665
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003666 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003667 return png_gamma_16bit_correct(value, gamma_val);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003668}
3669
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003670/* Internal function to build a single 16-bit table - the table consists of
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003671 * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
3672 * to shift the input values right (or 16-number_of_signifiant_bits).
3673 *
Glenn Randers-Pehrsona774c5d2010-08-26 19:37:55 -05003674 * The caller is responsible for ensuring that the table gets cleaned up on
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003675 * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
3676 * should be somewhere that will be cleaned.
3677 */
3678static void
John Bowler5d567862011-12-24 09:12:00 -06003679png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003680 PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003681{
3682 /* Various values derived from 'shift': */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003683 PNG_CONST unsigned int num = 1U << (8U - shift);
3684 PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
3685 PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
3686 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003687
3688 png_uint_16pp table = *ptable =
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003689 (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003690
3691 for (i = 0; i < num; i++)
3692 {
3693 png_uint_16p sub_table = table[i] =
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003694 (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003695
3696 /* The 'threshold' test is repeated here because it can arise for one of
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003697 * the 16-bit tables even if the others don't hit it.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003698 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003699 if (png_gamma_significant(gamma_val))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003700 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003701 /* The old code would overflow at the end and this would cause the
3702 * 'pow' function to return a result >1, resulting in an
3703 * arithmetic error. This code follows the spec exactly; ig is
3704 * the recovered input sample, it always has 8-16 bits.
3705 *
3706 * We want input * 65535/max, rounded, the arithmetic fits in 32
3707 * bits (unsigned) so long as max <= 32767.
3708 */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003709 unsigned int j;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003710 for (j = 0; j < 256; j++)
3711 {
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003712 png_uint_32 ig = (j << (8-shift)) + i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003713# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003714 /* Inline the 'max' scaling operation: */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003715 double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003716 sub_table[j] = (png_uint_16)d;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003717# else
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003718 if (shift)
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05003719 ig = (ig * 65535U + max_by_2)/max;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003720
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003721 sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003722# endif
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003723 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003724 }
3725 else
3726 {
3727 /* We must still build a table, but do it the fast way. */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003728 unsigned int j;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003729
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003730 for (j = 0; j < 256; j++)
3731 {
3732 png_uint_32 ig = (j << (8-shift)) + i;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003733
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003734 if (shift)
3735 ig = (ig * 65535U + max_by_2)/max;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003736
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003737 sub_table[j] = (png_uint_16)ig;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003738 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003739 }
3740 }
3741}
3742
3743/* NOTE: this function expects the *inverse* of the overall gamma transformation
3744 * required.
3745 */
3746static void
John Bowler5d567862011-12-24 09:12:00 -06003747png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003748 PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003749{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003750 PNG_CONST unsigned int num = 1U << (8U - shift);
3751 PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
3752 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003753 png_uint_32 last;
3754
3755 png_uint_16pp table = *ptable =
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003756 (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003757
3758 /* 'num' is the number of tables and also the number of low bits of low
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003759 * bits of the input 16-bit value used to select a table. Each table is
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003760 * itself index by the high 8 bits of the value.
3761 */
3762 for (i = 0; i < num; i++)
3763 table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003764 256 * (sizeof (png_uint_16)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003765
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003766 /* 'gamma_val' is set to the reciprocal of the value calculated above, so
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003767 * pow(out,g) is an *input* value. 'last' is the last input value set.
3768 *
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003769 * In the loop 'i' is used to find output values. Since the output is
3770 * 8-bit there are only 256 possible values. The tables are set up to
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003771 * select the closest possible output value for each input by finding
3772 * the input value at the boundary between each pair of output values
3773 * and filling the table up to that boundary with the lower output
3774 * value.
3775 *
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003776 * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003777 * values the code below uses a 16-bit value in i; the values start at
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003778 * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
3779 * entries are filled with 255). Start i at 128 and fill all 'last'
3780 * table entries <= 'max'
3781 */
3782 last = 0;
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003783 for (i = 0; i < 255; ++i) /* 8-bit output value */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003784 {
3785 /* Find the corresponding maximum input value */
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003786 png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003787
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003788 /* Find the boundary value in 16 bits: */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003789 png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003790
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003791 /* Adjust (round) to (16-shift) bits: */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003792 bound = (bound * max + 32768U)/65535U + 1U;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003793
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003794 while (last < bound)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003795 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003796 table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
3797 last++;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003798 }
3799 }
3800
3801 /* And fill in the final entries. */
3802 while (last < (num << 8))
3803 {
3804 table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
3805 last++;
3806 }
3807}
3808
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003809/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003810 * typically much faster). Note that libpng currently does no sBIT processing
3811 * (apparently contrary to the spec) so a 256 entry table is always generated.
3812 */
3813static void
John Bowler5d567862011-12-24 09:12:00 -06003814png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003815 PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003816{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003817 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003818 png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
3819
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003820 if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++)
3821 table[i] = png_gamma_8bit_correct(i, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003822
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003823 else for (i=0; i<256; ++i)
3824 table[i] = (png_byte)i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003825}
3826
John Bowler07772cb2011-10-14 18:19:47 -05003827/* Used from png_read_destroy and below to release the memory used by the gamma
3828 * tables.
3829 */
3830void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06003831png_destroy_gamma_table(png_structrp png_ptr)
John Bowler07772cb2011-10-14 18:19:47 -05003832{
3833 png_free(png_ptr, png_ptr->gamma_table);
3834 png_ptr->gamma_table = NULL;
3835
3836 if (png_ptr->gamma_16_table != NULL)
3837 {
3838 int i;
3839 int istop = (1 << (8 - png_ptr->gamma_shift));
3840 for (i = 0; i < istop; i++)
3841 {
3842 png_free(png_ptr, png_ptr->gamma_16_table[i]);
3843 }
3844 png_free(png_ptr, png_ptr->gamma_16_table);
3845 png_ptr->gamma_16_table = NULL;
3846 }
3847
3848#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3849 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
3850 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3851 png_free(png_ptr, png_ptr->gamma_from_1);
3852 png_ptr->gamma_from_1 = NULL;
3853 png_free(png_ptr, png_ptr->gamma_to_1);
3854 png_ptr->gamma_to_1 = NULL;
3855
3856 if (png_ptr->gamma_16_from_1 != NULL)
3857 {
3858 int i;
3859 int istop = (1 << (8 - png_ptr->gamma_shift));
3860 for (i = 0; i < istop; i++)
3861 {
3862 png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
3863 }
3864 png_free(png_ptr, png_ptr->gamma_16_from_1);
3865 png_ptr->gamma_16_from_1 = NULL;
3866 }
3867 if (png_ptr->gamma_16_to_1 != NULL)
3868 {
3869 int i;
3870 int istop = (1 << (8 - png_ptr->gamma_shift));
3871 for (i = 0; i < istop; i++)
3872 {
3873 png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
3874 }
3875 png_free(png_ptr, png_ptr->gamma_16_to_1);
3876 png_ptr->gamma_16_to_1 = NULL;
3877 }
3878#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
3879}
3880
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003881/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
3882 * tables, we don't make a full table if we are reducing to 8-bit in
3883 * the future. Note also how the gamma_16 tables are segmented so that
3884 * we don't need to allocate > 64K chunks for a full 16-bit table.
3885 */
3886void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06003887png_build_gamma_table(png_structrp png_ptr, int bit_depth)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003888{
3889 png_debug(1, "in png_build_gamma_table");
3890
John Bowler07772cb2011-10-14 18:19:47 -05003891 /* Remove any existing table; this copes with multiple calls to
3892 * png_read_update_info. The warning is because building the gamma tables
3893 * multiple times is a performance hit - it's harmless but the ability to call
3894 * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible
3895 * to warn if the app introduces such a hit.
3896 */
3897 if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
3898 {
3899 png_warning(png_ptr, "gamma table being rebuilt");
3900 png_destroy_gamma_table(png_ptr);
3901 }
3902
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003903 if (bit_depth <= 8)
3904 {
3905 png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003906 png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003907 png_ptr->screen_gamma) : PNG_FP_1);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003908
3909#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
John Bowlerd273ad22011-05-07 21:00:28 -05003910 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003911 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
John Bowlerd273ad22011-05-07 21:00:28 -05003912 if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003913 {
3914 png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003915 png_reciprocal(png_ptr->colorspace.gamma));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003916
3917 png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003918 png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003919 png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003920 }
John Bowlerd273ad22011-05-07 21:00:28 -05003921#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003922 }
3923 else
3924 {
3925 png_byte shift, sig_bit;
3926
3927 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3928 {
3929 sig_bit = png_ptr->sig_bit.red;
3930
3931 if (png_ptr->sig_bit.green > sig_bit)
3932 sig_bit = png_ptr->sig_bit.green;
3933
3934 if (png_ptr->sig_bit.blue > sig_bit)
3935 sig_bit = png_ptr->sig_bit.blue;
3936 }
3937 else
3938 sig_bit = png_ptr->sig_bit.gray;
3939
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003940 /* 16-bit gamma code uses this equation:
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003941 *
3942 * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
3943 *
3944 * Where 'iv' is the input color value and 'ov' is the output value -
3945 * pow(iv, gamma).
3946 *
3947 * Thus the gamma table consists of up to 256 256 entry tables. The table
3948 * is selected by the (8-gamma_shift) most significant of the low 8 bits of
3949 * the color value then indexed by the upper 8 bits:
3950 *
3951 * table[low bits][high 8 bits]
3952 *
3953 * So the table 'n' corresponds to all those 'iv' of:
3954 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003955 * <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003956 *
3957 */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003958 if (sig_bit > 0 && sig_bit < 16U)
3959 shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003960
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003961 else
3962 shift = 0; /* keep all 16 bits */
3963
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05003964 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003965 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003966 /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
3967 * the significant bits in the *input* when the output will
3968 * eventually be 8 bits. By default it is 11.
3969 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003970 if (shift < (16U - PNG_MAX_GAMMA_8))
3971 shift = (16U - PNG_MAX_GAMMA_8);
3972 }
3973
3974 if (shift > 8U)
3975 shift = 8U; /* Guarantees at least one table! */
3976
3977 png_ptr->gamma_shift = shift;
3978
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003979#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrsonef217b72011-06-15 12:58:27 -05003980 /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
John Bowlerd273ad22011-05-07 21:00:28 -05003981 * PNG_COMPOSE). This effectively smashed the background calculation for
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003982 * 16-bit output because the 8-bit table assumes the result will be reduced
John Bowlerd273ad22011-05-07 21:00:28 -05003983 * to 8 bits.
3984 */
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05003985 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003986#endif
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003987 png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003988 png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003989 png_ptr->screen_gamma) : PNG_FP_1);
3990
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003991#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003992 else
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003993 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06003994 png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003995 png_ptr->screen_gamma) : PNG_FP_1);
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003996#endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003997
3998#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
John Bowlerd273ad22011-05-07 21:00:28 -05003999 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05004000 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
John Bowlerd273ad22011-05-07 21:00:28 -05004001 if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05004002 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05004003 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004004 png_reciprocal(png_ptr->colorspace.gamma));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05004005
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05004006 /* Notice that the '16 from 1' table should be full precision, however
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05004007 * the lookup on this table still uses gamma_shift, so it can't be.
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05004008 * TODO: fix this.
4009 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05004010 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05004011 png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004012 png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05004013 }
John Bowlerd273ad22011-05-07 21:00:28 -05004014#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05004015 }
4016}
4017#endif /* READ_GAMMA */
John Bowler7875d532011-11-07 22:33:49 -06004018
John Bowlerf3728102013-03-04 16:26:31 -06004019/* HARDWARE OPTION SUPPORT */
4020#ifdef PNG_SET_OPTION_SUPPORTED
4021int PNGAPI
4022png_set_option(png_structrp png_ptr, int option, int onoff)
4023{
4024 if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
4025 (option & 1) == 0)
4026 {
4027 int mask = 3 << option;
4028 int setting = (2 + (onoff != 0)) << option;
4029 int current = png_ptr->options;
4030
4031 png_ptr->options = (png_byte)((current & ~mask) | setting);
4032
4033 return (current & mask) >> option;
4034 }
4035
4036 return PNG_OPTION_INVALID;
4037}
4038#endif
4039
John Bowler7875d532011-11-07 22:33:49 -06004040/* sRGB support */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004041#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
4042 defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
John Bowler0a521d32011-11-11 18:14:59 -06004043/* sRGB conversion tables; these are machine generated with the code in
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004044 * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
4045 * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
4046 * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
4047 * The sRGB to linear table is exact (to the nearest 16 bit linear fraction).
4048 * The inverse (linear to sRGB) table has accuracies as follows:
John Bowler0a521d32011-11-11 18:14:59 -06004049 *
4050 * For all possible (255*65535+1) input values:
4051 *
4052 * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
4053 *
4054 * For the input values corresponding to the 65536 16-bit values:
4055 *
4056 * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
4057 *
4058 * In all cases the inexact readings are off by one.
John Bowler7875d532011-11-07 22:33:49 -06004059 */
John Bowler7875d532011-11-07 22:33:49 -06004060
4061#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
4062/* The convert-to-sRGB table is only currently required for read. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004063const png_uint_16 png_sRGB_table[256] =
John Bowler7875d532011-11-07 22:33:49 -06004064{
4065 0,20,40,60,80,99,119,139,
4066 159,179,199,219,241,264,288,313,
4067 340,367,396,427,458,491,526,562,
4068 599,637,677,718,761,805,851,898,
4069 947,997,1048,1101,1156,1212,1270,1330,
4070 1391,1453,1517,1583,1651,1720,1790,1863,
4071 1937,2013,2090,2170,2250,2333,2418,2504,
4072 2592,2681,2773,2866,2961,3058,3157,3258,
4073 3360,3464,3570,3678,3788,3900,4014,4129,
4074 4247,4366,4488,4611,4736,4864,4993,5124,
4075 5257,5392,5530,5669,5810,5953,6099,6246,
4076 6395,6547,6700,6856,7014,7174,7335,7500,
4077 7666,7834,8004,8177,8352,8528,8708,8889,
4078 9072,9258,9445,9635,9828,10022,10219,10417,
4079 10619,10822,11028,11235,11446,11658,11873,12090,
4080 12309,12530,12754,12980,13209,13440,13673,13909,
4081 14146,14387,14629,14874,15122,15371,15623,15878,
4082 16135,16394,16656,16920,17187,17456,17727,18001,
4083 18277,18556,18837,19121,19407,19696,19987,20281,
4084 20577,20876,21177,21481,21787,22096,22407,22721,
4085 23038,23357,23678,24002,24329,24658,24990,25325,
4086 25662,26001,26344,26688,27036,27386,27739,28094,
4087 28452,28813,29176,29542,29911,30282,30656,31033,
4088 31412,31794,32179,32567,32957,33350,33745,34143,
4089 34544,34948,35355,35764,36176,36591,37008,37429,
4090 37852,38278,38706,39138,39572,40009,40449,40891,
4091 41337,41785,42236,42690,43147,43606,44069,44534,
4092 45002,45473,45947,46423,46903,47385,47871,48359,
4093 48850,49344,49841,50341,50844,51349,51858,52369,
4094 52884,53401,53921,54445,54971,55500,56032,56567,
4095 57105,57646,58190,58737,59287,59840,60396,60955,
4096 61517,62082,62650,63221,63795,64372,64952,65535
4097};
John Bowler0a521d32011-11-11 18:14:59 -06004098
John Bowler7875d532011-11-07 22:33:49 -06004099#endif /* simplified read only */
4100
4101/* The base/delta tables are required for both read and write (but currently
4102 * only the simplified versions.)
4103 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004104const png_uint_16 png_sRGB_base[512] =
John Bowler7875d532011-11-07 22:33:49 -06004105{
John Bowler0a521d32011-11-11 18:14:59 -06004106 128,1782,3383,4644,5675,6564,7357,8074,
4107 8732,9346,9921,10463,10977,11466,11935,12384,
4108 12816,13233,13634,14024,14402,14769,15125,15473,
4109 15812,16142,16466,16781,17090,17393,17690,17981,
John Bowler7875d532011-11-07 22:33:49 -06004110 18266,18546,18822,19093,19359,19621,19879,20133,
John Bowler0a521d32011-11-11 18:14:59 -06004111 20383,20630,20873,21113,21349,21583,21813,22041,
4112 22265,22487,22707,22923,23138,23350,23559,23767,
John Bowler7875d532011-11-07 22:33:49 -06004113 23972,24175,24376,24575,24772,24967,25160,25352,
John Bowler0a521d32011-11-11 18:14:59 -06004114 25542,25730,25916,26101,26284,26465,26645,26823,
4115 27000,27176,27350,27523,27695,27865,28034,28201,
John Bowler7875d532011-11-07 22:33:49 -06004116 28368,28533,28697,28860,29021,29182,29341,29500,
John Bowler0a521d32011-11-11 18:14:59 -06004117 29657,29813,29969,30123,30276,30429,30580,30730,
John Bowler7875d532011-11-07 22:33:49 -06004118 30880,31028,31176,31323,31469,31614,31758,31902,
John Bowler0a521d32011-11-11 18:14:59 -06004119 32045,32186,32327,32468,32607,32746,32884,33021,
4120 33158,33294,33429,33564,33697,33831,33963,34095,
4121 34226,34357,34486,34616,34744,34873,35000,35127,
John Bowler7875d532011-11-07 22:33:49 -06004122 35253,35379,35504,35629,35753,35876,35999,36122,
4123 36244,36365,36486,36606,36726,36845,36964,37083,
John Bowler0a521d32011-11-11 18:14:59 -06004124 37201,37318,37435,37551,37668,37783,37898,38013,
John Bowler7875d532011-11-07 22:33:49 -06004125 38127,38241,38354,38467,38580,38692,38803,38915,
John Bowler0a521d32011-11-11 18:14:59 -06004126 39026,39136,39246,39356,39465,39574,39682,39790,
John Bowler7875d532011-11-07 22:33:49 -06004127 39898,40005,40112,40219,40325,40431,40537,40642,
4128 40747,40851,40955,41059,41163,41266,41369,41471,
John Bowler0a521d32011-11-11 18:14:59 -06004129 41573,41675,41777,41878,41979,42079,42179,42279,
4130 42379,42478,42577,42676,42775,42873,42971,43068,
4131 43165,43262,43359,43456,43552,43648,43743,43839,
4132 43934,44028,44123,44217,44311,44405,44499,44592,
4133 44685,44778,44870,44962,45054,45146,45238,45329,
John Bowler7875d532011-11-07 22:33:49 -06004134 45420,45511,45601,45692,45782,45872,45961,46051,
John Bowler0a521d32011-11-11 18:14:59 -06004135 46140,46229,46318,46406,46494,46583,46670,46758,
4136 46846,46933,47020,47107,47193,47280,47366,47452,
4137 47538,47623,47709,47794,47879,47964,48048,48133,
4138 48217,48301,48385,48468,48552,48635,48718,48801,
4139 48884,48966,49048,49131,49213,49294,49376,49458,
4140 49539,49620,49701,49782,49862,49943,50023,50103,
4141 50183,50263,50342,50422,50501,50580,50659,50738,
4142 50816,50895,50973,51051,51129,51207,51285,51362,
4143 51439,51517,51594,51671,51747,51824,51900,51977,
4144 52053,52129,52205,52280,52356,52432,52507,52582,
John Bowler7875d532011-11-07 22:33:49 -06004145 52657,52732,52807,52881,52956,53030,53104,53178,
John Bowler0a521d32011-11-11 18:14:59 -06004146 53252,53326,53400,53473,53546,53620,53693,53766,
John Bowler7875d532011-11-07 22:33:49 -06004147 53839,53911,53984,54056,54129,54201,54273,54345,
4148 54417,54489,54560,54632,54703,54774,54845,54916,
John Bowler0a521d32011-11-11 18:14:59 -06004149 54987,55058,55129,55199,55269,55340,55410,55480,
4150 55550,55620,55689,55759,55828,55898,55967,56036,
4151 56105,56174,56243,56311,56380,56448,56517,56585,
John Bowler7875d532011-11-07 22:33:49 -06004152 56653,56721,56789,56857,56924,56992,57059,57127,
4153 57194,57261,57328,57395,57462,57529,57595,57662,
4154 57728,57795,57861,57927,57993,58059,58125,58191,
4155 58256,58322,58387,58453,58518,58583,58648,58713,
4156 58778,58843,58908,58972,59037,59101,59165,59230,
4157 59294,59358,59422,59486,59549,59613,59677,59740,
4158 59804,59867,59930,59993,60056,60119,60182,60245,
4159 60308,60370,60433,60495,60558,60620,60682,60744,
4160 60806,60868,60930,60992,61054,61115,61177,61238,
4161 61300,61361,61422,61483,61544,61605,61666,61727,
John Bowler0a521d32011-11-11 18:14:59 -06004162 61788,61848,61909,61969,62030,62090,62150,62211,
John Bowler7875d532011-11-07 22:33:49 -06004163 62271,62331,62391,62450,62510,62570,62630,62689,
4164 62749,62808,62867,62927,62986,63045,63104,63163,
John Bowler0a521d32011-11-11 18:14:59 -06004165 63222,63281,63340,63398,63457,63515,63574,63632,
John Bowler7875d532011-11-07 22:33:49 -06004166 63691,63749,63807,63865,63923,63981,64039,64097,
John Bowler0a521d32011-11-11 18:14:59 -06004167 64155,64212,64270,64328,64385,64443,64500,64557,
4168 64614,64672,64729,64786,64843,64900,64956,65013,
4169 65070,65126,65183,65239,65296,65352,65409,65465
John Bowler7875d532011-11-07 22:33:49 -06004170};
4171
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004172const png_byte png_sRGB_delta[512] =
John Bowler7875d532011-11-07 22:33:49 -06004173{
John Bowler0a521d32011-11-11 18:14:59 -06004174 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
John Bowler7875d532011-11-07 22:33:49 -06004175 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
4176 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
John Bowler0a521d32011-11-11 18:14:59 -06004177 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
John Bowler7875d532011-11-07 22:33:49 -06004178 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
4179 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
4180 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
4181 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
4182 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
4183 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
4184 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
4185 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
4186 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
4187 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
4188 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
4189 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
4190 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
4191 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
4192 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
4193 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4194 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4195 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4196 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4197 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4198 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4199 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4200 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4201 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4202 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
4203 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
4204 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
4205 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
4206};
John Bowler7875d532011-11-07 22:33:49 -06004207#endif /* SIMPLIFIED READ/WRITE sRGB support */
4208
4209/* SIMPLIFIED READ/WRITE SUPPORT */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004210#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
4211 defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
John Bowler7875d532011-11-07 22:33:49 -06004212static int
4213png_image_free_function(png_voidp argument)
4214{
John Bowler4fa96a42011-11-16 16:39:16 -06004215 png_imagep image = png_voidcast(png_imagep, argument);
John Bowler7875d532011-11-07 22:33:49 -06004216 png_controlp cp = image->opaque;
4217 png_control c;
4218
4219 /* Double check that we have a png_ptr - it should be impossible to get here
4220 * without one.
4221 */
4222 if (cp->png_ptr == NULL)
4223 return 0;
4224
4225 /* First free any data held in the control structure. */
4226# ifdef PNG_STDIO_SUPPORTED
4227 if (cp->owned_file)
4228 {
John Bowler4fa96a42011-11-16 16:39:16 -06004229 FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
John Bowler7875d532011-11-07 22:33:49 -06004230 cp->owned_file = 0;
4231
4232 /* Ignore errors here. */
4233 if (fp != NULL)
4234 {
4235 cp->png_ptr->io_ptr = NULL;
4236 (void)fclose(fp);
4237 }
4238 }
4239# endif
4240
4241 /* Copy the control structure so that the original, allocated, version can be
4242 * safely freed. Notice that a png_error here stops the remainder of the
4243 * cleanup, but this is probably fine because that would indicate bad memory
4244 * problems anyway.
4245 */
4246 c = *cp;
4247 image->opaque = &c;
4248 png_free(c.png_ptr, cp);
4249
4250 /* Then the structures, calling the correct API. */
4251 if (c.for_write)
4252 {
4253# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
4254 png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
4255# else
4256 png_error(c.png_ptr, "simplified write not supported");
4257# endif
4258 }
4259 else
4260 {
4261# ifdef PNG_SIMPLIFIED_READ_SUPPORTED
4262 png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
4263# else
4264 png_error(c.png_ptr, "simplified read not supported");
4265# endif
4266 }
4267
4268 /* Success. */
4269 return 1;
4270}
4271
4272void PNGAPI
4273png_image_free(png_imagep image)
4274{
4275 /* Safely call the real function, but only if doing so is safe at this point
4276 * (if not inside an error handling context). Otherwise assume
4277 * png_safe_execute will call this API after the return.
4278 */
4279 if (image != NULL && image->opaque != NULL &&
4280 image->opaque->error_buf == NULL)
4281 {
4282 /* Ignore errors here: */
4283 (void)png_safe_execute(image, png_image_free_function, image);
4284 image->opaque = NULL;
4285 }
4286}
4287
4288int /* PRIVATE */
4289png_image_error(png_imagep image, png_const_charp error_message)
4290{
4291 /* Utility to log an error. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06004292 png_safecat(image->message, (sizeof image->message), 0, error_message);
4293 image->warning_or_error |= PNG_IMAGE_ERROR;
John Bowler7875d532011-11-07 22:33:49 -06004294 png_image_free(image);
4295 return 0;
4296}
4297
4298#endif /* SIMPLIFIED READ/WRITE */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05004299#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */