blob: a9996b7b6a94e9744903be7696a20d32ee336466 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002/* png.c - location for general purpose libpng functions
3 *
Glenn Randers-Pehrson13831bc2011-12-21 08:28:28 -06004 * Last changed in libpng 1.6.0 [(PENDING RELEASE)]
Glenn Randers-Pehrson1531bd62012-01-01 14:45:04 -06005 * Copyright (c) 1998-2012 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-Pehrson34491692012-02-03 01:58:20 -060017typedef png_libpng_version_1_6_0beta11 Your_png_h_is_not_version_1_6_0beta11;
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-Pehrson145f5c82008-07-10 09:13:13 -050065 return ((int)(png_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-Pehrsonbb5cb142011-09-22 12:41:58 -0500118 if (PNG_CHUNK_ANCILLIARY(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
John Bowlerf3f7e142011-09-09 07:32:37 -0500131 /* 'uLong' is defined as unsigned long, this means that on some systems it is
132 * a 64 bit value. crc32, however, returns 32 bits so the following cast is
133 * safe. 'uInt' may be no more than 16 bits, so it is necessary to perform a
134 * loop here.
135 */
136 if (need_crc && length > 0)
137 {
138 uLong crc = png_ptr->crc; /* Should never issue a warning */
139
140 do
141 {
142 uInt safeLength = (uInt)length;
143 if (safeLength == 0)
144 safeLength = (uInt)-1; /* evil, but safe */
145
146 crc = crc32(crc, ptr, safeLength);
147
148 /* The following should never issue compiler warnings, if they do the
149 * target system has characteristics that will probably violate other
150 * assumptions within the libpng code.
151 */
152 ptr += safeLength;
153 length -= safeLength;
154 }
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
163 * functions that create a png_struct
164 */
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
187 * only check the first digit.
188 */
189 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
190 (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
191 (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
192 {
193#ifdef PNG_WARNINGS_SUPPORTED
194 size_t pos = 0;
195 char m[128];
196
197 pos = png_safecat(m, sizeof m, pos, "Application built with libpng-");
198 pos = png_safecat(m, sizeof m, pos, user_png_ver);
199 pos = png_safecat(m, sizeof m, pos, " but running with ");
200 pos = png_safecat(m, sizeof m, pos, png_libpng_ver);
201
202 png_warning(png_ptr, m);
203#endif
204
205#ifdef PNG_ERROR_NUMBERS_SUPPORTED
206 png_ptr->flags = 0;
207#endif
208
209 return 0;
210 }
211 }
212
213 /* Success return. */
214 return 1;
215}
216
John Bowlerd332c672011-12-21 17:36:12 -0600217/* Generic function to create a png_struct for either read or write - this
218 * contains the common initialization.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600219 */
John Bowlerd332c672011-12-21 17:36:12 -0600220PNG_FUNCTION(png_structp /* PRIVATE */,
221png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
222 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
223 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
224{
225 png_struct create_struct;
226# ifdef PNG_SETJMP_SUPPORTED
227 jmp_buf create_jmp_buf;
228# endif
229
230 /* This temporary stack-allocated structure is used to provide a place to
231 * build enough context to allow the user provided memory allocator (if any)
232 * to be called.
233 */
234 png_memset(&create_struct, 0, sizeof create_struct);
235
236 /* Added at libpng-1.2.6 */
237# ifdef PNG_USER_LIMITS_SUPPORTED
238 create_struct.user_width_max = PNG_USER_WIDTH_MAX;
239 create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
240
241# ifdef PNG_USER_CHUNK_CACHE_MAX
242 /* Added at libpng-1.2.43 and 1.4.0 */
243 create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
244# endif
245
246# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
247 /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
248 * in png_struct regardless.
249 */
250 create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
251# endif
252# endif
253
254 /* The following two API calls simply set fields in png_struct, so it is safe
255 * to do them now even though error handling is not yet set up.
256 */
257# ifdef PNG_USER_MEM_SUPPORTED
258 png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
259# endif
260
261 /* (*error_fn) can return control to the caller after the error_ptr is set,
262 * this will result in a memory leak unless the error_fn does something
263 * extremely sophisticated. The design lacks merit but is implicit in the
264 * API.
265 */
266 png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
267
268# ifdef PNG_SETJMP_SUPPORTED
269 if (!setjmp(create_jmp_buf))
270 {
271 /* Temporarily fake out the longjmp information until we have
272 * successfully completed this function. This only works if we have
273 * setjmp() support compiled in, but it is safe - this stuff should
274 * never happen.
275 */
276 create_struct.jmp_buf_ptr = &create_jmp_buf;
277 create_struct.jmp_buf_size = 0; /*stack allocation*/
278 create_struct.longjmp_fn = longjmp;
279# else
280 {
281# endif
282 /* Call the general version checker (shared with read and write code):
283 */
284 if (png_user_version_check(&create_struct, user_png_ver))
285 {
286
287 /* TODO: delay initializing the zlib structure until it really is
288 * needed.
289 */
290 /* Initialize zbuf - compression/decompression buffer */
291 create_struct.zbuf_size = PNG_ZBUF_SIZE;
292 create_struct.zbuf = png_voidcast(png_bytep,
293 png_malloc_warn(&create_struct, create_struct.zbuf_size));
294
295 /* Finally allocate the png_struct itself. */
296 if (create_struct.zbuf != NULL)
297 {
John Bowler5d567862011-12-24 09:12:00 -0600298 png_structrp png_ptr = png_voidcast(png_structrp,
John Bowlerd332c672011-12-21 17:36:12 -0600299 png_malloc_warn(&create_struct, sizeof *png_ptr));
300
301 if (png_ptr != NULL)
302 {
303# ifdef PNG_SETJMP_SUPPORTED
304 /* Eliminate the local error handling: */
305 create_struct.jmp_buf_ptr = NULL;
306 create_struct.jmp_buf_size = 0;
307 create_struct.longjmp_fn = 0;
308# endif
309
310 *png_ptr = create_struct;
311
312 /* This is the successful return point */
313 return png_ptr;
314 }
315 }
316 }
317 }
318
319 /* A longjmp because of a bug in the application storage allocator or a
320 * simple failure to allocate the png_struct.
321 */
322 if (create_struct.zbuf != NULL)
323 {
324 png_bytep zbuf = create_struct.zbuf;
325
326 /* Ensure we don't keep on returning to this point: */
327 create_struct.zbuf = NULL;
328 png_free(&create_struct, zbuf);
329 }
330
331 return NULL;
332}
333
334/* Allocate the memory for an info_struct for the application. */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -0500335PNG_FUNCTION(png_infop,PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600336png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500337{
John Bowler5d567862011-12-24 09:12:00 -0600338 png_inforp info_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500339
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500340 png_debug(1, "in png_create_info_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500341
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500342 if (png_ptr == NULL)
John Bowlerd332c672011-12-21 17:36:12 -0600343 return NULL;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500344
John Bowlerd332c672011-12-21 17:36:12 -0600345 /* Use the internal API that does not (or at least should not) error out, so
346 * that this call always returns ok. The application typically sets up the
347 * error handling *after* creating the info_struct because this is the way it
348 * has always been done in 'example.c'.
349 */
John Bowler5d567862011-12-24 09:12:00 -0600350 info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
John Bowlerd332c672011-12-21 17:36:12 -0600351 sizeof *info_ptr));
352
Glenn Randers-Pehrson5cded0b2001-11-07 07:10:08 -0600353 if (info_ptr != NULL)
John Bowlerd332c672011-12-21 17:36:12 -0600354 png_memset(info_ptr, 0, sizeof *info_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500355
John Bowlerd332c672011-12-21 17:36:12 -0600356 return info_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500357}
358
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600359/* This function frees the memory associated with a single info struct.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600360 * Normally, one would use either png_destroy_read_struct() or
361 * png_destroy_write_struct() to free an info struct, but this may be
John Bowlerd332c672011-12-21 17:36:12 -0600362 * useful for some applications. From libpng 1.6.0 this function is also used
363 * internally to implement the png_info release part of the 'struct' destroy
364 * APIs. This ensures that all possible approaches free the same data (all of
365 * it).
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600366 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500367void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600368png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600369{
John Bowler5d567862011-12-24 09:12:00 -0600370 png_inforp info_ptr = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600371
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500372 png_debug(1, "in png_destroy_info_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500373
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500374 if (png_ptr == NULL)
375 return;
376
Andreas Dilger47a0c421997-05-16 02:46:07 -0500377 if (info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600378 info_ptr = *info_ptr_ptr;
379
Andreas Dilger47a0c421997-05-16 02:46:07 -0500380 if (info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600381 {
John Bowlerd332c672011-12-21 17:36:12 -0600382 /* Do this first in case of an error below; if the app implements its own
383 * memory management this can lead to png_free calling png_error, which
384 * will abort this routine and return control to the app error handler.
385 * An infinite loop may result if it then tries to free the same info
386 * ptr.
387 */
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -0500388 *info_ptr_ptr = NULL;
John Bowlerd332c672011-12-21 17:36:12 -0600389
John Bowlerdf477e42011-12-24 07:47:02 -0600390 png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
391 png_memset(info_ptr, 0, sizeof *info_ptr);
John Bowlerd332c672011-12-21 17:36:12 -0600392 png_free(png_ptr, info_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600393 }
394}
395
396/* Initialize the info structure. This is now an internal function (0.89)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600397 * and applications using it are urged to use png_create_info_struct()
John Bowlerd332c672011-12-21 17:36:12 -0600398 * instead. Use deprecated in 1.6.0, internal use removed (used internally it
399 * is just a memset).
400 *
401 * NOTE: it is almost inconceivable that this API is used because it bypasses
402 * the user-memory mechanism and the user error handling/warning mechanisms in
403 * those cases where it does anything other than a memset.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600404 */
John Bowlerd332c672011-12-21 17:36:12 -0600405PNG_FUNCTION(void,PNGAPI
406png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
407 PNG_DEPRECATED)
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500408{
John Bowler5d567862011-12-24 09:12:00 -0600409 png_inforp info_ptr = *ptr_ptr;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500410
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500411 png_debug(1, "in png_info_init_3");
412
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500413 if (info_ptr == NULL)
414 return;
Glenn Randers-Pehrson6b12c082006-11-14 10:53:30 -0600415
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500416 if (png_sizeof(png_info) > png_info_struct_size)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500417 {
John Bowlerd332c672011-12-21 17:36:12 -0600418 *ptr_ptr = NULL;
419 /* The following line is why this API should not be used: */
420 free(info_ptr);
John Bowler5d567862011-12-24 09:12:00 -0600421 info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
John Bowlerd332c672011-12-21 17:36:12 -0600422 sizeof *info_ptr));
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500423 *ptr_ptr = info_ptr;
424 }
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500425
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500426 /* Set everything to 0 */
John Bowlerd332c672011-12-21 17:36:12 -0600427 png_memset(info_ptr, 0, sizeof *info_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600428}
429
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500430void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600431png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500432 int freer, png_uint_32 mask)
433{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500434 png_debug(1, "in png_data_freer");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500435
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500436 if (png_ptr == NULL || info_ptr == NULL)
437 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500438
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500439 if (freer == PNG_DESTROY_WILL_FREE_DATA)
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500440 info_ptr->free_me |= mask;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500441
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500442 else if (freer == PNG_USER_WILL_FREE_DATA)
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500443 info_ptr->free_me &= ~mask;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500444
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500445 else
446 png_warning(png_ptr,
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500447 "Unknown freer parameter in png_data_freer");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500448}
449
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500450void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600451png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500452 int num)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600453{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500454 png_debug(1, "in png_free_data");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500455
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600456 if (png_ptr == NULL || info_ptr == NULL)
457 return;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600458
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500459#ifdef PNG_TEXT_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500460 /* Free text item num or (if num == -1) all text items */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500461 if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600462 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500463 if (num != -1)
464 {
465 if (info_ptr->text && info_ptr->text[num].key)
466 {
467 png_free(png_ptr, info_ptr->text[num].key);
468 info_ptr->text[num].key = NULL;
469 }
470 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500471
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500472 else
473 {
474 int i;
475 for (i = 0; i < info_ptr->num_text; i++)
476 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
477 png_free(png_ptr, info_ptr->text);
478 info_ptr->text = NULL;
479 info_ptr->num_text=0;
480 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600481 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600482#endif
483
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500484#ifdef PNG_tRNS_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500485 /* Free any tRNS entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500486 if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500487 {
Glenn Randers-Pehrson6abea752009-08-08 16:52:06 -0500488 png_free(png_ptr, info_ptr->trans_alpha);
489 info_ptr->trans_alpha = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500490 info_ptr->valid &= ~PNG_INFO_tRNS;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500491 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600492#endif
493
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500494#ifdef PNG_sCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500495 /* Free any sCAL entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500496 if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500497 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500498 png_free(png_ptr, info_ptr->scal_s_width);
499 png_free(png_ptr, info_ptr->scal_s_height);
500 info_ptr->scal_s_width = NULL;
501 info_ptr->scal_s_height = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500502 info_ptr->valid &= ~PNG_INFO_sCAL;
503 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600504#endif
505
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500506#ifdef PNG_pCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500507 /* Free any pCAL entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500508 if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500509 {
510 png_free(png_ptr, info_ptr->pcal_purpose);
511 png_free(png_ptr, info_ptr->pcal_units);
512 info_ptr->pcal_purpose = NULL;
513 info_ptr->pcal_units = NULL;
514 if (info_ptr->pcal_params != NULL)
515 {
516 int i;
517 for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
518 {
519 png_free(png_ptr, info_ptr->pcal_params[i]);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600520 info_ptr->pcal_params[i] = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500521 }
522 png_free(png_ptr, info_ptr->pcal_params);
523 info_ptr->pcal_params = NULL;
524 }
525 info_ptr->valid &= ~PNG_INFO_pCAL;
526 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600527#endif
528
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500529#ifdef PNG_iCCP_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500530 /* Free any iCCP entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500531 if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500532 {
533 png_free(png_ptr, info_ptr->iccp_name);
534 png_free(png_ptr, info_ptr->iccp_profile);
535 info_ptr->iccp_name = NULL;
536 info_ptr->iccp_profile = NULL;
537 info_ptr->valid &= ~PNG_INFO_iCCP;
538 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600539#endif
540
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500541#ifdef PNG_sPLT_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500542 /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500543 if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600544 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500545 if (num != -1)
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500546 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500547 if (info_ptr->splt_palettes)
548 {
549 png_free(png_ptr, info_ptr->splt_palettes[num].name);
550 png_free(png_ptr, info_ptr->splt_palettes[num].entries);
551 info_ptr->splt_palettes[num].name = NULL;
552 info_ptr->splt_palettes[num].entries = NULL;
553 }
554 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500555
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500556 else
557 {
558 if (info_ptr->splt_palettes_num)
559 {
560 int i;
561 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
562 png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
563
564 png_free(png_ptr, info_ptr->splt_palettes);
565 info_ptr->splt_palettes = NULL;
566 info_ptr->splt_palettes_num = 0;
567 }
568 info_ptr->valid &= ~PNG_INFO_sPLT;
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500569 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600570 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600571#endif
572
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500573#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500574 if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600575 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500576 if (num != -1)
577 {
578 if (info_ptr->unknown_chunks)
579 {
580 png_free(png_ptr, info_ptr->unknown_chunks[num].data);
581 info_ptr->unknown_chunks[num].data = NULL;
582 }
583 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500584
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500585 else
586 {
587 int i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600588
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500589 if (info_ptr->unknown_chunks_num)
590 {
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -0500591 for (i = 0; i < info_ptr->unknown_chunks_num; i++)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500592 png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600593
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500594 png_free(png_ptr, info_ptr->unknown_chunks);
595 info_ptr->unknown_chunks = NULL;
596 info_ptr->unknown_chunks_num = 0;
597 }
598 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600599 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600600#endif
601
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500602#ifdef PNG_hIST_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500603 /* Free any hIST entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500604 if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500605 {
606 png_free(png_ptr, info_ptr->hist);
607 info_ptr->hist = NULL;
608 info_ptr->valid &= ~PNG_INFO_hIST;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500609 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600610#endif
611
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500612 /* Free any PLTE entry that was internally allocated */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500613 if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500614 {
John Bowler40b26032011-12-22 08:09:15 -0600615 png_free(png_ptr, info_ptr->palette);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500616 info_ptr->palette = NULL;
617 info_ptr->valid &= ~PNG_INFO_PLTE;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500618 info_ptr->num_palette = 0;
619 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600620
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500621#ifdef PNG_INFO_IMAGE_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500622 /* Free any image bits attached to the info structure */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500623 if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500624 {
625 if (info_ptr->row_pointers)
626 {
627 int row;
628 for (row = 0; row < (int)info_ptr->height; row++)
629 {
630 png_free(png_ptr, info_ptr->row_pointers[row]);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600631 info_ptr->row_pointers[row] = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500632 }
633 png_free(png_ptr, info_ptr->row_pointers);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600634 info_ptr->row_pointers = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500635 }
636 info_ptr->valid &= ~PNG_INFO_IDAT;
637 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600638#endif
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500639
John Bowler56a739b2010-12-19 16:33:20 -0600640 if (num != -1)
641 mask &= ~PNG_FREE_MUL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500642
John Bowler56a739b2010-12-19 16:33:20 -0600643 info_ptr->free_me &= ~mask;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600644}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600645#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500646
Guy Schalnate5a37791996-06-05 15:50:50 -0500647/* This function returns a pointer to the io_ptr associated with the user
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600648 * functions. The application should free any memory associated with this
649 * pointer before png_write_destroy() or png_read_destroy() are called.
650 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500651png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600652png_get_io_ptr(png_const_structrp png_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500653{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500654 if (png_ptr == NULL)
655 return (NULL);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500656
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600657 return (png_ptr->io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500658}
Andreas Dilger47a0c421997-05-16 02:46:07 -0500659
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600660#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600661# ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500662/* Initialize the default input/output functions for the PNG file. If you
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600663 * use your own read or write routines, you can call either png_set_read_fn()
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500664 * or png_set_write_fn() instead of png_init_io(). If you have defined
Glenn Randers-Pehrsonce775cc2011-07-13 06:28:26 -0500665 * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
666 * function of your own because "FILE *" isn't necessarily available.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600667 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500668void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600669png_init_io(png_structrp png_ptr, png_FILE_p fp)
Guy Schalnate5a37791996-06-05 15:50:50 -0500670{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500671 png_debug(1, "in png_init_io");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500672
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500673 if (png_ptr == NULL)
674 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500675
Guy Schalnate5a37791996-06-05 15:50:50 -0500676 png_ptr->io_ptr = (png_voidp)fp;
677}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600678# endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500679
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600680# ifdef PNG_TIME_RFC1123_SUPPORTED
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500681/* Convert the supplied time into an RFC 1123 string suitable for use in
682 * a "Creation Time" or other text-based time string.
683 */
John Bowler40b26032011-12-22 08:09:15 -0600684int PNGAPI
685png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500686{
687 static PNG_CONST char short_months[12][4] =
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600688 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
689 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500690
John Bowler40b26032011-12-22 08:09:15 -0600691 if (out == NULL)
692 return 0;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500693
Glenn Randers-Pehrson925a6022011-11-19 18:04:01 -0600694 if (ptime->year > 9999 /* RFC1123 limitation */ ||
695 ptime->month == 0 || ptime->month > 12 ||
696 ptime->day == 0 || ptime->day > 31 ||
697 ptime->hour > 23 || ptime->minute > 59 ||
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600698 ptime->second > 60)
John Bowler40b26032011-12-22 08:09:15 -0600699 return 0;
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600700
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500701 {
John Bowler88b77cc2011-05-05 06:49:55 -0500702 size_t pos = 0;
Glenn Randers-Pehrson925a6022011-11-19 18:04:01 -0600703 char number_buf[5]; /* enough for a four-digit year */
John Bowler88b77cc2011-05-05 06:49:55 -0500704
John Bowler40b26032011-12-22 08:09:15 -0600705# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
John Bowler88b77cc2011-05-05 06:49:55 -0500706# define APPEND_NUMBER(format, value)\
707 APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
John Bowler40b26032011-12-22 08:09:15 -0600708# define APPEND(ch) if (pos < 28) out[pos++] = (ch)
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500709
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600710 APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
John Bowler88b77cc2011-05-05 06:49:55 -0500711 APPEND(' ');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600712 APPEND_STRING(short_months[(ptime->month - 1)]);
John Bowler88b77cc2011-05-05 06:49:55 -0500713 APPEND(' ');
714 APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
715 APPEND(' ');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600716 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
John Bowler88b77cc2011-05-05 06:49:55 -0500717 APPEND(':');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600718 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
John Bowler88b77cc2011-05-05 06:49:55 -0500719 APPEND(':');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600720 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
John Bowler88b77cc2011-05-05 06:49:55 -0500721 APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
722
723# undef APPEND
724# undef APPEND_NUMBER
725# undef APPEND_STRING
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500726 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500727
John Bowler40b26032011-12-22 08:09:15 -0600728 return 1;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500729}
John Bowler40b26032011-12-22 08:09:15 -0600730
731# if PNG_LIBPNG_VER < 10700
732/* Original API that uses a private buffer in png_struct.
733 * TODO: deprecate this, it causes png_struct to carry a spurious temporary
734 * buffer (png_struct::time_buffer), better to have the caller pass this in.
735 */
736png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600737png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
John Bowler40b26032011-12-22 08:09:15 -0600738{
739 if (png_ptr != NULL)
740 {
741 /* The only failure above if png_ptr != NULL is from an invalid ptime */
742 if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime))
743 png_warning(png_ptr, "Ignoring invalid time value");
744
745 else
746 return png_ptr->time_buffer;
747 }
748
749 return NULL;
750}
751# endif
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600752# endif /* PNG_TIME_RFC1123_SUPPORTED */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600753
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600754#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600755
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500756png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600757png_get_copyright(png_const_structrp png_ptr)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600758{
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600759 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500760#ifdef PNG_STRING_COPYRIGHT
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600761 return PNG_STRING_COPYRIGHT
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500762#else
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600763# ifdef __STDC__
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500764 return PNG_STRING_NEWLINE \
Glenn Randers-Pehrson5578c372012-02-04 10:31:38 -0600765 "libpng version 1.6.0beta11 - February 4, 2012" PNG_STRING_NEWLINE \
Glenn Randers-Pehrson1531bd62012-01-01 14:45:04 -0600766 "Copyright (c) 1998-2012 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
Glenn Randers-Pehrson43aaf6e2008-08-05 22:17:03 -0500767 "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
768 "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500769 PNG_STRING_NEWLINE;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600770# else
Glenn Randers-Pehrson5578c372012-02-04 10:31:38 -0600771 return "libpng version 1.6.0beta11 - February 4, 2012\
Glenn Randers-Pehrson1531bd62012-01-01 14:45:04 -0600772 Copyright (c) 1998-2012 Glenn Randers-Pehrson\
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500773 Copyright (c) 1996-1997 Andreas Dilger\
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500774 Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600775# endif
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500776#endif
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600777}
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -0500778
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600779/* The following return the library version as a short string in the
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500780 * format 1.0.0 through 99.99.99zz. To get the version of *.h files
781 * used with your application, print out PNG_LIBPNG_VER_STRING, which
782 * is defined in png.h.
783 * Note: now there is no difference between png_get_libpng_ver() and
784 * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
785 * it is guaranteed that png.c uses the correct version of png.h.
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600786 */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500787png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600788png_get_libpng_ver(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600789{
790 /* Version of *.c files used when building libpng */
Glenn Randers-Pehrson4c8f7262010-03-16 19:30:01 -0500791 return png_get_header_ver(png_ptr);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600792}
793
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500794png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600795png_get_header_ver(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600796{
797 /* Version of *.h files used when building libpng */
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600798 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500799 return PNG_LIBPNG_VER_STRING;
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600800}
801
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500802png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600803png_get_header_version(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600804{
805 /* Returns longer string containing both version and date */
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600806 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500807#ifdef __STDC__
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500808 return PNG_HEADER_VERSION_STRING
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600809# ifndef PNG_READ_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500810 " (NO READ SUPPORT)"
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600811# endif
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500812 PNG_STRING_NEWLINE;
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500813#else
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500814 return PNG_HEADER_VERSION_STRING;
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500815#endif
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600816}
817
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500818#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrsonc1bfe682002-03-06 22:08:00 -0600819int PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600820png_handle_as_unknown(png_structrp png_ptr, png_const_bytep chunk_name)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600821{
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500822 /* Check chunk_name and return "keep" value if it's on the list, else 0 */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500823 png_const_bytep p, p_end;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500824
John Bowlerfcd301d2011-12-28 21:34:27 -0600825 if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500826 return PNG_HANDLE_CHUNK_AS_DEFAULT;
827
828 p_end = png_ptr->chunk_list;
829 p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
830
831 /* The code is the fifth byte after each four byte string. Historically this
832 * code was always searched from the end of the list, so it should continue
833 * to do so in case there are duplicated entries.
834 */
835 do /* num_chunk_list > 0, so at least one */
836 {
837 p -= 5;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600838 if (!png_memcmp(chunk_name, p, 4))
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500839 return p[4];
840 }
841 while (p > p_end);
842
843 return PNG_HANDLE_CHUNK_AS_DEFAULT;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600844}
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500845
846int /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600847png_chunk_unknown_handling(png_structrp png_ptr, png_uint_32 chunk_name)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500848{
849 png_byte chunk_string[5];
850
851 PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
852 return png_handle_as_unknown(png_ptr, chunk_string);
853}
854#endif
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500855
Glenn Randers-Pehrsonf10fa3c2010-04-29 08:25:29 -0500856#ifdef PNG_READ_SUPPORTED
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500857/* This function, added to libpng-1.0.6g, is untested. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500858int PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600859png_reset_zstream(png_structrp png_ptr)
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500860{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500861 if (png_ptr == NULL)
862 return Z_STREAM_ERROR;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500863
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500864 return (inflateReset(&png_ptr->zstream));
865}
Glenn Randers-Pehrson2b8bef12010-04-29 11:50:24 -0500866#endif /* PNG_READ_SUPPORTED */
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500867
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -0600868/* This function was added to libpng-1.0.7 */
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500869png_uint_32 PNGAPI
870png_access_version_number(void)
871{
872 /* Version of *.c files used when building libpng */
Glenn Randers-Pehrsond2332872010-10-12 19:19:28 -0500873 return((png_uint_32)PNG_LIBPNG_VER);
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500874}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600875
Glenn Randers-Pehrson1fd5fb32001-05-06 05:34:26 -0500876
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500877
878#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
John Bowler736f40f2011-08-25 16:19:44 -0500879/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
880 * at libpng 1.5.5!
881 */
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600882
Glenn Randers-Pehrson02a5e332008-11-24 22:10:23 -0600883/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500884# ifdef PNG_CHECK_cHRM_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500885
Glenn Randers-Pehrson3f705ba2009-07-23 12:53:06 -0500886int /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -0600887png_check_cHRM_fixed(png_const_structrp png_ptr,
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600888 png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
889 png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
890 png_fixed_point blue_x, png_fixed_point blue_y)
891{
892 int ret = 1;
Glenn Randers-Pehrsond0c40592008-11-22 07:09:51 -0600893 unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600894
895 png_debug(1, "in function png_check_cHRM_fixed");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500896
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600897 if (png_ptr == NULL)
898 return 0;
899
John Bowlerd2f0bc22011-06-11 06:42:06 -0500900 /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white
901 * y must also be greater than 0. To test for the upper limit calculate
902 * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression
903 * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is
904 * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it
905 * pointless (and it produces compiler warnings!)
906 */
Glenn Randers-Pehrson02a5e332008-11-24 22:10:23 -0600907 if (white_x < 0 || white_y <= 0 ||
908 red_x < 0 || red_y < 0 ||
909 green_x < 0 || green_y < 0 ||
910 blue_x < 0 || blue_y < 0)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600911 {
912 png_warning(png_ptr,
913 "Ignoring attempt to set negative chromaticity value");
914 ret = 0;
915 }
John Bowlerd2f0bc22011-06-11 06:42:06 -0500916 /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */
917 if (white_x > PNG_FP_1 - white_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600918 {
919 png_warning(png_ptr, "Invalid cHRM white point");
920 ret = 0;
921 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500922
John Bowlerd2f0bc22011-06-11 06:42:06 -0500923 if (red_x > PNG_FP_1 - red_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600924 {
925 png_warning(png_ptr, "Invalid cHRM red point");
926 ret = 0;
927 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500928
John Bowlerd2f0bc22011-06-11 06:42:06 -0500929 if (green_x > PNG_FP_1 - green_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600930 {
931 png_warning(png_ptr, "Invalid cHRM green point");
932 ret = 0;
933 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500934
John Bowlerd2f0bc22011-06-11 06:42:06 -0500935 if (blue_x > PNG_FP_1 - blue_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600936 {
937 png_warning(png_ptr, "Invalid cHRM blue point");
938 ret = 0;
939 }
Glenn Randers-Pehrsond0c40592008-11-22 07:09:51 -0600940
941 png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
942 png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
943
944 if (xy_hi == yx_hi && xy_lo == yx_lo)
945 {
946 png_warning(png_ptr,
947 "Ignoring attempt to set cHRM RGB triangle with zero area");
948 ret = 0;
949 }
950
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600951 return ret;
952}
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500953# endif /* PNG_CHECK_cHRM_SUPPORTED */
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -0500954
John Bowler736f40f2011-08-25 16:19:44 -0500955#ifdef PNG_cHRM_SUPPORTED
956/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
957 * cHRM, as opposed to using chromaticities. These internal APIs return
958 * non-zero on a parameter error. The X, Y and Z values are required to be
959 * positive and less than 1.0.
960 */
961int png_xy_from_XYZ(png_xy *xy, png_XYZ XYZ)
962{
963 png_int_32 d, dwhite, whiteX, whiteY;
964
965 d = XYZ.redX + XYZ.redY + XYZ.redZ;
966 if (!png_muldiv(&xy->redx, XYZ.redX, PNG_FP_1, d)) return 1;
967 if (!png_muldiv(&xy->redy, XYZ.redY, PNG_FP_1, d)) return 1;
968 dwhite = d;
969 whiteX = XYZ.redX;
970 whiteY = XYZ.redY;
971
972 d = XYZ.greenX + XYZ.greenY + XYZ.greenZ;
973 if (!png_muldiv(&xy->greenx, XYZ.greenX, PNG_FP_1, d)) return 1;
974 if (!png_muldiv(&xy->greeny, XYZ.greenY, PNG_FP_1, d)) return 1;
975 dwhite += d;
976 whiteX += XYZ.greenX;
977 whiteY += XYZ.greenY;
978
979 d = XYZ.blueX + XYZ.blueY + XYZ.blueZ;
980 if (!png_muldiv(&xy->bluex, XYZ.blueX, PNG_FP_1, d)) return 1;
981 if (!png_muldiv(&xy->bluey, XYZ.blueY, PNG_FP_1, d)) return 1;
982 dwhite += d;
983 whiteX += XYZ.blueX;
984 whiteY += XYZ.blueY;
985
986 /* The reference white is simply the same of the end-point (X,Y,Z) vectors,
987 * thus:
988 */
989 if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;
990 if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;
991
992 return 0;
993}
994
995int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
996{
997 png_fixed_point red_inverse, green_inverse, blue_scale;
998 png_fixed_point left, right, denominator;
999
1000 /* Check xy and, implicitly, z. Note that wide gamut color spaces typically
1001 * have end points with 0 tristimulus values (these are impossible end
1002 * points, but they are used to cover the possible colors.)
1003 */
1004 if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1;
1005 if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1;
1006 if (xy.greenx < 0 || xy.greenx > PNG_FP_1) return 1;
1007 if (xy.greeny < 0 || xy.greeny > PNG_FP_1-xy.greenx) return 1;
1008 if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1;
1009 if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1;
1010 if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1;
1011 if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1;
1012
1013 /* The reverse calculation is more difficult because the original tristimulus
1014 * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
1015 * derived values were recorded in the cHRM chunk;
1016 * (red,green,blue,white)x(x,y). This loses one degree of freedom and
1017 * therefore an arbitrary ninth value has to be introduced to undo the
1018 * original transformations.
1019 *
1020 * Think of the original end-points as points in (X,Y,Z) space. The
1021 * chromaticity values (c) have the property:
1022 *
1023 * C
1024 * c = ---------
1025 * X + Y + Z
1026 *
1027 * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the
1028 * three chromaticity values (x,y,z) for each end-point obey the
1029 * relationship:
1030 *
1031 * x + y + z = 1
1032 *
1033 * This describes the plane in (X,Y,Z) space that intersects each axis at the
1034 * value 1.0; call this the chromaticity plane. Thus the chromaticity
1035 * calculation has scaled each end-point so that it is on the x+y+z=1 plane
1036 * and chromaticity is the intersection of the vector from the origin to the
1037 * (X,Y,Z) value with the chromaticity plane.
1038 *
1039 * To fully invert the chromaticity calculation we would need the three
1040 * end-point scale factors, (red-scale, green-scale, blue-scale), but these
1041 * were not recorded. Instead we calculated the reference white (X,Y,Z) and
1042 * recorded the chromaticity of this. The reference white (X,Y,Z) would have
1043 * given all three of the scale factors since:
1044 *
1045 * color-C = color-c * color-scale
1046 * white-C = red-C + green-C + blue-C
1047 * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
1048 *
1049 * But cHRM records only white-x and white-y, so we have lost the white scale
1050 * factor:
1051 *
1052 * white-C = white-c*white-scale
1053 *
1054 * To handle this the inverse transformation makes an arbitrary assumption
1055 * about white-scale:
1056 *
1057 * Assume: white-Y = 1.0
1058 * Hence: white-scale = 1/white-y
1059 * Or: red-Y + green-Y + blue-Y = 1.0
1060 *
1061 * Notice the last statement of the assumption gives an equation in three of
1062 * the nine values we want to calculate. 8 more equations come from the
1063 * above routine as summarised at the top above (the chromaticity
1064 * calculation):
1065 *
1066 * Given: color-x = color-X / (color-X + color-Y + color-Z)
1067 * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
1068 *
1069 * This is 9 simultaneous equations in the 9 variables "color-C" and can be
1070 * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix
1071 * determinants, however this is not as bad as it seems because only 28 of
1072 * the total of 90 terms in the various matrices are non-zero. Nevertheless
1073 * Cramer's rule is notoriously numerically unstable because the determinant
1074 * calculation involves the difference of large, but similar, numbers. It is
1075 * difficult to be sure that the calculation is stable for real world values
1076 * and it is certain that it becomes unstable where the end points are close
1077 * together.
1078 *
1079 * So this code uses the perhaps slighly less optimal but more understandable
1080 * and totally obvious approach of calculating color-scale.
1081 *
1082 * This algorithm depends on the precision in white-scale and that is
1083 * (1/white-y), so we can immediately see that as white-y approaches 0 the
1084 * accuracy inherent in the cHRM chunk drops off substantially.
1085 *
1086 * libpng arithmetic: a simple invertion of the above equations
1087 * ------------------------------------------------------------
1088 *
1089 * white_scale = 1/white-y
1090 * white-X = white-x * white-scale
1091 * white-Y = 1.0
1092 * white-Z = (1 - white-x - white-y) * white_scale
1093 *
1094 * white-C = red-C + green-C + blue-C
1095 * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
1096 *
1097 * This gives us three equations in (red-scale,green-scale,blue-scale) where
1098 * all the coefficients are now known:
1099 *
1100 * red-x*red-scale + green-x*green-scale + blue-x*blue-scale
1101 * = white-x/white-y
1102 * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
1103 * red-z*red-scale + green-z*green-scale + blue-z*blue-scale
1104 * = (1 - white-x - white-y)/white-y
1105 *
1106 * In the last equation color-z is (1 - color-x - color-y) so we can add all
1107 * three equations together to get an alternative third:
1108 *
1109 * red-scale + green-scale + blue-scale = 1/white-y = white-scale
1110 *
1111 * So now we have a Cramer's rule solution where the determinants are just
1112 * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve
1113 * multiplication of three coefficients so we can't guarantee to avoid
1114 * overflow in the libpng fixed point representation. Using Cramer's rule in
1115 * floating point is probably a good choice here, but it's not an option for
1116 * fixed point. Instead proceed to simplify the first two equations by
1117 * eliminating what is likely to be the largest value, blue-scale:
1118 *
1119 * blue-scale = white-scale - red-scale - green-scale
1120 *
1121 * Hence:
1122 *
1123 * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
1124 * (white-x - blue-x)*white-scale
1125 *
1126 * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
1127 * 1 - blue-y*white-scale
1128 *
1129 * And now we can trivially solve for (red-scale,green-scale):
1130 *
1131 * green-scale =
1132 * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
1133 * -----------------------------------------------------------
1134 * green-x - blue-x
1135 *
1136 * red-scale =
1137 * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale
1138 * ---------------------------------------------------------
1139 * red-y - blue-y
1140 *
1141 * Hence:
1142 *
1143 * red-scale =
1144 * ( (green-x - blue-x) * (white-y - blue-y) -
1145 * (green-y - blue-y) * (white-x - blue-x) ) / white-y
1146 * -------------------------------------------------------------------------
1147 * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
1148 *
1149 * green-scale =
1150 * ( (red-y - blue-y) * (white-x - blue-x) -
1151 * (red-x - blue-x) * (white-y - blue-y) ) / white-y
1152 * -------------------------------------------------------------------------
1153 * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
1154 *
1155 * Accuracy:
1156 * The input values have 5 decimal digits of accuracy. The values are all in
1157 * the range 0 < value < 1, so simple products are in the same range but may
1158 * need up to 10 decimal digits to preserve the original precision and avoid
1159 * underflow. Because we are using a 32-bit signed representation we cannot
1160 * match this; the best is a little over 9 decimal digits, less than 10.
1161 *
1162 * The approach used here is to preserve the maximum precision within the
1163 * signed representation. Because the red-scale calculation above uses the
1164 * difference between two products of values that must be in the range -1..+1
1165 * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The
1166 * factor is irrelevant in the calculation because it is applied to both
1167 * numerator and denominator.
1168 *
1169 * Note that the values of the differences of the products of the
1170 * chromaticities in the above equations tend to be small, for example for
1171 * the sRGB chromaticities they are:
1172 *
1173 * red numerator: -0.04751
1174 * green numerator: -0.08788
1175 * denominator: -0.2241 (without white-y multiplication)
1176 *
1177 * The resultant Y coefficients from the chromaticities of some widely used
1178 * color space definitions are (to 15 decimal places):
1179 *
1180 * sRGB
1181 * 0.212639005871510 0.715168678767756 0.072192315360734
1182 * Kodak ProPhoto
1183 * 0.288071128229293 0.711843217810102 0.000085653960605
1184 * Adobe RGB
1185 * 0.297344975250536 0.627363566255466 0.075291458493998
1186 * Adobe Wide Gamut RGB
1187 * 0.258728243040113 0.724682314948566 0.016589442011321
1188 */
1189 /* By the argument, above overflow should be impossible here. The return
1190 * value of 2 indicates an internal error to the caller.
1191 */
1192 if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.redy - xy.bluey, 7)) return 2;
1193 if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.redx - xy.bluex, 7)) return 2;
1194 denominator = left - right;
1195
1196 /* Now find the red numerator. */
1197 if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
1198 if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
1199
1200 /* Overflow is possible here and it indicates an extreme set of PNG cHRM
1201 * chunk values. This calculation actually returns the reciprocal of the
1202 * scale value because this allows us to delay the multiplication of white-y
1203 * into the denominator, which tends to produce a small number.
1204 */
1205 if (!png_muldiv(&red_inverse, xy.whitey, denominator, left-right) ||
1206 red_inverse <= xy.whitey /* r+g+b scales = white scale */)
1207 return 1;
1208
1209 /* Similarly for green_inverse: */
1210 if (!png_muldiv(&left, xy.redy-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
1211 if (!png_muldiv(&right, xy.redx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
1212 if (!png_muldiv(&green_inverse, xy.whitey, denominator, left-right) ||
1213 green_inverse <= xy.whitey)
1214 return 1;
1215
1216 /* And the blue scale, the checks above guarantee this can't overflow but it
1217 * can still produce 0 for extreme cHRM values.
1218 */
1219 blue_scale = png_reciprocal(xy.whitey) - png_reciprocal(red_inverse) -
1220 png_reciprocal(green_inverse);
1221 if (blue_scale <= 0) return 1;
1222
1223
1224 /* And fill in the png_XYZ: */
1225 if (!png_muldiv(&XYZ->redX, xy.redx, PNG_FP_1, red_inverse)) return 1;
1226 if (!png_muldiv(&XYZ->redY, xy.redy, PNG_FP_1, red_inverse)) return 1;
1227 if (!png_muldiv(&XYZ->redZ, PNG_FP_1 - xy.redx - xy.redy, PNG_FP_1,
1228 red_inverse))
1229 return 1;
1230
1231 if (!png_muldiv(&XYZ->greenX, xy.greenx, PNG_FP_1, green_inverse)) return 1;
1232 if (!png_muldiv(&XYZ->greenY, xy.greeny, PNG_FP_1, green_inverse)) return 1;
1233 if (!png_muldiv(&XYZ->greenZ, PNG_FP_1 - xy.greenx - xy.greeny, PNG_FP_1,
1234 green_inverse))
1235 return 1;
1236
1237 if (!png_muldiv(&XYZ->blueX, xy.bluex, blue_scale, PNG_FP_1)) return 1;
1238 if (!png_muldiv(&XYZ->blueY, xy.bluey, blue_scale, PNG_FP_1)) return 1;
1239 if (!png_muldiv(&XYZ->blueZ, PNG_FP_1 - xy.bluex - xy.bluey, blue_scale,
1240 PNG_FP_1))
1241 return 1;
1242
1243 return 0; /*success*/
1244}
1245
John Bowler5d567862011-12-24 09:12:00 -06001246int png_XYZ_from_xy_checked(png_const_structrp png_ptr, png_XYZ *XYZ, png_xy xy)
John Bowler736f40f2011-08-25 16:19:44 -05001247{
1248 switch (png_XYZ_from_xy(XYZ, xy))
1249 {
1250 case 0: /* success */
1251 return 1;
1252
1253 case 1:
1254 /* The chunk may be technically valid, but we got png_fixed_point
1255 * overflow while trying to get XYZ values out of it. This is
1256 * entirely benign - the cHRM chunk is pretty extreme.
1257 */
Glenn Randers-Pehrsonb6e4d582011-09-08 12:25:52 -05001258 png_warning(png_ptr,
John Bowler736f40f2011-08-25 16:19:44 -05001259 "extreme cHRM chunk cannot be converted to tristimulus values");
1260 break;
1261
1262 default:
1263 /* libpng is broken; this should be a warning but if it happens we
1264 * want error reports so for the moment it is an error.
1265 */
1266 png_error(png_ptr, "internal error in png_XYZ_from_xy");
1267 break;
1268 }
1269
1270 /* ERROR RETURN */
1271 return 0;
1272}
1273#endif
1274
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001275void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001276png_check_IHDR(png_const_structrp png_ptr,
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001277 png_uint_32 width, png_uint_32 height, int bit_depth,
1278 int color_type, int interlace_type, int compression_type,
1279 int filter_type)
1280{
1281 int error = 0;
1282
1283 /* Check for width and height valid values */
1284 if (width == 0)
1285 {
1286 png_warning(png_ptr, "Image width is zero in IHDR");
1287 error = 1;
1288 }
1289
1290 if (height == 0)
1291 {
1292 png_warning(png_ptr, "Image height is zero in IHDR");
1293 error = 1;
1294 }
1295
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001296# ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonb7040362011-06-11 14:20:22 -05001297 if (width > png_ptr->user_width_max)
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001298
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001299# else
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05001300 if (width > PNG_USER_WIDTH_MAX)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001301# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001302 {
1303 png_warning(png_ptr, "Image width exceeds user limit in IHDR");
1304 error = 1;
1305 }
1306
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001307# ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonb7040362011-06-11 14:20:22 -05001308 if (height > png_ptr->user_height_max)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001309# else
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001310 if (height > PNG_USER_HEIGHT_MAX)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001311# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001312 {
1313 png_warning(png_ptr, "Image height exceeds user limit in IHDR");
1314 error = 1;
1315 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001316
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05001317 if (width > PNG_UINT_31_MAX)
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001318 {
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05001319 png_warning(png_ptr, "Invalid image width in IHDR");
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001320 error = 1;
1321 }
1322
Glenn Randers-Pehrsonbc363ec2010-10-12 21:17:00 -05001323 if (height > PNG_UINT_31_MAX)
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001324 {
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05001325 png_warning(png_ptr, "Invalid image height in IHDR");
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001326 error = 1;
1327 }
1328
Glenn Randers-Pehrsonbc363ec2010-10-12 21:17:00 -05001329 if (width > (PNG_UINT_32_MAX
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001330 >> 3) /* 8-byte RGBA pixels */
Glenn Randers-Pehrsonc5080812010-10-23 08:26:26 -05001331 - 48 /* bigrowbuf hack */
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001332 - 1 /* filter byte */
1333 - 7*8 /* rounding of width to multiple of 8 pixels */
1334 - 8) /* extra max_pixel_depth pad */
1335 png_warning(png_ptr, "Width is too large for libpng to process pixels");
1336
1337 /* Check other values */
1338 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
1339 bit_depth != 8 && bit_depth != 16)
1340 {
1341 png_warning(png_ptr, "Invalid bit depth in IHDR");
1342 error = 1;
1343 }
1344
1345 if (color_type < 0 || color_type == 1 ||
1346 color_type == 5 || color_type > 6)
1347 {
1348 png_warning(png_ptr, "Invalid color type in IHDR");
1349 error = 1;
1350 }
1351
1352 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
1353 ((color_type == PNG_COLOR_TYPE_RGB ||
1354 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
1355 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
1356 {
1357 png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
1358 error = 1;
1359 }
1360
1361 if (interlace_type >= PNG_INTERLACE_LAST)
1362 {
1363 png_warning(png_ptr, "Unknown interlace method in IHDR");
1364 error = 1;
1365 }
1366
1367 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
1368 {
1369 png_warning(png_ptr, "Unknown compression method in IHDR");
1370 error = 1;
1371 }
1372
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001373# ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001374 /* Accept filter_method 64 (intrapixel differencing) only if
1375 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
1376 * 2. Libpng did not read a PNG signature (this filter_method is only
1377 * used in PNG datastreams that are embedded in MNG datastreams) and
1378 * 3. The application called png_permit_mng_features with a mask that
1379 * included PNG_FLAG_MNG_FILTER_64 and
1380 * 4. The filter_method is 64 and
1381 * 5. The color_type is RGB or RGBA
1382 */
1383 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
1384 png_ptr->mng_features_permitted)
1385 png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
1386
1387 if (filter_type != PNG_FILTER_TYPE_BASE)
1388 {
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05001389 if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001390 (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
1391 ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
1392 (color_type == PNG_COLOR_TYPE_RGB ||
1393 color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05001394 {
1395 png_warning(png_ptr, "Unknown filter method in IHDR");
1396 error = 1;
1397 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001398
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05001399 if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
1400 {
1401 png_warning(png_ptr, "Invalid filter method in IHDR");
1402 error = 1;
1403 }
1404 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001405
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001406# else
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001407 if (filter_type != PNG_FILTER_TYPE_BASE)
1408 {
1409 png_warning(png_ptr, "Unknown filter method in IHDR");
1410 error = 1;
1411 }
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06001412# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001413
1414 if (error == 1)
1415 png_error(png_ptr, "Invalid IHDR data");
1416}
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001417
1418#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
1419/* ASCII to fp functions */
1420/* Check an ASCII formated floating point value, see the more detailed
1421 * comments in pngpriv.h
1422 */
John Bowler8d261262011-06-18 13:37:11 -05001423/* The following is used internally to preserve the sticky flags */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001424#define png_fp_add(state, flags) ((state) |= (flags))
John Bowler8d261262011-06-18 13:37:11 -05001425#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001426
1427int /* PRIVATE */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001428png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001429 png_size_tp whereami)
1430{
1431 int state = *statep;
1432 png_size_t i = *whereami;
1433
1434 while (i < size)
1435 {
1436 int type;
1437 /* First find the type of the next character */
John Bowler8d261262011-06-18 13:37:11 -05001438 switch (string[i])
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001439 {
John Bowler8d261262011-06-18 13:37:11 -05001440 case 43: type = PNG_FP_SAW_SIGN; break;
1441 case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
1442 case 46: type = PNG_FP_SAW_DOT; break;
1443 case 48: type = PNG_FP_SAW_DIGIT; break;
1444 case 49: case 50: case 51: case 52:
1445 case 53: case 54: case 55: case 56:
1446 case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
1447 case 69:
1448 case 101: type = PNG_FP_SAW_E; break;
1449 default: goto PNG_FP_End;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001450 }
1451
1452 /* Now deal with this type according to the current
1453 * state, the type is arranged to not overlap the
1454 * bits of the PNG_FP_STATE.
1455 */
John Bowler8d261262011-06-18 13:37:11 -05001456 switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001457 {
John Bowler8d261262011-06-18 13:37:11 -05001458 case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001459 if (state & PNG_FP_SAW_ANY)
1460 goto PNG_FP_End; /* not a part of the number */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001461
John Bowler8d261262011-06-18 13:37:11 -05001462 png_fp_add(state, type);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001463 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001464
John Bowler8d261262011-06-18 13:37:11 -05001465 case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001466 /* Ok as trailer, ok as lead of fraction. */
1467 if (state & PNG_FP_SAW_DOT) /* two dots */
1468 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001469
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001470 else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
John Bowler8d261262011-06-18 13:37:11 -05001471 png_fp_add(state, type);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001472
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001473 else
John Bowler8d261262011-06-18 13:37:11 -05001474 png_fp_set(state, PNG_FP_FRACTION | type);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001475
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001476 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001477
John Bowler8d261262011-06-18 13:37:11 -05001478 case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001479 if (state & PNG_FP_SAW_DOT) /* delayed fraction */
1480 png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001481
John Bowler8d261262011-06-18 13:37:11 -05001482 png_fp_add(state, type | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001483
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001484 break;
John Bowler8d261262011-06-18 13:37:11 -05001485
1486 case PNG_FP_INTEGER + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001487 if ((state & PNG_FP_SAW_DIGIT) == 0)
1488 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001489
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001490 png_fp_set(state, PNG_FP_EXPONENT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001491
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001492 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001493
John Bowler8d261262011-06-18 13:37:11 -05001494 /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:
1495 goto PNG_FP_End; ** no sign in fraction */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001496
John Bowler8d261262011-06-18 13:37:11 -05001497 /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001498 goto PNG_FP_End; ** Because SAW_DOT is always set */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001499
John Bowler8d261262011-06-18 13:37:11 -05001500 case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
1501 png_fp_add(state, type | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001502 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001503
John Bowler8d261262011-06-18 13:37:11 -05001504 case PNG_FP_FRACTION + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001505 /* This is correct because the trailing '.' on an
1506 * integer is handled above - so we can only get here
1507 * with the sequence ".E" (with no preceding digits).
1508 */
1509 if ((state & PNG_FP_SAW_DIGIT) == 0)
1510 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001511
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001512 png_fp_set(state, PNG_FP_EXPONENT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001513
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001514 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001515
John Bowler8d261262011-06-18 13:37:11 -05001516 case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001517 if (state & PNG_FP_SAW_ANY)
1518 goto PNG_FP_End; /* not a part of the number */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001519
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001520 png_fp_add(state, PNG_FP_SAW_SIGN);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001521
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001522 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001523
John Bowler8d261262011-06-18 13:37:11 -05001524 /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001525 goto PNG_FP_End; */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001526
John Bowler8d261262011-06-18 13:37:11 -05001527 case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
1528 png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001529
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001530 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001531
John Bowler8d261262011-06-18 13:37:11 -05001532 /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001533 goto PNG_FP_End; */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001534
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001535 default: goto PNG_FP_End; /* I.e. break 2 */
1536 }
1537
1538 /* The character seems ok, continue. */
1539 ++i;
1540 }
1541
1542PNG_FP_End:
1543 /* Here at the end, update the state and return the correct
1544 * return code.
1545 */
1546 *statep = state;
1547 *whereami = i;
1548
1549 return (state & PNG_FP_SAW_DIGIT) != 0;
1550}
1551
1552
1553/* The same but for a complete string. */
1554int
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001555png_check_fp_string(png_const_charp string, png_size_t size)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001556{
1557 int state=0;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001558 png_size_t char_index=0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001559
John Bowler8d261262011-06-18 13:37:11 -05001560 if (png_check_fp_number(string, size, &state, &char_index) &&
1561 (char_index == size || string[char_index] == 0))
1562 return state /* must be non-zero - see above */;
1563
1564 return 0; /* i.e. fail */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001565}
1566#endif /* pCAL or sCAL */
1567
1568#ifdef PNG_READ_sCAL_SUPPORTED
1569# ifdef PNG_FLOATING_POINT_SUPPORTED
1570/* Utility used below - a simple accurate power of ten from an integral
1571 * exponent.
1572 */
1573static double
1574png_pow10(int power)
1575{
1576 int recip = 0;
1577 double d = 1;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001578
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001579 /* Handle negative exponent with a reciprocal at the end because
1580 * 10 is exact whereas .1 is inexact in base 2
1581 */
1582 if (power < 0)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001583 {
1584 if (power < DBL_MIN_10_EXP) return 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001585 recip = 1, power = -power;
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001586 }
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001587
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001588 if (power > 0)
1589 {
1590 /* Decompose power bitwise. */
1591 double mult = 10;
1592 do
1593 {
1594 if (power & 1) d *= mult;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001595 mult *= mult;
1596 power >>= 1;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001597 }
1598 while (power > 0);
1599
1600 if (recip) d = 1/d;
1601 }
1602 /* else power is 0 and d is 1 */
1603
1604 return d;
1605}
1606
1607/* Function to format a floating point value in ASCII with a given
1608 * precision.
1609 */
1610void /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -06001611png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001612 double fp, unsigned int precision)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001613{
1614 /* We use standard functions from math.h, but not printf because
1615 * that would require stdio. The caller must supply a buffer of
1616 * sufficient size or we will png_error. The tests on size and
1617 * the space in ascii[] consumed are indicated below.
1618 */
1619 if (precision < 1)
1620 precision = DBL_DIG;
1621
1622 /* Enforce the limit of the implementation precision too. */
1623 if (precision > DBL_DIG+1)
1624 precision = DBL_DIG+1;
1625
1626 /* Basic sanity checks */
1627 if (size >= precision+5) /* See the requirements below. */
1628 {
1629 if (fp < 0)
1630 {
1631 fp = -fp;
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05001632 *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001633 --size;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001634 }
1635
1636 if (fp >= DBL_MIN && fp <= DBL_MAX)
1637 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001638 int exp_b10; /* A base 10 exponent */
1639 double base; /* 10^exp_b10 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001640
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001641 /* First extract a base 10 exponent of the number,
1642 * the calculation below rounds down when converting
1643 * from base 2 to base 10 (multiply by log10(2) -
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001644 * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001645 * be increased. Note that the arithmetic shift
1646 * performs a floor() unlike C arithmetic - using a
1647 * C multiply would break the following for negative
1648 * exponents.
1649 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001650 (void)frexp(fp, &exp_b10); /* exponent to base 2 */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001651
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001652 exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001653
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001654 /* Avoid underflow here. */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001655 base = png_pow10(exp_b10); /* May underflow */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001656
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001657 while (base < DBL_MIN || base < fp)
1658 {
1659 /* And this may overflow. */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001660 double test = png_pow10(exp_b10+1);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001661
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001662 if (test <= DBL_MAX)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001663 ++exp_b10, base = test;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001664
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001665 else
1666 break;
1667 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001668
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001669 /* Normalize fp and correct exp_b10, after this fp is in the
1670 * range [.1,1) and exp_b10 is both the exponent and the digit
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001671 * *before* which the decimal point should be inserted
1672 * (starting with 0 for the first digit). Note that this
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001673 * works even if 10^exp_b10 is out of range because of the
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001674 * test on DBL_MAX above.
1675 */
1676 fp /= base;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001677 while (fp >= 1) fp /= 10, ++exp_b10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001678
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001679 /* Because of the code above fp may, at this point, be
1680 * less than .1, this is ok because the code below can
1681 * handle the leading zeros this generates, so no attempt
1682 * is made to correct that here.
1683 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001684
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001685 {
1686 int czero, clead, cdigits;
1687 char exponent[10];
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001688
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001689 /* Allow up to two leading zeros - this will not lengthen
1690 * the number compared to using E-n.
1691 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001692 if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001693 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001694 czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */
1695 exp_b10 = 0; /* Dot added below before first output. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001696 }
1697 else
1698 czero = 0; /* No zeros to add */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001699
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001700 /* Generate the digit list, stripping trailing zeros and
1701 * inserting a '.' before a digit if the exponent is 0.
1702 */
1703 clead = czero; /* Count of leading zeros */
1704 cdigits = 0; /* Count of digits in list. */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001705
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001706 do
1707 {
1708 double d;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001709
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001710 fp *= 10;
1711 /* Use modf here, not floor and subtract, so that
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001712 * the separation is done in one step. At the end
1713 * of the loop don't break the number into parts so
1714 * that the final digit is rounded.
1715 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001716 if (cdigits+czero-clead+1 < (int)precision)
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001717 fp = modf(fp, &d);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001718
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001719 else
1720 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001721 d = floor(fp + .5);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001722
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001723 if (d > 9)
1724 {
1725 /* Rounding up to 10, handle that here. */
1726 if (czero > 0)
1727 {
1728 --czero, d = 1;
1729 if (cdigits == 0) --clead;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001730 }
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001731 else
1732 {
1733 while (cdigits > 0 && d > 9)
1734 {
1735 int ch = *--ascii;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001736
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001737 if (exp_b10 != (-1))
1738 ++exp_b10;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001739
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001740 else if (ch == 46)
1741 {
1742 ch = *--ascii, ++size;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001743 /* Advance exp_b10 to '1', so that the
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001744 * decimal point happens after the
1745 * previous digit.
1746 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001747 exp_b10 = 1;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001748 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001749
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001750 --cdigits;
1751 d = ch - 47; /* I.e. 1+(ch-48) */
1752 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001753
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001754 /* Did we reach the beginning? If so adjust the
1755 * exponent but take into account the leading
1756 * decimal point.
1757 */
1758 if (d > 9) /* cdigits == 0 */
1759 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001760 if (exp_b10 == (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001761 {
1762 /* Leading decimal point (plus zeros?), if
1763 * we lose the decimal point here it must
1764 * be reentered below.
1765 */
1766 int ch = *--ascii;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001767
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001768 if (ch == 46)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001769 ++size, exp_b10 = 1;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001770
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001771 /* Else lost a leading zero, so 'exp_b10' is
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001772 * still ok at (-1)
1773 */
1774 }
1775 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001776 ++exp_b10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001777
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001778 /* In all cases we output a '1' */
1779 d = 1;
1780 }
1781 }
1782 }
1783 fp = 0; /* Guarantees termination below. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001784 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001785
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001786 if (d == 0)
1787 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001788 ++czero;
1789 if (cdigits == 0) ++clead;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001790 }
1791 else
1792 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001793 /* Included embedded zeros in the digit count. */
1794 cdigits += czero - clead;
1795 clead = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001796
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001797 while (czero > 0)
1798 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001799 /* exp_b10 == (-1) means we just output the decimal
1800 * place - after the DP don't adjust 'exp_b10' any
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001801 * more!
1802 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001803 if (exp_b10 != (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001804 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001805 if (exp_b10 == 0) *ascii++ = 46, --size;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001806 /* PLUS 1: TOTAL 4 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001807 --exp_b10;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001808 }
1809 *ascii++ = 48, --czero;
1810 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001811
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001812 if (exp_b10 != (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001813 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001814 if (exp_b10 == 0) *ascii++ = 46, --size; /* counted
1815 above */
1816 --exp_b10;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001817 }
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001818 *ascii++ = (char)(48 + (int)d), ++cdigits;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001819 }
1820 }
1821 while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001822
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001823 /* The total output count (max) is now 4+precision */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001824
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001825 /* Check for an exponent, if we don't need one we are
1826 * done and just need to terminate the string. At
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001827 * this point exp_b10==(-1) is effectively if flag - it got
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001828 * to '-1' because of the decrement after outputing
1829 * the decimal point above (the exponent required is
1830 * *not* -1!)
1831 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001832 if (exp_b10 >= (-1) && exp_b10 <= 2)
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001833 {
1834 /* The following only happens if we didn't output the
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001835 * leading zeros above for negative exponent, so this
1836 * doest add to the digit requirement. Note that the
1837 * two zeros here can only be output if the two leading
1838 * zeros were *not* output, so this doesn't increase
1839 * the output count.
1840 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06001841 while (--exp_b10 >= 0) *ascii++ = 48;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001842
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001843 *ascii = 0;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001844
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001845 /* Total buffer requirement (including the '\0') is
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05001846 * 5+precision - see check at the start.
1847 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001848 return;
1849 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001850
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001851 /* Here if an exponent is required, adjust size for
1852 * the digits we output but did not count. The total
1853 * digit output here so far is at most 1+precision - no
1854 * decimal point and no leading or trailing zeros have
1855 * been output.
1856 */
1857 size -= cdigits;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001858
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05001859 *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001860
John Bowler75156122011-09-09 17:21:44 -05001861 /* The following use of an unsigned temporary avoids ambiguities in
1862 * the signed arithmetic on exp_b10 and permits GCC at least to do
1863 * better optimization.
1864 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001865 {
John Bowler75156122011-09-09 17:21:44 -05001866 unsigned int uexp_b10;
1867
1868 if (exp_b10 < 0)
1869 {
1870 *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
1871 uexp_b10 = -exp_b10;
1872 }
1873
1874 else
1875 uexp_b10 = exp_b10;
1876
1877 cdigits = 0;
1878
1879 while (uexp_b10 > 0)
1880 {
1881 exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
1882 uexp_b10 /= 10;
1883 }
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001884 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001885
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001886 /* Need another size check here for the exponent digits, so
1887 * this need not be considered above.
1888 */
1889 if ((int)size > cdigits)
1890 {
1891 while (cdigits > 0) *ascii++ = exponent[--cdigits];
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001892
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001893 *ascii = 0;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05001894
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001895 return;
1896 }
1897 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001898 }
1899 else if (!(fp >= DBL_MIN))
1900 {
1901 *ascii++ = 48; /* '0' */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001902 *ascii = 0;
1903 return;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001904 }
1905 else
1906 {
1907 *ascii++ = 105; /* 'i' */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001908 *ascii++ = 110; /* 'n' */
1909 *ascii++ = 102; /* 'f' */
1910 *ascii = 0;
1911 return;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001912 }
1913 }
1914
1915 /* Here on buffer too small. */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05001916 png_error(png_ptr, "ASCII conversion buffer too small");
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001917}
1918
1919# endif /* FLOATING_POINT */
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001920
1921# ifdef PNG_FIXED_POINT_SUPPORTED
1922/* Function to format a fixed point value in ASCII.
1923 */
1924void /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -06001925png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
1926 png_size_t size, png_fixed_point fp)
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001927{
1928 /* Require space for 10 decimal digits, a decimal point, a minus sign and a
1929 * trailing \0, 13 characters:
1930 */
1931 if (size > 12)
1932 {
1933 png_uint_32 num;
1934
1935 /* Avoid overflow here on the minimum integer. */
1936 if (fp < 0)
1937 *ascii++ = 45, --size, num = -fp;
1938 else
1939 num = fp;
1940
John Bowler75156122011-09-09 17:21:44 -05001941 if (num <= 0x80000000) /* else overflowed */
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001942 {
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05001943 unsigned int ndigits = 0, first = 16 /* flag value */;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001944 char digits[10];
1945
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05001946 while (num)
1947 {
1948 /* Split the low digit off num: */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001949 unsigned int tmp = num/10;
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05001950 num -= tmp*10;
1951 digits[ndigits++] = (char)(48 + num);
1952 /* Record the first non-zero digit, note that this is a number
1953 * starting at 1, it's not actually the array index.
1954 */
1955 if (first == 16 && num > 0)
1956 first = ndigits;
1957 num = tmp;
1958 }
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001959
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05001960 if (ndigits > 0)
1961 {
1962 while (ndigits > 5) *ascii++ = digits[--ndigits];
1963 /* The remaining digits are fractional digits, ndigits is '5' or
1964 * smaller at this point. It is certainly not zero. Check for a
1965 * non-zero fractional digit:
1966 */
1967 if (first <= 5)
1968 {
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001969 unsigned int i;
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05001970 *ascii++ = 46; /* decimal point */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05001971 /* ndigits may be <5 for small numbers, output leading zeros
1972 * then ndigits digits to first:
1973 */
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05001974 i = 5;
1975 while (ndigits < i) *ascii++ = 48, --i;
1976 while (ndigits >= first) *ascii++ = digits[--ndigits];
1977 /* Don't output the trailing zeros! */
1978 }
1979 }
1980 else
1981 *ascii++ = 48;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001982
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05001983 /* And null terminate the string: */
1984 *ascii = 0;
1985 return;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05001986 }
1987 }
1988
1989 /* Here on buffer too small. */
1990 png_error(png_ptr, "ASCII conversion buffer too small");
1991}
1992# endif /* FIXED_POINT */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001993#endif /* READ_SCAL */
1994
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05001995#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001996 !defined(PNG_FIXED_POINT_MACRO_SUPPORTED)
1997png_fixed_point
John Bowler5d567862011-12-24 09:12:00 -06001998png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05001999{
2000 double r = floor(100000 * fp + .5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002001
Glenn Randers-Pehrson77c3bf12011-01-20 15:56:31 -06002002 if (r > 2147483647. || r < -2147483648.)
2003 png_fixed_error(png_ptr, text);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002004
Glenn Randers-Pehrson77c3bf12011-01-20 15:56:31 -06002005 return (png_fixed_point)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002006}
2007#endif
2008
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05002009#if defined(PNG_READ_GAMMA_SUPPORTED) || \
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002010 defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002011/* muldiv functions */
2012/* This API takes signed arguments and rounds the result to the nearest
2013 * integer (or, for a fixed point number - the standard argument - to
2014 * the nearest .00001). Overflow and divide by zero are signalled in
2015 * the result, a boolean - true on success, false on overflow.
2016 */
2017int
2018png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002019 png_int_32 divisor)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002020{
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002021 /* Return a * times / divisor, rounded. */
2022 if (divisor != 0)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002023 {
2024 if (a == 0 || times == 0)
2025 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002026 *res = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002027 return 1;
2028 }
2029 else
2030 {
2031#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002032 double r = a;
2033 r *= times;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002034 r /= divisor;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002035 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002036
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002037 /* A png_fixed_point is a 32-bit integer. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002038 if (r <= 2147483647. && r >= -2147483648.)
2039 {
2040 *res = (png_fixed_point)r;
2041 return 1;
2042 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002043#else
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002044 int negative = 0;
2045 png_uint_32 A, T, D;
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05002046 png_uint_32 s16, s32, s00;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002047
2048 if (a < 0)
2049 negative = 1, A = -a;
2050 else
2051 A = a;
2052
2053 if (times < 0)
2054 negative = !negative, T = -times;
2055 else
2056 T = times;
2057
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002058 if (divisor < 0)
2059 negative = !negative, D = -divisor;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002060 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002061 D = divisor;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002062
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002063 /* Following can't overflow because the arguments only
2064 * have 31 bits each, however the result may be 32 bits.
2065 */
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05002066 s16 = (A >> 16) * (T & 0xffff) +
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002067 (A & 0xffff) * (T >> 16);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002068 /* Can't overflow because the a*times bit is only 30
2069 * bits at most.
2070 */
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05002071 s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
2072 s00 = (A & 0xffff) * (T & 0xffff);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002073
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002074 s16 = (s16 & 0xffff) << 16;
2075 s00 += s16;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002076
2077 if (s00 < s16)
2078 ++s32; /* carry */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002079
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002080 if (s32 < D) /* else overflow */
2081 {
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002082 /* s32.s00 is now the 64-bit product, do a standard
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002083 * division, we know that s32 < D, so the maximum
2084 * required shift is 31.
2085 */
2086 int bitshift = 32;
2087 png_fixed_point result = 0; /* NOTE: signed */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002088
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002089 while (--bitshift >= 0)
2090 {
2091 png_uint_32 d32, d00;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002092
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002093 if (bitshift > 0)
2094 d32 = D >> (32-bitshift), d00 = D << bitshift;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002095
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002096 else
2097 d32 = 0, d00 = D;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002098
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002099 if (s32 > d32)
2100 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002101 if (s00 < d00) --s32; /* carry */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002102 s32 -= d32, s00 -= d00, result += 1<<bitshift;
2103 }
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002104
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002105 else
2106 if (s32 == d32 && s00 >= d00)
2107 s32 = 0, s00 -= d00, result += 1<<bitshift;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002108 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002109
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002110 /* Handle the rounding. */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002111 if (s00 >= (D >> 1))
2112 ++result;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002113
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002114 if (negative)
2115 result = -result;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002116
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002117 /* Check for overflow. */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002118 if ((negative && result <= 0) || (!negative && result >= 0))
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002119 {
2120 *res = result;
2121 return 1;
2122 }
2123 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002124#endif
2125 }
2126 }
2127
2128 return 0;
2129}
2130#endif /* READ_GAMMA || INCH_CONVERSIONS */
2131
2132#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
2133/* The following is for when the caller doesn't much care about the
2134 * result.
2135 */
2136png_fixed_point
John Bowler5d567862011-12-24 09:12:00 -06002137png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002138 png_int_32 divisor)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002139{
2140 png_fixed_point result;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002141
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002142 if (png_muldiv(&result, a, times, divisor))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002143 return result;
2144
2145 png_warning(png_ptr, "fixed point overflow ignored");
2146 return 0;
2147}
2148#endif
2149
2150#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */
2151/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
2152png_fixed_point
2153png_reciprocal(png_fixed_point a)
2154{
2155#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
2156 double r = floor(1E10/a+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002157
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002158 if (r <= 2147483647. && r >= -2147483648.)
2159 return (png_fixed_point)r;
2160#else
2161 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002162
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002163 if (png_muldiv(&res, 100000, 100000, a))
2164 return res;
2165#endif
2166
2167 return 0; /* error/overflow */
2168}
2169
2170/* A local convenience routine. */
2171static png_fixed_point
2172png_product2(png_fixed_point a, png_fixed_point b)
2173{
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -05002174 /* The required result is 1/a * 1/b; the following preserves accuracy. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002175#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
2176 double r = a * 1E-5;
2177 r *= b;
2178 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002179
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002180 if (r <= 2147483647. && r >= -2147483648.)
2181 return (png_fixed_point)r;
2182#else
2183 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002184
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002185 if (png_muldiv(&res, a, b, 100000))
2186 return res;
2187#endif
2188
2189 return 0; /* overflow */
2190}
2191
2192/* The inverse of the above. */
2193png_fixed_point
2194png_reciprocal2(png_fixed_point a, png_fixed_point b)
2195{
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -05002196 /* The required result is 1/a * 1/b; the following preserves accuracy. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002197#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
2198 double r = 1E15/a;
2199 r /= b;
2200 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002201
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002202 if (r <= 2147483647. && r >= -2147483648.)
2203 return (png_fixed_point)r;
2204#else
2205 /* This may overflow because the range of png_fixed_point isn't symmetric,
2206 * but this API is only used for the product of file and screen gamma so it
2207 * doesn't matter that the smallest number it can produce is 1/21474, not
2208 * 1/100000
2209 */
2210 png_fixed_point res = png_product2(a, b);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002211
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002212 if (res != 0)
2213 return png_reciprocal(res);
2214#endif
2215
2216 return 0; /* overflow */
2217}
2218#endif /* READ_GAMMA */
2219
2220#ifdef PNG_CHECK_cHRM_SUPPORTED
2221/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
2222 * 2010: moved from pngset.c) */
2223/*
2224 * Multiply two 32-bit numbers, V1 and V2, using 32-bit
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002225 * arithmetic, to produce a 64-bit result in the HI/LO words.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002226 *
2227 * A B
2228 * x C D
2229 * ------
2230 * AD || BD
2231 * AC || CB || 0
2232 *
2233 * where A and B are the high and low 16-bit words of V1,
2234 * C and D are the 16-bit words of V2, AD is the product of
2235 * A and D, and X || Y is (X << 16) + Y.
2236*/
2237
2238void /* PRIVATE */
2239png_64bit_product (long v1, long v2, unsigned long *hi_product,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002240 unsigned long *lo_product)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002241{
2242 int a, b, c, d;
2243 long lo, hi, x, y;
2244
2245 a = (v1 >> 16) & 0xffff;
2246 b = v1 & 0xffff;
2247 c = (v2 >> 16) & 0xffff;
2248 d = v2 & 0xffff;
2249
2250 lo = b * d; /* BD */
2251 x = a * d + c * b; /* AD + CB */
2252 y = ((lo >> 16) & 0xffff) + x;
2253
2254 lo = (lo & 0xffff) | ((y & 0xffff) << 16);
2255 hi = (y >> 16) & 0xffff;
2256
2257 hi += a * c; /* AC */
2258
2259 *hi_product = (unsigned long)hi;
2260 *lo_product = (unsigned long)lo;
2261}
2262#endif /* CHECK_cHRM */
2263
2264#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
2265#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
2266/* Fixed point gamma.
2267 *
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06002268 * The code to calculate the tables used below can be found in the shell script
2269 * contrib/tools/intgamma.sh
2270 *
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002271 * To calculate gamma this code implements fast log() and exp() calls using only
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002272 * fixed point arithmetic. This code has sufficient precision for either 8-bit
2273 * or 16-bit sample values.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002274 *
2275 * The tables used here were calculated using simple 'bc' programs, but C double
2276 * precision floating point arithmetic would work fine. The programs are given
2277 * at the head of each table.
2278 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002279 * 8-bit log table
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002280 * 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 -05002281 * 255, so it's the base 2 logarithm of a normalized 8-bit floating point
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002282 * mantissa. The numbers are 32-bit fractions.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002283 */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06002284static const png_uint_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002285png_8bit_l2[128] =
2286{
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002287 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
2288 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
2289 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
2290 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
2291 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
2292 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
2293 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
2294 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
2295 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
2296 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
2297 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
2298 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
2299 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
2300 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
2301 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
2302 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
2303 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
2304 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
2305 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
2306 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
2307 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
2308 24347096U, 0U
Glenn Randers-Pehrson8888ea42011-11-28 11:29:10 -06002309
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002310#if 0
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002311 /* The following are the values for 16-bit tables - these work fine for the
2312 * 8-bit conversions but produce very slightly larger errors in the 16-bit
2313 * log (about 1.2 as opposed to 0.7 absolute error in the final value). To
2314 * use these all the shifts below must be adjusted appropriately.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002315 */
2316 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
2317 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
2318 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
2319 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
2320 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
2321 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
2322 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
2323 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
2324 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
2325 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
2326 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
2327 1119, 744, 372
2328#endif
2329};
2330
John Bowler8d261262011-06-18 13:37:11 -05002331PNG_STATIC png_int_32
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002332png_log8bit(unsigned int x)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002333{
John Bowler168a4332011-01-16 19:32:22 -06002334 unsigned int lg2 = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002335 /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
2336 * because the log is actually negate that means adding 1. The final
2337 * returned value thus has the range 0 (for 255 input) to 7.994 (for 1
2338 * input), return 7.99998 for the overflow (log 0) case - so the result is
2339 * always at most 19 bits.
2340 */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002341 if ((x &= 0xff) == 0)
Glenn Randers-Pehrsona5815562010-11-20 21:48:29 -06002342 return 0xffffffff;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002343
2344 if ((x & 0xf0) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002345 lg2 = 4, x <<= 4;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002346
2347 if ((x & 0xc0) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002348 lg2 += 2, x <<= 2;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002349
2350 if ((x & 0x80) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002351 lg2 += 1, x <<= 1;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002352
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002353 /* result is at most 19 bits, so this cast is safe: */
John Bowler168a4332011-01-16 19:32:22 -06002354 return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002355}
2356
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002357/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
2358 * 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 -05002359 * get an approximation then multiply the approximation by a correction factor
2360 * determined by the remaining up to 8 bits. This requires an additional step
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002361 * in the 16-bit case.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002362 *
2363 * We want log2(value/65535), we have log2(v'/255), where:
2364 *
2365 * value = v' * 256 + v''
2366 * = v' * f
2367 *
2368 * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
2369 * 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 -05002370 * than 258. The final factor also needs to correct for the fact that our 8-bit
2371 * value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002372 *
2373 * This gives a final formula using a calculated value 'x' which is value/v' and
2374 * scaling by 65536 to match the above table:
2375 *
2376 * log2(x/257) * 65536
2377 *
2378 * Since these numbers are so close to '1' we can use simple linear
2379 * interpolation between the two end values 256/257 (result -368.61) and 258/257
2380 * (result 367.179). The values used below are scaled by a further 64 to give
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002381 * 16-bit precision in the interpolation:
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002382 *
2383 * Start (256): -23591
2384 * Zero (257): 0
2385 * End (258): 23499
2386 */
John Bowler8d261262011-06-18 13:37:11 -05002387PNG_STATIC png_int_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002388png_log16bit(png_uint_32 x)
2389{
John Bowler168a4332011-01-16 19:32:22 -06002390 unsigned int lg2 = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002391
2392 /* As above, but now the input has 16 bits. */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002393 if ((x &= 0xffff) == 0)
2394 return 0xffffffff;
2395
2396 if ((x & 0xff00) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002397 lg2 = 8, x <<= 8;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002398
2399 if ((x & 0xf000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002400 lg2 += 4, x <<= 4;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002401
2402 if ((x & 0xc000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002403 lg2 += 2, x <<= 2;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002404
2405 if ((x & 0x8000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06002406 lg2 += 1, x <<= 1;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002407
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002408 /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002409 * value.
2410 */
John Bowler168a4332011-01-16 19:32:22 -06002411 lg2 <<= 28;
2412 lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002413
2414 /* Now we need to interpolate the factor, this requires a division by the top
2415 * 8 bits. Do this with maximum precision.
2416 */
2417 x = ((x << 16) + (x >> 9)) / (x >> 8);
2418
2419 /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
2420 * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
2421 * 16 bits to interpolate to get the low bits of the result. Round the
2422 * answer. Note that the end point values are scaled by 64 to retain overall
John Bowler168a4332011-01-16 19:32:22 -06002423 * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002424 * the overall scaling by 6-12. Round at every step.
2425 */
2426 x -= 1U << 24;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002427
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002428 if (x <= 65536U) /* <= '257' */
John Bowler168a4332011-01-16 19:32:22 -06002429 lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002430
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002431 else
John Bowler168a4332011-01-16 19:32:22 -06002432 lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002433
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002434 /* Safe, because the result can't have more than 20 bits: */
John Bowler168a4332011-01-16 19:32:22 -06002435 return (png_int_32)((lg2 + 2048) >> 12);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002436}
2437
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002438/* The 'exp()' case must invert the above, taking a 20-bit fixed point
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002439 * logarithmic value and returning a 16 or 8-bit number as appropriate. In
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002440 * each case only the low 16 bits are relevant - the fraction - since the
2441 * integer bits (the top 4) simply determine a shift.
2442 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002443 * The worst case is the 16-bit distinction between 65535 and 65534, this
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002444 * requires perhaps spurious accuracty in the decoding of the logarithm to
2445 * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
2446 * of getting this accuracy in practice.
2447 *
2448 * To deal with this the following exp() function works out the exponent of the
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002449 * frational part of the logarithm by using an accurate 32-bit value from the
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002450 * top four fractional bits then multiplying in the remaining bits.
2451 */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06002452static const png_uint_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002453png_32bit_exp[16] =
2454{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002455 /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002456 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
2457 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
2458 2553802834U, 2445529972U, 2341847524U, 2242560872U
2459};
2460
2461/* Adjustment table; provided to explain the numbers in the code below. */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06002462#if 0
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002463for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
2464 11 44937.64284865548751208448
2465 10 45180.98734845585101160448
2466 9 45303.31936980687359311872
2467 8 45364.65110595323018870784
2468 7 45395.35850361789624614912
2469 6 45410.72259715102037508096
2470 5 45418.40724413220722311168
2471 4 45422.25021786898173001728
2472 3 45424.17186732298419044352
2473 2 45425.13273269940811464704
2474 1 45425.61317555035558641664
2475 0 45425.85339951654943850496
2476#endif
2477
John Bowler8d261262011-06-18 13:37:11 -05002478PNG_STATIC png_uint_32
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002479png_exp(png_fixed_point x)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002480{
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002481 if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002482 {
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002483 /* Obtain a 4-bit approximation */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002484 png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
2485
2486 /* Incorporate the low 12 bits - these decrease the returned value by
2487 * multiplying by a number less than 1 if the bit is set. The multiplier
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002488 * is determined by the above table and the shift. Notice that the values
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002489 * converge on 45426 and this is used to allow linear interpolation of the
2490 * low bits.
2491 */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002492 if (x & 0x800)
2493 e -= (((e >> 16) * 44938U) + 16U) >> 5;
2494
2495 if (x & 0x400)
2496 e -= (((e >> 16) * 45181U) + 32U) >> 6;
2497
2498 if (x & 0x200)
2499 e -= (((e >> 16) * 45303U) + 64U) >> 7;
2500
2501 if (x & 0x100)
2502 e -= (((e >> 16) * 45365U) + 128U) >> 8;
2503
2504 if (x & 0x080)
2505 e -= (((e >> 16) * 45395U) + 256U) >> 9;
2506
2507 if (x & 0x040)
2508 e -= (((e >> 16) * 45410U) + 512U) >> 10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002509
2510 /* And handle the low 6 bits in a single block. */
2511 e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
2512
2513 /* Handle the upper bits of x. */
2514 e >>= x >> 16;
2515 return e;
2516 }
2517
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002518 /* Check for overflow */
2519 if (x <= 0)
2520 return png_32bit_exp[0];
2521
2522 /* Else underflow */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002523 return 0;
2524}
2525
John Bowler8d261262011-06-18 13:37:11 -05002526PNG_STATIC png_byte
John Bowler168a4332011-01-16 19:32:22 -06002527png_exp8bit(png_fixed_point lg2)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002528{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002529 /* Get a 32-bit value: */
John Bowler168a4332011-01-16 19:32:22 -06002530 png_uint_32 x = png_exp(lg2);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002531
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002532 /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002533 * second, rounding, step can't overflow because of the first, subtraction,
2534 * step.
2535 */
2536 x -= x >> 8;
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002537 return (png_byte)((x + 0x7fffffU) >> 24);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002538}
2539
John Bowler8d261262011-06-18 13:37:11 -05002540PNG_STATIC png_uint_16
John Bowler168a4332011-01-16 19:32:22 -06002541png_exp16bit(png_fixed_point lg2)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002542{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002543 /* Get a 32-bit value: */
John Bowler168a4332011-01-16 19:32:22 -06002544 png_uint_32 x = png_exp(lg2);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002545
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002546 /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002547 x -= x >> 16;
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002548 return (png_uint_16)((x + 32767U) >> 16);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002549}
2550#endif /* FLOATING_ARITHMETIC */
2551
2552png_byte
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002553png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002554{
2555 if (value > 0 && value < 255)
2556 {
2557# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002558 double r = floor(255*pow(value/255.,gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002559 return (png_byte)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002560# else
John Bowler168a4332011-01-16 19:32:22 -06002561 png_int_32 lg2 = png_log8bit(value);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002562 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002563
John Bowler168a4332011-01-16 19:32:22 -06002564 if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002565 return png_exp8bit(res);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002566
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002567 /* Overflow. */
2568 value = 0;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002569# endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002570 }
2571
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002572 return (png_byte)value;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002573}
2574
2575png_uint_16
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002576png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002577{
2578 if (value > 0 && value < 65535)
2579 {
2580# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002581 double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002582 return (png_uint_16)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002583# else
John Bowler168a4332011-01-16 19:32:22 -06002584 png_int_32 lg2 = png_log16bit(value);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002585 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002586
John Bowler168a4332011-01-16 19:32:22 -06002587 if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002588 return png_exp16bit(res);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002589
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002590 /* Overflow. */
2591 value = 0;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002592# endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002593 }
2594
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002595 return (png_uint_16)value;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002596}
2597
2598/* This does the right thing based on the bit_depth field of the
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002599 * png_struct, interpreting values as 8-bit or 16-bit. While the result
2600 * is nominally a 16-bit value if bit depth is 8 then the result is
2601 * 8-bit (as are the arguments.)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002602 */
2603png_uint_16 /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06002604png_gamma_correct(png_structrp png_ptr, unsigned int value,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002605 png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002606{
2607 if (png_ptr->bit_depth == 8)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002608 return png_gamma_8bit_correct(value, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002609
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002610 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002611 return png_gamma_16bit_correct(value, gamma_val);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002612}
2613
2614/* This is the shared test on whether a gamma value is 'significant' - whether
2615 * it is worth doing gamma correction.
2616 */
2617int /* PRIVATE */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002618png_gamma_significant(png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002619{
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002620 return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
2621 gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002622}
2623
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002624/* Internal function to build a single 16-bit table - the table consists of
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002625 * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
2626 * to shift the input values right (or 16-number_of_signifiant_bits).
2627 *
Glenn Randers-Pehrsona774c5d2010-08-26 19:37:55 -05002628 * The caller is responsible for ensuring that the table gets cleaned up on
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002629 * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
2630 * should be somewhere that will be cleaned.
2631 */
2632static void
John Bowler5d567862011-12-24 09:12:00 -06002633png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002634 PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002635{
2636 /* Various values derived from 'shift': */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002637 PNG_CONST unsigned int num = 1U << (8U - shift);
2638 PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
2639 PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
2640 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002641
2642 png_uint_16pp table = *ptable =
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002643 (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002644
2645 for (i = 0; i < num; i++)
2646 {
2647 png_uint_16p sub_table = table[i] =
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002648 (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002649
2650 /* The 'threshold' test is repeated here because it can arise for one of
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002651 * the 16-bit tables even if the others don't hit it.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002652 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002653 if (png_gamma_significant(gamma_val))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002654 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002655 /* The old code would overflow at the end and this would cause the
2656 * 'pow' function to return a result >1, resulting in an
2657 * arithmetic error. This code follows the spec exactly; ig is
2658 * the recovered input sample, it always has 8-16 bits.
2659 *
2660 * We want input * 65535/max, rounded, the arithmetic fits in 32
2661 * bits (unsigned) so long as max <= 32767.
2662 */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002663 unsigned int j;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002664 for (j = 0; j < 256; j++)
2665 {
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002666 png_uint_32 ig = (j << (8-shift)) + i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002667# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002668 /* Inline the 'max' scaling operation: */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002669 double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002670 sub_table[j] = (png_uint_16)d;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002671# else
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002672 if (shift)
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002673 ig = (ig * 65535U + max_by_2)/max;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002674
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002675 sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002676# endif
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002677 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002678 }
2679 else
2680 {
2681 /* We must still build a table, but do it the fast way. */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002682 unsigned int j;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002683
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002684 for (j = 0; j < 256; j++)
2685 {
2686 png_uint_32 ig = (j << (8-shift)) + i;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002687
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002688 if (shift)
2689 ig = (ig * 65535U + max_by_2)/max;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002690
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002691 sub_table[j] = (png_uint_16)ig;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002692 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002693 }
2694 }
2695}
2696
2697/* NOTE: this function expects the *inverse* of the overall gamma transformation
2698 * required.
2699 */
2700static void
John Bowler5d567862011-12-24 09:12:00 -06002701png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002702 PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002703{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002704 PNG_CONST unsigned int num = 1U << (8U - shift);
2705 PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
2706 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002707 png_uint_32 last;
2708
2709 png_uint_16pp table = *ptable =
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002710 (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002711
2712 /* 'num' is the number of tables and also the number of low bits of low
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002713 * bits of the input 16-bit value used to select a table. Each table is
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002714 * itself index by the high 8 bits of the value.
2715 */
2716 for (i = 0; i < num; i++)
2717 table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002718 256 * png_sizeof(png_uint_16));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002719
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002720 /* 'gamma_val' is set to the reciprocal of the value calculated above, so
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002721 * pow(out,g) is an *input* value. 'last' is the last input value set.
2722 *
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002723 * In the loop 'i' is used to find output values. Since the output is
2724 * 8-bit there are only 256 possible values. The tables are set up to
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002725 * select the closest possible output value for each input by finding
2726 * the input value at the boundary between each pair of output values
2727 * and filling the table up to that boundary with the lower output
2728 * value.
2729 *
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05002730 * 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 -05002731 * values the code below uses a 16-bit value in i; the values start at
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002732 * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
2733 * entries are filled with 255). Start i at 128 and fill all 'last'
2734 * table entries <= 'max'
2735 */
2736 last = 0;
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002737 for (i = 0; i < 255; ++i) /* 8-bit output value */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002738 {
2739 /* Find the corresponding maximum input value */
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002740 png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002741
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002742 /* Find the boundary value in 16 bits: */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002743 png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002744
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002745 /* Adjust (round) to (16-shift) bits: */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002746 bound = (bound * max + 32768U)/65535U + 1U;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002747
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002748 while (last < bound)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002749 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002750 table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
2751 last++;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002752 }
2753 }
2754
2755 /* And fill in the final entries. */
2756 while (last < (num << 8))
2757 {
2758 table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
2759 last++;
2760 }
2761}
2762
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002763/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002764 * typically much faster). Note that libpng currently does no sBIT processing
2765 * (apparently contrary to the spec) so a 256 entry table is always generated.
2766 */
2767static void
John Bowler5d567862011-12-24 09:12:00 -06002768png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002769 PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002770{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002771 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002772 png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
2773
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002774 if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++)
2775 table[i] = png_gamma_8bit_correct(i, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002776
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002777 else for (i=0; i<256; ++i)
2778 table[i] = (png_byte)i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002779}
2780
John Bowler07772cb2011-10-14 18:19:47 -05002781/* Used from png_read_destroy and below to release the memory used by the gamma
2782 * tables.
2783 */
2784void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06002785png_destroy_gamma_table(png_structrp png_ptr)
John Bowler07772cb2011-10-14 18:19:47 -05002786{
2787 png_free(png_ptr, png_ptr->gamma_table);
2788 png_ptr->gamma_table = NULL;
2789
2790 if (png_ptr->gamma_16_table != NULL)
2791 {
2792 int i;
2793 int istop = (1 << (8 - png_ptr->gamma_shift));
2794 for (i = 0; i < istop; i++)
2795 {
2796 png_free(png_ptr, png_ptr->gamma_16_table[i]);
2797 }
2798 png_free(png_ptr, png_ptr->gamma_16_table);
2799 png_ptr->gamma_16_table = NULL;
2800 }
2801
2802#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
2803 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
2804 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2805 png_free(png_ptr, png_ptr->gamma_from_1);
2806 png_ptr->gamma_from_1 = NULL;
2807 png_free(png_ptr, png_ptr->gamma_to_1);
2808 png_ptr->gamma_to_1 = NULL;
2809
2810 if (png_ptr->gamma_16_from_1 != NULL)
2811 {
2812 int i;
2813 int istop = (1 << (8 - png_ptr->gamma_shift));
2814 for (i = 0; i < istop; i++)
2815 {
2816 png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
2817 }
2818 png_free(png_ptr, png_ptr->gamma_16_from_1);
2819 png_ptr->gamma_16_from_1 = NULL;
2820 }
2821 if (png_ptr->gamma_16_to_1 != NULL)
2822 {
2823 int i;
2824 int istop = (1 << (8 - png_ptr->gamma_shift));
2825 for (i = 0; i < istop; i++)
2826 {
2827 png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
2828 }
2829 png_free(png_ptr, png_ptr->gamma_16_to_1);
2830 png_ptr->gamma_16_to_1 = NULL;
2831 }
2832#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
2833}
2834
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002835/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
2836 * tables, we don't make a full table if we are reducing to 8-bit in
2837 * the future. Note also how the gamma_16 tables are segmented so that
2838 * we don't need to allocate > 64K chunks for a full 16-bit table.
2839 */
2840void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06002841png_build_gamma_table(png_structrp png_ptr, int bit_depth)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002842{
2843 png_debug(1, "in png_build_gamma_table");
2844
John Bowler07772cb2011-10-14 18:19:47 -05002845 /* Remove any existing table; this copes with multiple calls to
2846 * png_read_update_info. The warning is because building the gamma tables
2847 * multiple times is a performance hit - it's harmless but the ability to call
2848 * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible
2849 * to warn if the app introduces such a hit.
2850 */
2851 if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
2852 {
2853 png_warning(png_ptr, "gamma table being rebuilt");
2854 png_destroy_gamma_table(png_ptr);
2855 }
2856
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002857 if (bit_depth <= 8)
2858 {
2859 png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002860 png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
2861 png_ptr->screen_gamma) : PNG_FP_1);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002862
2863#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
John Bowlerd273ad22011-05-07 21:00:28 -05002864 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002865 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
John Bowlerd273ad22011-05-07 21:00:28 -05002866 if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002867 {
2868 png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002869 png_reciprocal(png_ptr->gamma));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002870
2871 png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002872 png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
2873 png_ptr->gamma/* Probably doing rgb_to_gray */);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002874 }
John Bowlerd273ad22011-05-07 21:00:28 -05002875#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002876 }
2877 else
2878 {
2879 png_byte shift, sig_bit;
2880
2881 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
2882 {
2883 sig_bit = png_ptr->sig_bit.red;
2884
2885 if (png_ptr->sig_bit.green > sig_bit)
2886 sig_bit = png_ptr->sig_bit.green;
2887
2888 if (png_ptr->sig_bit.blue > sig_bit)
2889 sig_bit = png_ptr->sig_bit.blue;
2890 }
2891 else
2892 sig_bit = png_ptr->sig_bit.gray;
2893
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002894 /* 16-bit gamma code uses this equation:
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002895 *
2896 * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
2897 *
2898 * Where 'iv' is the input color value and 'ov' is the output value -
2899 * pow(iv, gamma).
2900 *
2901 * Thus the gamma table consists of up to 256 256 entry tables. The table
2902 * is selected by the (8-gamma_shift) most significant of the low 8 bits of
2903 * the color value then indexed by the upper 8 bits:
2904 *
2905 * table[low bits][high 8 bits]
2906 *
2907 * So the table 'n' corresponds to all those 'iv' of:
2908 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002909 * <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002910 *
2911 */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05002912 if (sig_bit > 0 && sig_bit < 16U)
2913 shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002914
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002915 else
2916 shift = 0; /* keep all 16 bits */
2917
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05002918 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002919 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002920 /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
2921 * the significant bits in the *input* when the output will
2922 * eventually be 8 bits. By default it is 11.
2923 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002924 if (shift < (16U - PNG_MAX_GAMMA_8))
2925 shift = (16U - PNG_MAX_GAMMA_8);
2926 }
2927
2928 if (shift > 8U)
2929 shift = 8U; /* Guarantees at least one table! */
2930
2931 png_ptr->gamma_shift = shift;
2932
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05002933#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrsonef217b72011-06-15 12:58:27 -05002934 /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
John Bowlerd273ad22011-05-07 21:00:28 -05002935 * PNG_COMPOSE). This effectively smashed the background calculation for
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05002936 * 16-bit output because the 8-bit table assumes the result will be reduced
John Bowlerd273ad22011-05-07 21:00:28 -05002937 * to 8 bits.
2938 */
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05002939 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05002940#endif
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002941 png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
2942 png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma,
2943 png_ptr->screen_gamma) : PNG_FP_1);
2944
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05002945#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002946 else
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002947 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
2948 png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
2949 png_ptr->screen_gamma) : PNG_FP_1);
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05002950#endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002951
2952#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
John Bowlerd273ad22011-05-07 21:00:28 -05002953 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002954 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
John Bowlerd273ad22011-05-07 21:00:28 -05002955 if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002956 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002957 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002958 png_reciprocal(png_ptr->gamma));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002959
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002960 /* Notice that the '16 from 1' table should be full precision, however
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002961 * the lookup on this table still uses gamma_shift, so it can't be.
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002962 * TODO: fix this.
2963 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002964 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002965 png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
2966 png_ptr->gamma/* Probably doing rgb_to_gray */);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002967 }
John Bowlerd273ad22011-05-07 21:00:28 -05002968#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002969 }
2970}
2971#endif /* READ_GAMMA */
John Bowler7875d532011-11-07 22:33:49 -06002972
2973/* sRGB support */
2974#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
2975 defined PNG_SIMPLIFIED_WRITE_SUPPORTED
John Bowler0a521d32011-11-11 18:14:59 -06002976/* sRGB conversion tables; these are machine generated with the code in
Glenn Randers-Pehrson5578c372012-02-04 10:31:38 -06002977 * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
2978 * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
2979 * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
2980 * The sRGB to linear table is exact (to the nearest 16 bit linear fraction).
2981 * The inverse (linear to sRGB) table has accuracies as follows:
John Bowler0a521d32011-11-11 18:14:59 -06002982 *
2983 * For all possible (255*65535+1) input values:
2984 *
2985 * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
2986 *
2987 * For the input values corresponding to the 65536 16-bit values:
2988 *
2989 * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
2990 *
2991 * In all cases the inexact readings are off by one.
John Bowler7875d532011-11-07 22:33:49 -06002992 */
John Bowler7875d532011-11-07 22:33:49 -06002993
2994#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
2995/* The convert-to-sRGB table is only currently required for read. */
John Bowler572b0782012-01-31 07:09:34 -06002996const png_uint_16 png_sRGB_table[256] =
John Bowler7875d532011-11-07 22:33:49 -06002997{
2998 0,20,40,60,80,99,119,139,
2999 159,179,199,219,241,264,288,313,
3000 340,367,396,427,458,491,526,562,
3001 599,637,677,718,761,805,851,898,
3002 947,997,1048,1101,1156,1212,1270,1330,
3003 1391,1453,1517,1583,1651,1720,1790,1863,
3004 1937,2013,2090,2170,2250,2333,2418,2504,
3005 2592,2681,2773,2866,2961,3058,3157,3258,
3006 3360,3464,3570,3678,3788,3900,4014,4129,
3007 4247,4366,4488,4611,4736,4864,4993,5124,
3008 5257,5392,5530,5669,5810,5953,6099,6246,
3009 6395,6547,6700,6856,7014,7174,7335,7500,
3010 7666,7834,8004,8177,8352,8528,8708,8889,
3011 9072,9258,9445,9635,9828,10022,10219,10417,
3012 10619,10822,11028,11235,11446,11658,11873,12090,
3013 12309,12530,12754,12980,13209,13440,13673,13909,
3014 14146,14387,14629,14874,15122,15371,15623,15878,
3015 16135,16394,16656,16920,17187,17456,17727,18001,
3016 18277,18556,18837,19121,19407,19696,19987,20281,
3017 20577,20876,21177,21481,21787,22096,22407,22721,
3018 23038,23357,23678,24002,24329,24658,24990,25325,
3019 25662,26001,26344,26688,27036,27386,27739,28094,
3020 28452,28813,29176,29542,29911,30282,30656,31033,
3021 31412,31794,32179,32567,32957,33350,33745,34143,
3022 34544,34948,35355,35764,36176,36591,37008,37429,
3023 37852,38278,38706,39138,39572,40009,40449,40891,
3024 41337,41785,42236,42690,43147,43606,44069,44534,
3025 45002,45473,45947,46423,46903,47385,47871,48359,
3026 48850,49344,49841,50341,50844,51349,51858,52369,
3027 52884,53401,53921,54445,54971,55500,56032,56567,
3028 57105,57646,58190,58737,59287,59840,60396,60955,
3029 61517,62082,62650,63221,63795,64372,64952,65535
3030};
John Bowler0a521d32011-11-11 18:14:59 -06003031
John Bowler7875d532011-11-07 22:33:49 -06003032#endif /* simplified read only */
3033
3034/* The base/delta tables are required for both read and write (but currently
3035 * only the simplified versions.)
3036 */
John Bowler572b0782012-01-31 07:09:34 -06003037const png_uint_16 png_sRGB_base[512] =
John Bowler7875d532011-11-07 22:33:49 -06003038{
John Bowler0a521d32011-11-11 18:14:59 -06003039 128,1782,3383,4644,5675,6564,7357,8074,
3040 8732,9346,9921,10463,10977,11466,11935,12384,
3041 12816,13233,13634,14024,14402,14769,15125,15473,
3042 15812,16142,16466,16781,17090,17393,17690,17981,
John Bowler7875d532011-11-07 22:33:49 -06003043 18266,18546,18822,19093,19359,19621,19879,20133,
John Bowler0a521d32011-11-11 18:14:59 -06003044 20383,20630,20873,21113,21349,21583,21813,22041,
3045 22265,22487,22707,22923,23138,23350,23559,23767,
John Bowler7875d532011-11-07 22:33:49 -06003046 23972,24175,24376,24575,24772,24967,25160,25352,
John Bowler0a521d32011-11-11 18:14:59 -06003047 25542,25730,25916,26101,26284,26465,26645,26823,
3048 27000,27176,27350,27523,27695,27865,28034,28201,
John Bowler7875d532011-11-07 22:33:49 -06003049 28368,28533,28697,28860,29021,29182,29341,29500,
John Bowler0a521d32011-11-11 18:14:59 -06003050 29657,29813,29969,30123,30276,30429,30580,30730,
John Bowler7875d532011-11-07 22:33:49 -06003051 30880,31028,31176,31323,31469,31614,31758,31902,
John Bowler0a521d32011-11-11 18:14:59 -06003052 32045,32186,32327,32468,32607,32746,32884,33021,
3053 33158,33294,33429,33564,33697,33831,33963,34095,
3054 34226,34357,34486,34616,34744,34873,35000,35127,
John Bowler7875d532011-11-07 22:33:49 -06003055 35253,35379,35504,35629,35753,35876,35999,36122,
3056 36244,36365,36486,36606,36726,36845,36964,37083,
John Bowler0a521d32011-11-11 18:14:59 -06003057 37201,37318,37435,37551,37668,37783,37898,38013,
John Bowler7875d532011-11-07 22:33:49 -06003058 38127,38241,38354,38467,38580,38692,38803,38915,
John Bowler0a521d32011-11-11 18:14:59 -06003059 39026,39136,39246,39356,39465,39574,39682,39790,
John Bowler7875d532011-11-07 22:33:49 -06003060 39898,40005,40112,40219,40325,40431,40537,40642,
3061 40747,40851,40955,41059,41163,41266,41369,41471,
John Bowler0a521d32011-11-11 18:14:59 -06003062 41573,41675,41777,41878,41979,42079,42179,42279,
3063 42379,42478,42577,42676,42775,42873,42971,43068,
3064 43165,43262,43359,43456,43552,43648,43743,43839,
3065 43934,44028,44123,44217,44311,44405,44499,44592,
3066 44685,44778,44870,44962,45054,45146,45238,45329,
John Bowler7875d532011-11-07 22:33:49 -06003067 45420,45511,45601,45692,45782,45872,45961,46051,
John Bowler0a521d32011-11-11 18:14:59 -06003068 46140,46229,46318,46406,46494,46583,46670,46758,
3069 46846,46933,47020,47107,47193,47280,47366,47452,
3070 47538,47623,47709,47794,47879,47964,48048,48133,
3071 48217,48301,48385,48468,48552,48635,48718,48801,
3072 48884,48966,49048,49131,49213,49294,49376,49458,
3073 49539,49620,49701,49782,49862,49943,50023,50103,
3074 50183,50263,50342,50422,50501,50580,50659,50738,
3075 50816,50895,50973,51051,51129,51207,51285,51362,
3076 51439,51517,51594,51671,51747,51824,51900,51977,
3077 52053,52129,52205,52280,52356,52432,52507,52582,
John Bowler7875d532011-11-07 22:33:49 -06003078 52657,52732,52807,52881,52956,53030,53104,53178,
John Bowler0a521d32011-11-11 18:14:59 -06003079 53252,53326,53400,53473,53546,53620,53693,53766,
John Bowler7875d532011-11-07 22:33:49 -06003080 53839,53911,53984,54056,54129,54201,54273,54345,
3081 54417,54489,54560,54632,54703,54774,54845,54916,
John Bowler0a521d32011-11-11 18:14:59 -06003082 54987,55058,55129,55199,55269,55340,55410,55480,
3083 55550,55620,55689,55759,55828,55898,55967,56036,
3084 56105,56174,56243,56311,56380,56448,56517,56585,
John Bowler7875d532011-11-07 22:33:49 -06003085 56653,56721,56789,56857,56924,56992,57059,57127,
3086 57194,57261,57328,57395,57462,57529,57595,57662,
3087 57728,57795,57861,57927,57993,58059,58125,58191,
3088 58256,58322,58387,58453,58518,58583,58648,58713,
3089 58778,58843,58908,58972,59037,59101,59165,59230,
3090 59294,59358,59422,59486,59549,59613,59677,59740,
3091 59804,59867,59930,59993,60056,60119,60182,60245,
3092 60308,60370,60433,60495,60558,60620,60682,60744,
3093 60806,60868,60930,60992,61054,61115,61177,61238,
3094 61300,61361,61422,61483,61544,61605,61666,61727,
John Bowler0a521d32011-11-11 18:14:59 -06003095 61788,61848,61909,61969,62030,62090,62150,62211,
John Bowler7875d532011-11-07 22:33:49 -06003096 62271,62331,62391,62450,62510,62570,62630,62689,
3097 62749,62808,62867,62927,62986,63045,63104,63163,
John Bowler0a521d32011-11-11 18:14:59 -06003098 63222,63281,63340,63398,63457,63515,63574,63632,
John Bowler7875d532011-11-07 22:33:49 -06003099 63691,63749,63807,63865,63923,63981,64039,64097,
John Bowler0a521d32011-11-11 18:14:59 -06003100 64155,64212,64270,64328,64385,64443,64500,64557,
3101 64614,64672,64729,64786,64843,64900,64956,65013,
3102 65070,65126,65183,65239,65296,65352,65409,65465
John Bowler7875d532011-11-07 22:33:49 -06003103};
3104
John Bowler572b0782012-01-31 07:09:34 -06003105const png_byte png_sRGB_delta[512] =
John Bowler7875d532011-11-07 22:33:49 -06003106{
John Bowler0a521d32011-11-11 18:14:59 -06003107 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
John Bowler7875d532011-11-07 22:33:49 -06003108 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
3109 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
John Bowler0a521d32011-11-11 18:14:59 -06003110 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
John Bowler7875d532011-11-07 22:33:49 -06003111 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
3112 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
3113 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
3114 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
3115 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
3116 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
3117 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
3118 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
3119 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
3120 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
3121 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
3122 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
3123 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
3124 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
3125 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
3126 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
3127 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
3128 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
3129 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
3130 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
3131 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
3132 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
3133 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
3134 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
3135 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
3136 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
3137 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
3138 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
3139};
John Bowler7875d532011-11-07 22:33:49 -06003140#endif /* SIMPLIFIED READ/WRITE sRGB support */
3141
3142/* SIMPLIFIED READ/WRITE SUPPORT */
3143#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
3144 defined PNG_SIMPLIFIED_WRITE_SUPPORTED
3145static int
3146png_image_free_function(png_voidp argument)
3147{
John Bowler4fa96a42011-11-16 16:39:16 -06003148 png_imagep image = png_voidcast(png_imagep, argument);
John Bowler7875d532011-11-07 22:33:49 -06003149 png_controlp cp = image->opaque;
3150 png_control c;
3151
3152 /* Double check that we have a png_ptr - it should be impossible to get here
3153 * without one.
3154 */
3155 if (cp->png_ptr == NULL)
3156 return 0;
3157
3158 /* First free any data held in the control structure. */
3159# ifdef PNG_STDIO_SUPPORTED
3160 if (cp->owned_file)
3161 {
John Bowler4fa96a42011-11-16 16:39:16 -06003162 FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
John Bowler7875d532011-11-07 22:33:49 -06003163 cp->owned_file = 0;
3164
3165 /* Ignore errors here. */
3166 if (fp != NULL)
3167 {
3168 cp->png_ptr->io_ptr = NULL;
3169 (void)fclose(fp);
3170 }
3171 }
3172# endif
3173
3174 /* Copy the control structure so that the original, allocated, version can be
3175 * safely freed. Notice that a png_error here stops the remainder of the
3176 * cleanup, but this is probably fine because that would indicate bad memory
3177 * problems anyway.
3178 */
3179 c = *cp;
3180 image->opaque = &c;
3181 png_free(c.png_ptr, cp);
3182
3183 /* Then the structures, calling the correct API. */
3184 if (c.for_write)
3185 {
3186# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
3187 png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
3188# else
3189 png_error(c.png_ptr, "simplified write not supported");
3190# endif
3191 }
3192 else
3193 {
3194# ifdef PNG_SIMPLIFIED_READ_SUPPORTED
3195 png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
3196# else
3197 png_error(c.png_ptr, "simplified read not supported");
3198# endif
3199 }
3200
3201 /* Success. */
3202 return 1;
3203}
3204
3205void PNGAPI
3206png_image_free(png_imagep image)
3207{
3208 /* Safely call the real function, but only if doing so is safe at this point
3209 * (if not inside an error handling context). Otherwise assume
3210 * png_safe_execute will call this API after the return.
3211 */
3212 if (image != NULL && image->opaque != NULL &&
3213 image->opaque->error_buf == NULL)
3214 {
3215 /* Ignore errors here: */
3216 (void)png_safe_execute(image, png_image_free_function, image);
3217 image->opaque = NULL;
3218 }
3219}
3220
3221int /* PRIVATE */
3222png_image_error(png_imagep image, png_const_charp error_message)
3223{
3224 /* Utility to log an error. */
3225 png_safecat(image->message, sizeof image->message, 0, error_message);
John Bowler04336ba2012-01-16 07:48:36 -06003226 image->warning_or_error |= PNG_IMAGE_ERROR;
John Bowler7875d532011-11-07 22:33:49 -06003227 png_image_free(image);
3228 return 0;
3229}
3230
3231#endif /* SIMPLIFIED READ/WRITE */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003232#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */