blob: f33c1fc8c697ae08959da14b665de7359989503c [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-Pehrsonb593b3f2012-08-11 18:15:41 -050017typedef png_libpng_version_1_6_0beta28 Your_png_h_is_not_version_1_6_0beta28;
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-Pehrsondbb7e192012-08-10 17:27:42 -050065 return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060066}
67
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060068#endif /* PNG_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050069
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060070#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrsonc5080812010-10-23 08:26:26 -050071/* Function to allocate memory for zlib */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -050072PNG_FUNCTION(voidpf /* PRIVATE */,
73png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
Guy Schalnat0d580581995-07-20 02:43:20 -050074{
John Bowlerd332c672011-12-21 17:36:12 -060075 png_alloc_size_t num_bytes = size;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050076
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050077 if (png_ptr == NULL)
John Bowlerd332c672011-12-21 17:36:12 -060078 return NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050079
John Bowlerd332c672011-12-21 17:36:12 -060080 if (items >= (~(png_alloc_size_t)0)/size)
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050081 {
John Bowler5d567862011-12-24 09:12:00 -060082 png_warning (png_voidcast(png_structrp, png_ptr),
John Bowlerd332c672011-12-21 17:36:12 -060083 "Potential overflow in png_zalloc()");
84 return NULL;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050085 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -060086
John Bowlerd332c672011-12-21 17:36:12 -060087 num_bytes *= items;
John Bowler5d567862011-12-24 09:12:00 -060088 return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050089}
90
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050091/* Function to free memory for zlib */
Glenn Randers-Pehrson3f705ba2009-07-23 12:53:06 -050092void /* PRIVATE */
Guy Schalnat51f0eb41995-09-26 05:22:39 -050093png_zfree(voidpf png_ptr, voidpf ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050094{
John Bowler5d567862011-12-24 09:12:00 -060095 png_free(png_voidcast(png_const_structrp,png_ptr), ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -050096}
97
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060098/* Reset the CRC variable to 32 bits of 1's. Care must be taken
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060099 * in case CRC is > 32 bits to leave the top bits 0.
100 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500101void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600102png_reset_crc(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500103{
John Bowlerf3f7e142011-09-09 07:32:37 -0500104 /* The cast is safe because the crc is a 32 bit value. */
105 png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500106}
107
Andreas Dilger47a0c421997-05-16 02:46:07 -0500108/* Calculate the CRC over a section of data. We can only pass as
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600109 * much data to this routine as the largest single buffer size. We
110 * also check that this data will actually be used before going to the
111 * trouble of calculating it.
112 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500113void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600114png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500115{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500116 int need_crc = 1;
117
Glenn Randers-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 {
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -0500142 uInt safe_length = (uInt)length;
143 if (safe_length == 0)
144 safe_length = (uInt)-1; /* evil, but safe */
John Bowlerf3f7e142011-09-09 07:32:37 -0500145
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -0500146 crc = crc32(crc, ptr, safe_length);
John Bowlerf3f7e142011-09-09 07:32:37 -0500147
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 */
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -0500152 ptr += safe_length;
153 length -= safe_length;
John Bowlerf3f7e142011-09-09 07:32:37 -0500154 }
155 while (length > 0);
156
157 /* And the following is always safe because the crc is only 32 bits. */
158 png_ptr->crc = (png_uint_32)crc;
159 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500160}
Guy Schalnate5a37791996-06-05 15:50:50 -0500161
John Bowler88b77cc2011-05-05 06:49:55 -0500162/* Check a user supplied version number, called from both read and write
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
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -0500197 pos = png_safecat(m, (sizeof m), pos,
198 "Application built with libpng-");
199 pos = png_safecat(m, (sizeof m), pos, user_png_ver);
200 pos = png_safecat(m, (sizeof m), pos, " but running with ");
201 pos = png_safecat(m, (sizeof m), pos, png_libpng_ver);
John Bowler88b77cc2011-05-05 06:49:55 -0500202
203 png_warning(png_ptr, m);
204#endif
205
206#ifdef PNG_ERROR_NUMBERS_SUPPORTED
207 png_ptr->flags = 0;
208#endif
209
210 return 0;
211 }
212 }
213
214 /* Success return. */
215 return 1;
216}
217
John Bowlerd332c672011-12-21 17:36:12 -0600218/* Generic function to create a png_struct for either read or write - this
219 * contains the common initialization.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600220 */
John Bowlerd332c672011-12-21 17:36:12 -0600221PNG_FUNCTION(png_structp /* PRIVATE */,
222png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
223 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
224 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
225{
226 png_struct create_struct;
227# ifdef PNG_SETJMP_SUPPORTED
228 jmp_buf create_jmp_buf;
229# endif
230
231 /* This temporary stack-allocated structure is used to provide a place to
232 * build enough context to allow the user provided memory allocator (if any)
233 * to be called.
234 */
Glenn Randers-Pehrsondbb7e192012-08-10 17:27:42 -0500235 memset(&create_struct, 0, (sizeof create_struct));
John Bowlerd332c672011-12-21 17:36:12 -0600236
237 /* Added at libpng-1.2.6 */
238# ifdef PNG_USER_LIMITS_SUPPORTED
239 create_struct.user_width_max = PNG_USER_WIDTH_MAX;
240 create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
241
242# ifdef PNG_USER_CHUNK_CACHE_MAX
243 /* Added at libpng-1.2.43 and 1.4.0 */
244 create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
245# endif
246
247# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
248 /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
249 * in png_struct regardless.
250 */
251 create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
252# endif
253# endif
254
255 /* The following two API calls simply set fields in png_struct, so it is safe
256 * to do them now even though error handling is not yet set up.
257 */
258# ifdef PNG_USER_MEM_SUPPORTED
259 png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
260# endif
261
262 /* (*error_fn) can return control to the caller after the error_ptr is set,
263 * this will result in a memory leak unless the error_fn does something
264 * extremely sophisticated. The design lacks merit but is implicit in the
265 * API.
266 */
267 png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
268
269# ifdef PNG_SETJMP_SUPPORTED
270 if (!setjmp(create_jmp_buf))
271 {
272 /* Temporarily fake out the longjmp information until we have
273 * successfully completed this function. This only works if we have
274 * setjmp() support compiled in, but it is safe - this stuff should
275 * never happen.
276 */
277 create_struct.jmp_buf_ptr = &create_jmp_buf;
278 create_struct.jmp_buf_size = 0; /*stack allocation*/
279 create_struct.longjmp_fn = longjmp;
280# else
281 {
282# endif
283 /* Call the general version checker (shared with read and write code):
284 */
285 if (png_user_version_check(&create_struct, user_png_ver))
286 {
John Bowlerb5d00512012-03-09 09:15:18 -0600287 png_structrp png_ptr = png_voidcast(png_structrp,
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -0500288 png_malloc_warn(&create_struct, (sizeof *png_ptr)));
John Bowlerd332c672011-12-21 17:36:12 -0600289
John Bowlerb5d00512012-03-09 09:15:18 -0600290 if (png_ptr != NULL)
John Bowlerd332c672011-12-21 17:36:12 -0600291 {
John Bowlerb5d00512012-03-09 09:15:18 -0600292 /* png_ptr->zstream holds a back-pointer to the png_struct, so
293 * this can only be done now:
294 */
295 create_struct.zstream.zalloc = png_zalloc;
296 create_struct.zstream.zfree = png_zfree;
297 create_struct.zstream.opaque = png_ptr;
John Bowlerd332c672011-12-21 17:36:12 -0600298
John Bowlerb5d00512012-03-09 09:15:18 -0600299# ifdef PNG_SETJMP_SUPPORTED
300 /* Eliminate the local error handling: */
301 create_struct.jmp_buf_ptr = NULL;
302 create_struct.jmp_buf_size = 0;
303 create_struct.longjmp_fn = 0;
304# endif
John Bowlerd332c672011-12-21 17:36:12 -0600305
John Bowlerb5d00512012-03-09 09:15:18 -0600306 *png_ptr = create_struct;
John Bowlerd332c672011-12-21 17:36:12 -0600307
John Bowlerb5d00512012-03-09 09:15:18 -0600308 /* This is the successful return point */
309 return png_ptr;
John Bowlerd332c672011-12-21 17:36:12 -0600310 }
311 }
312 }
313
314 /* A longjmp because of a bug in the application storage allocator or a
315 * simple failure to allocate the png_struct.
316 */
John Bowlerd332c672011-12-21 17:36:12 -0600317 return NULL;
318}
319
320/* Allocate the memory for an info_struct for the application. */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -0500321PNG_FUNCTION(png_infop,PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600322png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500323{
John Bowler5d567862011-12-24 09:12:00 -0600324 png_inforp info_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500325
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500326 png_debug(1, "in png_create_info_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500327
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500328 if (png_ptr == NULL)
John Bowlerd332c672011-12-21 17:36:12 -0600329 return NULL;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500330
John Bowlerd332c672011-12-21 17:36:12 -0600331 /* Use the internal API that does not (or at least should not) error out, so
332 * that this call always returns ok. The application typically sets up the
333 * error handling *after* creating the info_struct because this is the way it
334 * has always been done in 'example.c'.
335 */
John Bowler5d567862011-12-24 09:12:00 -0600336 info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -0500337 (sizeof *info_ptr)));
John Bowlerd332c672011-12-21 17:36:12 -0600338
Glenn Randers-Pehrson5cded0b2001-11-07 07:10:08 -0600339 if (info_ptr != NULL)
Glenn Randers-Pehrsondbb7e192012-08-10 17:27:42 -0500340 memset(info_ptr, 0, (sizeof *info_ptr));
Guy Schalnate5a37791996-06-05 15:50:50 -0500341
John Bowlerd332c672011-12-21 17:36:12 -0600342 return info_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500343}
344
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600345/* This function frees the memory associated with a single info struct.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600346 * Normally, one would use either png_destroy_read_struct() or
347 * png_destroy_write_struct() to free an info struct, but this may be
John Bowlerd332c672011-12-21 17:36:12 -0600348 * useful for some applications. From libpng 1.6.0 this function is also used
349 * internally to implement the png_info release part of the 'struct' destroy
350 * APIs. This ensures that all possible approaches free the same data (all of
351 * it).
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600352 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500353void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600354png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600355{
John Bowler5d567862011-12-24 09:12:00 -0600356 png_inforp info_ptr = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600357
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500358 png_debug(1, "in png_destroy_info_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500359
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500360 if (png_ptr == NULL)
361 return;
362
Andreas Dilger47a0c421997-05-16 02:46:07 -0500363 if (info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600364 info_ptr = *info_ptr_ptr;
365
Andreas Dilger47a0c421997-05-16 02:46:07 -0500366 if (info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600367 {
John Bowlerd332c672011-12-21 17:36:12 -0600368 /* Do this first in case of an error below; if the app implements its own
369 * memory management this can lead to png_free calling png_error, which
370 * will abort this routine and return control to the app error handler.
371 * An infinite loop may result if it then tries to free the same info
372 * ptr.
373 */
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -0500374 *info_ptr_ptr = NULL;
John Bowlerd332c672011-12-21 17:36:12 -0600375
John Bowlerdf477e42011-12-24 07:47:02 -0600376 png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
Glenn Randers-Pehrsondbb7e192012-08-10 17:27:42 -0500377 memset(info_ptr, 0, (sizeof *info_ptr));
John Bowlerd332c672011-12-21 17:36:12 -0600378 png_free(png_ptr, info_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600379 }
380}
381
382/* Initialize the info structure. This is now an internal function (0.89)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600383 * and applications using it are urged to use png_create_info_struct()
John Bowlerd332c672011-12-21 17:36:12 -0600384 * instead. Use deprecated in 1.6.0, internal use removed (used internally it
385 * is just a memset).
386 *
387 * NOTE: it is almost inconceivable that this API is used because it bypasses
388 * the user-memory mechanism and the user error handling/warning mechanisms in
389 * those cases where it does anything other than a memset.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600390 */
John Bowlerd332c672011-12-21 17:36:12 -0600391PNG_FUNCTION(void,PNGAPI
392png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
393 PNG_DEPRECATED)
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500394{
John Bowler5d567862011-12-24 09:12:00 -0600395 png_inforp info_ptr = *ptr_ptr;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500396
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500397 png_debug(1, "in png_info_init_3");
398
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500399 if (info_ptr == NULL)
400 return;
Glenn Randers-Pehrson6b12c082006-11-14 10:53:30 -0600401
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -0500402 if ((sizeof (png_info)) > png_info_struct_size)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500403 {
John Bowlerd332c672011-12-21 17:36:12 -0600404 *ptr_ptr = NULL;
405 /* The following line is why this API should not be used: */
406 free(info_ptr);
John Bowler5d567862011-12-24 09:12:00 -0600407 info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -0500408 (sizeof *info_ptr)));
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500409 *ptr_ptr = info_ptr;
410 }
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500411
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500412 /* Set everything to 0 */
Glenn Randers-Pehrsondbb7e192012-08-10 17:27:42 -0500413 memset(info_ptr, 0, (sizeof *info_ptr));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600414}
415
John Bowlerb11b31a2012-03-21 07:55:46 -0500416/* The following API is not called internally */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500417void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600418png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500419 int freer, png_uint_32 mask)
420{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500421 png_debug(1, "in png_data_freer");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500422
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500423 if (png_ptr == NULL || info_ptr == NULL)
424 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500425
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500426 if (freer == PNG_DESTROY_WILL_FREE_DATA)
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500427 info_ptr->free_me |= mask;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500428
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500429 else if (freer == PNG_USER_WILL_FREE_DATA)
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500430 info_ptr->free_me &= ~mask;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500431
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500432 else
John Bowlerb11b31a2012-03-21 07:55:46 -0500433 png_error(png_ptr, "Unknown freer parameter in png_data_freer");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500434}
435
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500436void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600437png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500438 int num)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600439{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500440 png_debug(1, "in png_free_data");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500441
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600442 if (png_ptr == NULL || info_ptr == NULL)
443 return;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600444
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500445#ifdef PNG_TEXT_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500446 /* Free text item num or (if num == -1) all text items */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500447 if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600448 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500449 if (num != -1)
450 {
451 if (info_ptr->text && info_ptr->text[num].key)
452 {
453 png_free(png_ptr, info_ptr->text[num].key);
454 info_ptr->text[num].key = NULL;
455 }
456 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500457
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500458 else
459 {
460 int i;
461 for (i = 0; i < info_ptr->num_text; i++)
462 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
463 png_free(png_ptr, info_ptr->text);
464 info_ptr->text = NULL;
465 info_ptr->num_text=0;
466 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600467 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600468#endif
469
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500470#ifdef PNG_tRNS_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500471 /* Free any tRNS entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500472 if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500473 {
Glenn Randers-Pehrson6abea752009-08-08 16:52:06 -0500474 png_free(png_ptr, info_ptr->trans_alpha);
475 info_ptr->trans_alpha = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500476 info_ptr->valid &= ~PNG_INFO_tRNS;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500477 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600478#endif
479
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500480#ifdef PNG_sCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500481 /* Free any sCAL entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500482 if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500483 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500484 png_free(png_ptr, info_ptr->scal_s_width);
485 png_free(png_ptr, info_ptr->scal_s_height);
486 info_ptr->scal_s_width = NULL;
487 info_ptr->scal_s_height = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500488 info_ptr->valid &= ~PNG_INFO_sCAL;
489 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600490#endif
491
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500492#ifdef PNG_pCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500493 /* Free any pCAL entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500494 if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500495 {
496 png_free(png_ptr, info_ptr->pcal_purpose);
497 png_free(png_ptr, info_ptr->pcal_units);
498 info_ptr->pcal_purpose = NULL;
499 info_ptr->pcal_units = NULL;
500 if (info_ptr->pcal_params != NULL)
501 {
502 int i;
503 for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
504 {
505 png_free(png_ptr, info_ptr->pcal_params[i]);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600506 info_ptr->pcal_params[i] = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500507 }
508 png_free(png_ptr, info_ptr->pcal_params);
509 info_ptr->pcal_params = NULL;
510 }
511 info_ptr->valid &= ~PNG_INFO_pCAL;
512 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600513#endif
514
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500515#ifdef PNG_iCCP_SUPPORTED
John Bowlerb11b31a2012-03-21 07:55:46 -0500516 /* Free any profile entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500517 if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500518 {
519 png_free(png_ptr, info_ptr->iccp_name);
520 png_free(png_ptr, info_ptr->iccp_profile);
521 info_ptr->iccp_name = NULL;
522 info_ptr->iccp_profile = NULL;
523 info_ptr->valid &= ~PNG_INFO_iCCP;
524 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600525#endif
526
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500527#ifdef PNG_sPLT_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500528 /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500529 if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600530 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500531 if (num != -1)
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500532 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500533 if (info_ptr->splt_palettes)
534 {
535 png_free(png_ptr, info_ptr->splt_palettes[num].name);
536 png_free(png_ptr, info_ptr->splt_palettes[num].entries);
537 info_ptr->splt_palettes[num].name = NULL;
538 info_ptr->splt_palettes[num].entries = NULL;
539 }
540 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500541
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500542 else
543 {
544 if (info_ptr->splt_palettes_num)
545 {
546 int i;
547 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
548 png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
549
550 png_free(png_ptr, info_ptr->splt_palettes);
551 info_ptr->splt_palettes = NULL;
552 info_ptr->splt_palettes_num = 0;
553 }
554 info_ptr->valid &= ~PNG_INFO_sPLT;
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500555 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600556 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600557#endif
558
John Bowlere9567512012-08-15 22:53:00 -0500559#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500560 if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600561 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500562 if (num != -1)
563 {
564 if (info_ptr->unknown_chunks)
565 {
566 png_free(png_ptr, info_ptr->unknown_chunks[num].data);
567 info_ptr->unknown_chunks[num].data = NULL;
568 }
569 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500570
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500571 else
572 {
John Bowlere9567512012-08-15 22:53:00 -0500573 unsigned int i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600574
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500575 if (info_ptr->unknown_chunks_num)
576 {
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -0500577 for (i = 0; i < info_ptr->unknown_chunks_num; i++)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500578 png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600579
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500580 png_free(png_ptr, info_ptr->unknown_chunks);
581 info_ptr->unknown_chunks = NULL;
582 info_ptr->unknown_chunks_num = 0;
583 }
584 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600585 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600586#endif
587
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500588#ifdef PNG_hIST_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500589 /* Free any hIST entry */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500590 if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500591 {
592 png_free(png_ptr, info_ptr->hist);
593 info_ptr->hist = NULL;
594 info_ptr->valid &= ~PNG_INFO_hIST;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500595 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600596#endif
597
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500598 /* Free any PLTE entry that was internally allocated */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500599 if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500600 {
John Bowler40b26032011-12-22 08:09:15 -0600601 png_free(png_ptr, info_ptr->palette);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500602 info_ptr->palette = NULL;
603 info_ptr->valid &= ~PNG_INFO_PLTE;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500604 info_ptr->num_palette = 0;
605 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600606
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500607#ifdef PNG_INFO_IMAGE_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500608 /* Free any image bits attached to the info structure */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500609 if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500610 {
611 if (info_ptr->row_pointers)
612 {
613 int row;
614 for (row = 0; row < (int)info_ptr->height; row++)
615 {
616 png_free(png_ptr, info_ptr->row_pointers[row]);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600617 info_ptr->row_pointers[row] = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500618 }
619 png_free(png_ptr, info_ptr->row_pointers);
Glenn Randers-Pehrsonf81b50b2009-12-29 16:50:15 -0600620 info_ptr->row_pointers = NULL;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500621 }
622 info_ptr->valid &= ~PNG_INFO_IDAT;
623 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600624#endif
Glenn Randers-Pehrsonfc4a1432000-05-17 17:39:34 -0500625
John Bowler56a739b2010-12-19 16:33:20 -0600626 if (num != -1)
627 mask &= ~PNG_FREE_MUL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500628
John Bowler56a739b2010-12-19 16:33:20 -0600629 info_ptr->free_me &= ~mask;
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600630}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600631#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500632
Guy Schalnate5a37791996-06-05 15:50:50 -0500633/* This function returns a pointer to the io_ptr associated with the user
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600634 * functions. The application should free any memory associated with this
635 * pointer before png_write_destroy() or png_read_destroy() are called.
636 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500637png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600638png_get_io_ptr(png_const_structrp png_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500639{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500640 if (png_ptr == NULL)
641 return (NULL);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500642
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600643 return (png_ptr->io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500644}
Andreas Dilger47a0c421997-05-16 02:46:07 -0500645
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600646#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600647# ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500648/* Initialize the default input/output functions for the PNG file. If you
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600649 * use your own read or write routines, you can call either png_set_read_fn()
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500650 * or png_set_write_fn() instead of png_init_io(). If you have defined
Glenn Randers-Pehrsonce775cc2011-07-13 06:28:26 -0500651 * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
652 * function of your own because "FILE *" isn't necessarily available.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600653 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500654void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600655png_init_io(png_structrp png_ptr, png_FILE_p fp)
Guy Schalnate5a37791996-06-05 15:50:50 -0500656{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500657 png_debug(1, "in png_init_io");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500658
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500659 if (png_ptr == NULL)
660 return;
Glenn Randers-Pehrsonb3ce3652009-08-15 21:47:03 -0500661
Guy Schalnate5a37791996-06-05 15:50:50 -0500662 png_ptr->io_ptr = (png_voidp)fp;
663}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600664# endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500665
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600666# ifdef PNG_TIME_RFC1123_SUPPORTED
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500667/* Convert the supplied time into an RFC 1123 string suitable for use in
668 * a "Creation Time" or other text-based time string.
669 */
John Bowler40b26032011-12-22 08:09:15 -0600670int PNGAPI
671png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500672{
673 static PNG_CONST char short_months[12][4] =
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600674 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
675 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500676
John Bowler40b26032011-12-22 08:09:15 -0600677 if (out == NULL)
678 return 0;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500679
Glenn Randers-Pehrson925a6022011-11-19 18:04:01 -0600680 if (ptime->year > 9999 /* RFC1123 limitation */ ||
681 ptime->month == 0 || ptime->month > 12 ||
682 ptime->day == 0 || ptime->day > 31 ||
683 ptime->hour > 23 || ptime->minute > 59 ||
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600684 ptime->second > 60)
John Bowler40b26032011-12-22 08:09:15 -0600685 return 0;
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600686
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500687 {
John Bowler88b77cc2011-05-05 06:49:55 -0500688 size_t pos = 0;
Glenn Randers-Pehrson925a6022011-11-19 18:04:01 -0600689 char number_buf[5]; /* enough for a four-digit year */
John Bowler88b77cc2011-05-05 06:49:55 -0500690
John Bowler40b26032011-12-22 08:09:15 -0600691# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
John Bowler88b77cc2011-05-05 06:49:55 -0500692# define APPEND_NUMBER(format, value)\
693 APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
John Bowler40b26032011-12-22 08:09:15 -0600694# define APPEND(ch) if (pos < 28) out[pos++] = (ch)
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500695
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600696 APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
John Bowler88b77cc2011-05-05 06:49:55 -0500697 APPEND(' ');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600698 APPEND_STRING(short_months[(ptime->month - 1)]);
John Bowler88b77cc2011-05-05 06:49:55 -0500699 APPEND(' ');
700 APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
701 APPEND(' ');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600702 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
John Bowler88b77cc2011-05-05 06:49:55 -0500703 APPEND(':');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600704 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
John Bowler88b77cc2011-05-05 06:49:55 -0500705 APPEND(':');
Glenn Randers-Pehrson29fca792011-11-19 15:08:04 -0600706 APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
John Bowler88b77cc2011-05-05 06:49:55 -0500707 APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
708
709# undef APPEND
710# undef APPEND_NUMBER
711# undef APPEND_STRING
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500712 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500713
John Bowler40b26032011-12-22 08:09:15 -0600714 return 1;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500715}
John Bowler40b26032011-12-22 08:09:15 -0600716
717# if PNG_LIBPNG_VER < 10700
Glenn Randers-Pehrson0546e4e2012-06-12 13:06:52 -0500718/* To do: remove the following from libpng-1.7 */
John Bowler40b26032011-12-22 08:09:15 -0600719/* Original API that uses a private buffer in png_struct.
Glenn Randers-Pehrson0546e4e2012-06-12 13:06:52 -0500720 * Deprecated because it causes png_struct to carry a spurious temporary
John Bowler40b26032011-12-22 08:09:15 -0600721 * buffer (png_struct::time_buffer), better to have the caller pass this in.
722 */
723png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600724png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
John Bowler40b26032011-12-22 08:09:15 -0600725{
726 if (png_ptr != NULL)
727 {
728 /* The only failure above if png_ptr != NULL is from an invalid ptime */
729 if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime))
730 png_warning(png_ptr, "Ignoring invalid time value");
731
732 else
733 return png_ptr->time_buffer;
734 }
735
736 return NULL;
737}
738# endif
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600739# endif /* PNG_TIME_RFC1123_SUPPORTED */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600740
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600741#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600742
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500743png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600744png_get_copyright(png_const_structrp png_ptr)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600745{
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600746 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500747#ifdef PNG_STRING_COPYRIGHT
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600748 return PNG_STRING_COPYRIGHT
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500749#else
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600750# ifdef __STDC__
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500751 return PNG_STRING_NEWLINE \
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -0500752 "libpng version 1.6.0beta28 - August 18, 2012" PNG_STRING_NEWLINE \
Glenn Randers-Pehrson1531bd62012-01-01 14:45:04 -0600753 "Copyright (c) 1998-2012 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
Glenn Randers-Pehrson43aaf6e2008-08-05 22:17:03 -0500754 "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
755 "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500756 PNG_STRING_NEWLINE;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600757# else
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -0500758 return "libpng version 1.6.0beta28 - August 18, 2012\
Glenn Randers-Pehrson1531bd62012-01-01 14:45:04 -0600759 Copyright (c) 1998-2012 Glenn Randers-Pehrson\
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500760 Copyright (c) 1996-1997 Andreas Dilger\
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500761 Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600762# endif
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500763#endif
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600764}
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -0500765
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600766/* The following return the library version as a short string in the
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500767 * format 1.0.0 through 99.99.99zz. To get the version of *.h files
768 * used with your application, print out PNG_LIBPNG_VER_STRING, which
769 * is defined in png.h.
770 * Note: now there is no difference between png_get_libpng_ver() and
771 * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
772 * it is guaranteed that png.c uses the correct version of png.h.
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600773 */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500774png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600775png_get_libpng_ver(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600776{
777 /* Version of *.c files used when building libpng */
Glenn Randers-Pehrson4c8f7262010-03-16 19:30:01 -0500778 return png_get_header_ver(png_ptr);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600779}
780
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500781png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600782png_get_header_ver(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600783{
784 /* Version of *.h files used when building libpng */
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600785 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500786 return PNG_LIBPNG_VER_STRING;
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600787}
788
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500789png_const_charp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600790png_get_header_version(png_const_structrp png_ptr)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600791{
792 /* Returns longer string containing both version and date */
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -0600793 PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500794#ifdef __STDC__
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500795 return PNG_HEADER_VERSION_STRING
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600796# ifndef PNG_READ_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500797 " (NO READ SUPPORT)"
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600798# endif
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500799 PNG_STRING_NEWLINE;
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500800#else
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500801 return PNG_HEADER_VERSION_STRING;
Glenn Randers-Pehrsone0784c72008-08-09 07:11:44 -0500802#endif
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600803}
804
John Bowlere9567512012-08-15 22:53:00 -0500805#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrsonc1bfe682002-03-06 22:08:00 -0600806int PNGAPI
John Bowlere9567512012-08-15 22:53:00 -0500807png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600808{
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500809 /* Check chunk_name and return "keep" value if it's on the list, else 0 */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500810 png_const_bytep p, p_end;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500811
John Bowlerfcd301d2011-12-28 21:34:27 -0600812 if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500813 return PNG_HANDLE_CHUNK_AS_DEFAULT;
814
815 p_end = png_ptr->chunk_list;
816 p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
817
818 /* The code is the fifth byte after each four byte string. Historically this
John Bowlere9567512012-08-15 22:53:00 -0500819 * code was always searched from the end of the list, this is no longer
820 * necessary because the 'set' routine handles duplicate entries correcty.
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500821 */
822 do /* num_chunk_list > 0, so at least one */
823 {
824 p -= 5;
John Bowlere9567512012-08-15 22:53:00 -0500825
Glenn Randers-Pehrsondbb7e192012-08-10 17:27:42 -0500826 if (!memcmp(chunk_name, p, 4))
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500827 return p[4];
828 }
829 while (p > p_end);
830
John Bowlere9567512012-08-15 22:53:00 -0500831 /* This means that known chunks should be processed and unknown chunks should
832 * be handled according to the value of png_ptr->unknown_default; this can be
833 * confusing because, as a result, there are two levels of defaulting for
834 * unknown chunks.
835 */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500836 return PNG_HANDLE_CHUNK_AS_DEFAULT;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600837}
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500838
John Bowlere9567512012-08-15 22:53:00 -0500839#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500840int /* PRIVATE */
John Bowlere9567512012-08-15 22:53:00 -0500841png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500842{
843 png_byte chunk_string[5];
844
845 PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
846 return png_handle_as_unknown(png_ptr, chunk_string);
847}
John Bowlere9567512012-08-15 22:53:00 -0500848#endif /* READ_UNKNOWN_CHUNKS */
849#endif /* SET_UNKNOWN_CHUNKS */
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500850
Glenn Randers-Pehrsonf10fa3c2010-04-29 08:25:29 -0500851#ifdef PNG_READ_SUPPORTED
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500852/* This function, added to libpng-1.0.6g, is untested. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500853int PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600854png_reset_zstream(png_structrp png_ptr)
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500855{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500856 if (png_ptr == NULL)
857 return Z_STREAM_ERROR;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500858
John Bowlerb5d00512012-03-09 09:15:18 -0600859 /* WARNING: this resets the window bits to the maximum! */
Glenn Randers-Pehrson228bd392000-04-23 23:14:02 -0500860 return (inflateReset(&png_ptr->zstream));
861}
Glenn Randers-Pehrson2b8bef12010-04-29 11:50:24 -0500862#endif /* PNG_READ_SUPPORTED */
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500863
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -0600864/* This function was added to libpng-1.0.7 */
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500865png_uint_32 PNGAPI
866png_access_version_number(void)
867{
868 /* Version of *.c files used when building libpng */
Glenn Randers-Pehrsond2332872010-10-12 19:19:28 -0500869 return((png_uint_32)PNG_LIBPNG_VER);
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -0500870}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600871
Glenn Randers-Pehrson1fd5fb32001-05-06 05:34:26 -0500872
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500873
874#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
John Bowlerb5d00512012-03-09 09:15:18 -0600875/* Ensure that png_ptr->zstream.msg holds some appropriate error message string.
876 * If it doesn't 'ret' is used to set it to something appropriate, even in cases
877 * like Z_OK or Z_STREAM_END where the error code is apparently a success code.
878 */
879void /* PRIVATE */
880png_zstream_error(png_structrp png_ptr, int ret)
881{
882 /* Translate 'ret' into an appropriate error string, priority is given to the
883 * one in zstream if set. This always returns a string, even in cases like
884 * Z_OK or Z_STREAM_END where the error code is a success code.
885 */
886 if (png_ptr->zstream.msg == NULL) switch (ret)
887 {
888 default:
889 case Z_OK:
890 png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");
891 break;
892
893 case Z_STREAM_END:
894 /* Normal exit */
895 png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");
896 break;
897
898 case Z_NEED_DICT:
899 /* This means the deflate stream did not have a dictionary; this
900 * indicates a bogus PNG.
901 */
902 png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");
903 break;
904
905 case Z_ERRNO:
906 /* gz APIs only: should not happen */
907 png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");
908 break;
909
910 case Z_STREAM_ERROR:
911 /* internal libpng error */
912 png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");
913 break;
914
915 case Z_DATA_ERROR:
916 png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");
917 break;
918
919 case Z_MEM_ERROR:
920 png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");
921 break;
922
923 case Z_BUF_ERROR:
924 /* End of input or output; not a problem if the caller is doing
925 * incremental read or write.
926 */
927 png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");
928 break;
929
930 case Z_VERSION_ERROR:
931 png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");
932 break;
933
934 case PNG_UNEXPECTED_ZLIB_RETURN:
935 /* Compile errors here mean that zlib now uses the value co-opted in
936 * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
937 * and change pngpriv.h. Note that this message is "... return",
938 * whereas the default/Z_OK one is "... return code".
939 */
940 png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");
941 break;
942 }
943}
944
John Bowler736f40f2011-08-25 16:19:44 -0500945/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
946 * at libpng 1.5.5!
947 */
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -0600948
Glenn Randers-Pehrson02a5e332008-11-24 22:10:23 -0600949/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
John Bowlerb11b31a2012-03-21 07:55:46 -0500950#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
951static int
952png_colorspace_check_gamma(png_const_structrp png_ptr,
953 png_colorspacerp colorspace, png_fixed_point gAMA, int preferred)
954{
955 /* The 'invalid' flag needs to be sticky, doing things this way avoids having
956 * many messages caused by just one invalid colorspace chunk.
957 */
958 if (colorspace->flags & PNG_COLORSPACE_INVALID)
959 return 0;
960
961 if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA))
962 {
963 png_fixed_point gtest;
964
965 if (!png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) ||
966 png_gamma_significant(gtest))
967 {
968 colorspace->flags |= PNG_COLORSPACE_INVALID;
969 png_benign_error(png_ptr, "inconsistent gamma values");
970 return 0; /* failed */
971 }
972
973 else if (!preferred)
974 return 1; /* ok, use existing gamma */
975 }
976
977 return 2; /* ok, write gamma */
978}
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500979
Glenn Randers-Pehrson3f705ba2009-07-23 12:53:06 -0500980int /* PRIVATE */
John Bowlerb11b31a2012-03-21 07:55:46 -0500981png_colorspace_set_gamma(png_const_structrp png_ptr,
982 png_colorspacerp colorspace, png_fixed_point gAMA, int preferred)
983{
984 int result = png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
985 preferred);
986
987 if (result == 2)
988 {
989 colorspace->gamma = gAMA;
990 colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
991 }
992
993 return result;
994}
995
996void /* PRIVATE */
997png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
998{
999 if (info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID)
1000 {
1001 /* Everything is invalid */
1002 info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
1003 PNG_INFO_iCCP);
1004
1005# ifdef PNG_COLORSPACE_SUPPORTED
1006 /* Clean up the iCCP profile now if it won't be used. */
1007 png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
1008# else
1009 PNG_UNUSED(png_ptr)
1010# endif
1011 }
1012
1013 else
1014 {
1015# ifdef PNG_COLORSPACE_SUPPORTED
1016 /* Leave the INFO_iCCP flag set if the pngset.c code has already set
1017 * it; this allows a PNG to contain a profile which matches sRGB and
1018 * yet still have that profile retrievable by the application.
1019 */
1020 if (info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB)
1021 info_ptr->valid |= PNG_INFO_sRGB;
1022
1023 else
1024 info_ptr->valid &= ~PNG_INFO_sRGB;
1025
1026 if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)
1027 info_ptr->valid |= PNG_INFO_cHRM;
1028
1029 else
1030 info_ptr->valid &= ~PNG_INFO_cHRM;
1031
1032 /* TODO: at present it is possible to png_set a detectably inconsistent
1033 * ICC profile, this should be handled, somehow.
1034 */
1035# endif
1036
1037 if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA)
1038 info_ptr->valid |= PNG_INFO_gAMA;
1039
1040 else
1041 info_ptr->valid &= ~PNG_INFO_gAMA;
1042 }
1043}
1044
1045#ifdef PNG_READ_SUPPORTED
1046void /* PRIVATE */
1047png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
1048{
1049 if (info_ptr == NULL) /* reduce code size; check here not in the caller */
1050 return;
1051
1052 info_ptr->colorspace = png_ptr->colorspace;
1053 png_colorspace_sync_info(png_ptr, info_ptr);
1054}
1055#endif
1056#endif
1057
1058#ifdef PNG_COLORSPACE_SUPPORTED
1059#if 0
1060/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
1061 * 2010: moved from pngset.c) */
1062/*
1063 * Multiply two 32-bit numbers, V1 and V2, using 32-bit
1064 * arithmetic, to produce a 64-bit result in the HI/LO words.
1065 *
1066 * A B
1067 * x C D
1068 * ------
1069 * AD || BD
1070 * AC || CB || 0
1071 *
1072 * where A and B are the high and low 16-bit words of V1,
1073 * C and D are the 16-bit words of V2, AD is the product of
1074 * A and D, and X || Y is (X << 16) + Y.
1075*/
Glenn Randers-Pehrson3744f942012-08-10 19:22:53 -05001076static void
John Bowlerb11b31a2012-03-21 07:55:46 -05001077png_64bit_product (long v1, long v2, unsigned long *hi_product,
1078 unsigned long *lo_product)
1079{
1080 int a, b, c, d;
1081 long lo, hi, x, y;
1082
1083 a = (v1 >> 16) & 0xffff;
1084 b = v1 & 0xffff;
1085 c = (v2 >> 16) & 0xffff;
1086 d = v2 & 0xffff;
1087
1088 lo = b * d; /* BD */
1089 x = a * d + c * b; /* AD + CB */
1090 y = ((lo >> 16) & 0xffff) + x;
1091
1092 lo = (lo & 0xffff) | ((y & 0xffff) << 16);
1093 hi = (y >> 16) & 0xffff;
1094
1095 hi += a * c; /* AC */
1096
1097 *hi_product = (unsigned long)hi;
1098 *lo_product = (unsigned long)lo;
1099}
1100
1101static int
John Bowler4f67e402011-12-28 08:43:37 -06001102png_check_cHRM_fixed(png_const_structrp png_ptr,
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001103 png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
1104 png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
1105 png_fixed_point blue_x, png_fixed_point blue_y)
1106{
1107 int ret = 1;
Glenn Randers-Pehrsond0c40592008-11-22 07:09:51 -06001108 unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001109
1110 png_debug(1, "in function png_check_cHRM_fixed");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -05001111
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001112 if (png_ptr == NULL)
1113 return 0;
1114
John Bowlerd2f0bc22011-06-11 06:42:06 -05001115 /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white
1116 * y must also be greater than 0. To test for the upper limit calculate
1117 * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression
1118 * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is
1119 * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it
1120 * pointless (and it produces compiler warnings!)
1121 */
Glenn Randers-Pehrson02a5e332008-11-24 22:10:23 -06001122 if (white_x < 0 || white_y <= 0 ||
1123 red_x < 0 || red_y < 0 ||
1124 green_x < 0 || green_y < 0 ||
1125 blue_x < 0 || blue_y < 0)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001126 {
1127 png_warning(png_ptr,
1128 "Ignoring attempt to set negative chromaticity value");
1129 ret = 0;
1130 }
John Bowlerd2f0bc22011-06-11 06:42:06 -05001131 /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */
1132 if (white_x > PNG_FP_1 - white_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001133 {
1134 png_warning(png_ptr, "Invalid cHRM white point");
1135 ret = 0;
1136 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001137
John Bowlerd2f0bc22011-06-11 06:42:06 -05001138 if (red_x > PNG_FP_1 - red_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001139 {
1140 png_warning(png_ptr, "Invalid cHRM red point");
1141 ret = 0;
1142 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001143
John Bowlerd2f0bc22011-06-11 06:42:06 -05001144 if (green_x > PNG_FP_1 - green_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001145 {
1146 png_warning(png_ptr, "Invalid cHRM green point");
1147 ret = 0;
1148 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001149
John Bowlerd2f0bc22011-06-11 06:42:06 -05001150 if (blue_x > PNG_FP_1 - blue_y)
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001151 {
1152 png_warning(png_ptr, "Invalid cHRM blue point");
1153 ret = 0;
1154 }
Glenn Randers-Pehrsond0c40592008-11-22 07:09:51 -06001155
1156 png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
1157 png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
1158
1159 if (xy_hi == yx_hi && xy_lo == yx_lo)
1160 {
1161 png_warning(png_ptr,
1162 "Ignoring attempt to set cHRM RGB triangle with zero area");
1163 ret = 0;
1164 }
1165
Glenn Randers-Pehrsonf7831012008-11-13 06:05:13 -06001166 return ret;
1167}
John Bowlerb11b31a2012-03-21 07:55:46 -05001168#endif /*0*/
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05001169
John Bowler736f40f2011-08-25 16:19:44 -05001170/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
1171 * cHRM, as opposed to using chromaticities. These internal APIs return
1172 * non-zero on a parameter error. The X, Y and Z values are required to be
1173 * positive and less than 1.0.
1174 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001175static int
1176png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
John Bowler736f40f2011-08-25 16:19:44 -05001177{
1178 png_int_32 d, dwhite, whiteX, whiteY;
1179
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001180 d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
1181 if (!png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d)) return 1;
1182 if (!png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d)) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001183 dwhite = d;
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001184 whiteX = XYZ->red_X;
1185 whiteY = XYZ->red_Y;
John Bowler736f40f2011-08-25 16:19:44 -05001186
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001187 d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
1188 if (!png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d)) return 1;
1189 if (!png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d)) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001190 dwhite += d;
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001191 whiteX += XYZ->green_X;
1192 whiteY += XYZ->green_Y;
John Bowler736f40f2011-08-25 16:19:44 -05001193
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001194 d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
1195 if (!png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d)) return 1;
1196 if (!png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d)) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001197 dwhite += d;
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001198 whiteX += XYZ->blue_X;
1199 whiteY += XYZ->blue_Y;
John Bowler736f40f2011-08-25 16:19:44 -05001200
John Bowlerb11b31a2012-03-21 07:55:46 -05001201 /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
John Bowler736f40f2011-08-25 16:19:44 -05001202 * thus:
1203 */
1204 if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;
1205 if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;
1206
1207 return 0;
1208}
1209
John Bowlerb11b31a2012-03-21 07:55:46 -05001210static int
1211png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
John Bowler736f40f2011-08-25 16:19:44 -05001212{
1213 png_fixed_point red_inverse, green_inverse, blue_scale;
1214 png_fixed_point left, right, denominator;
1215
1216 /* Check xy and, implicitly, z. Note that wide gamut color spaces typically
1217 * have end points with 0 tristimulus values (these are impossible end
1218 * points, but they are used to cover the possible colors.)
1219 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001220 if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
1221 if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
1222 if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
1223 if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
1224 if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
1225 if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
1226 if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
1227 if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
John Bowler736f40f2011-08-25 16:19:44 -05001228
1229 /* The reverse calculation is more difficult because the original tristimulus
1230 * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
1231 * derived values were recorded in the cHRM chunk;
1232 * (red,green,blue,white)x(x,y). This loses one degree of freedom and
1233 * therefore an arbitrary ninth value has to be introduced to undo the
1234 * original transformations.
1235 *
1236 * Think of the original end-points as points in (X,Y,Z) space. The
1237 * chromaticity values (c) have the property:
1238 *
1239 * C
1240 * c = ---------
1241 * X + Y + Z
1242 *
1243 * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the
1244 * three chromaticity values (x,y,z) for each end-point obey the
1245 * relationship:
1246 *
1247 * x + y + z = 1
1248 *
1249 * This describes the plane in (X,Y,Z) space that intersects each axis at the
1250 * value 1.0; call this the chromaticity plane. Thus the chromaticity
1251 * calculation has scaled each end-point so that it is on the x+y+z=1 plane
1252 * and chromaticity is the intersection of the vector from the origin to the
1253 * (X,Y,Z) value with the chromaticity plane.
1254 *
1255 * To fully invert the chromaticity calculation we would need the three
1256 * end-point scale factors, (red-scale, green-scale, blue-scale), but these
1257 * were not recorded. Instead we calculated the reference white (X,Y,Z) and
1258 * recorded the chromaticity of this. The reference white (X,Y,Z) would have
1259 * given all three of the scale factors since:
1260 *
1261 * color-C = color-c * color-scale
1262 * white-C = red-C + green-C + blue-C
1263 * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
1264 *
1265 * But cHRM records only white-x and white-y, so we have lost the white scale
1266 * factor:
1267 *
1268 * white-C = white-c*white-scale
1269 *
1270 * To handle this the inverse transformation makes an arbitrary assumption
1271 * about white-scale:
1272 *
1273 * Assume: white-Y = 1.0
1274 * Hence: white-scale = 1/white-y
1275 * Or: red-Y + green-Y + blue-Y = 1.0
1276 *
1277 * Notice the last statement of the assumption gives an equation in three of
1278 * the nine values we want to calculate. 8 more equations come from the
1279 * above routine as summarised at the top above (the chromaticity
1280 * calculation):
1281 *
1282 * Given: color-x = color-X / (color-X + color-Y + color-Z)
1283 * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
1284 *
1285 * This is 9 simultaneous equations in the 9 variables "color-C" and can be
1286 * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix
1287 * determinants, however this is not as bad as it seems because only 28 of
1288 * the total of 90 terms in the various matrices are non-zero. Nevertheless
1289 * Cramer's rule is notoriously numerically unstable because the determinant
1290 * calculation involves the difference of large, but similar, numbers. It is
1291 * difficult to be sure that the calculation is stable for real world values
1292 * and it is certain that it becomes unstable where the end points are close
1293 * together.
1294 *
Glenn Randers-Pehrsoncc461572012-06-06 13:16:09 -05001295 * So this code uses the perhaps slightly less optimal but more
1296 * understandable and totally obvious approach of calculating color-scale.
John Bowler736f40f2011-08-25 16:19:44 -05001297 *
1298 * This algorithm depends on the precision in white-scale and that is
1299 * (1/white-y), so we can immediately see that as white-y approaches 0 the
1300 * accuracy inherent in the cHRM chunk drops off substantially.
1301 *
1302 * libpng arithmetic: a simple invertion of the above equations
1303 * ------------------------------------------------------------
1304 *
1305 * white_scale = 1/white-y
1306 * white-X = white-x * white-scale
1307 * white-Y = 1.0
1308 * white-Z = (1 - white-x - white-y) * white_scale
1309 *
1310 * white-C = red-C + green-C + blue-C
1311 * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
1312 *
1313 * This gives us three equations in (red-scale,green-scale,blue-scale) where
1314 * all the coefficients are now known:
1315 *
1316 * red-x*red-scale + green-x*green-scale + blue-x*blue-scale
1317 * = white-x/white-y
1318 * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
1319 * red-z*red-scale + green-z*green-scale + blue-z*blue-scale
1320 * = (1 - white-x - white-y)/white-y
1321 *
1322 * In the last equation color-z is (1 - color-x - color-y) so we can add all
1323 * three equations together to get an alternative third:
1324 *
1325 * red-scale + green-scale + blue-scale = 1/white-y = white-scale
1326 *
1327 * So now we have a Cramer's rule solution where the determinants are just
1328 * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve
1329 * multiplication of three coefficients so we can't guarantee to avoid
1330 * overflow in the libpng fixed point representation. Using Cramer's rule in
1331 * floating point is probably a good choice here, but it's not an option for
1332 * fixed point. Instead proceed to simplify the first two equations by
1333 * eliminating what is likely to be the largest value, blue-scale:
1334 *
1335 * blue-scale = white-scale - red-scale - green-scale
1336 *
1337 * Hence:
1338 *
1339 * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
1340 * (white-x - blue-x)*white-scale
1341 *
1342 * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
1343 * 1 - blue-y*white-scale
1344 *
1345 * And now we can trivially solve for (red-scale,green-scale):
1346 *
1347 * green-scale =
1348 * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
1349 * -----------------------------------------------------------
1350 * green-x - blue-x
1351 *
1352 * red-scale =
1353 * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale
1354 * ---------------------------------------------------------
1355 * red-y - blue-y
1356 *
1357 * Hence:
1358 *
1359 * red-scale =
1360 * ( (green-x - blue-x) * (white-y - blue-y) -
1361 * (green-y - blue-y) * (white-x - blue-x) ) / white-y
1362 * -------------------------------------------------------------------------
1363 * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
1364 *
1365 * green-scale =
1366 * ( (red-y - blue-y) * (white-x - blue-x) -
1367 * (red-x - blue-x) * (white-y - blue-y) ) / white-y
1368 * -------------------------------------------------------------------------
1369 * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
1370 *
1371 * Accuracy:
1372 * The input values have 5 decimal digits of accuracy. The values are all in
1373 * the range 0 < value < 1, so simple products are in the same range but may
1374 * need up to 10 decimal digits to preserve the original precision and avoid
1375 * underflow. Because we are using a 32-bit signed representation we cannot
1376 * match this; the best is a little over 9 decimal digits, less than 10.
1377 *
1378 * The approach used here is to preserve the maximum precision within the
1379 * signed representation. Because the red-scale calculation above uses the
1380 * difference between two products of values that must be in the range -1..+1
1381 * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The
1382 * factor is irrelevant in the calculation because it is applied to both
1383 * numerator and denominator.
1384 *
1385 * Note that the values of the differences of the products of the
1386 * chromaticities in the above equations tend to be small, for example for
1387 * the sRGB chromaticities they are:
1388 *
1389 * red numerator: -0.04751
1390 * green numerator: -0.08788
1391 * denominator: -0.2241 (without white-y multiplication)
1392 *
1393 * The resultant Y coefficients from the chromaticities of some widely used
1394 * color space definitions are (to 15 decimal places):
1395 *
1396 * sRGB
1397 * 0.212639005871510 0.715168678767756 0.072192315360734
1398 * Kodak ProPhoto
1399 * 0.288071128229293 0.711843217810102 0.000085653960605
1400 * Adobe RGB
1401 * 0.297344975250536 0.627363566255466 0.075291458493998
1402 * Adobe Wide Gamut RGB
1403 * 0.258728243040113 0.724682314948566 0.016589442011321
1404 */
1405 /* By the argument, above overflow should be impossible here. The return
1406 * value of 2 indicates an internal error to the caller.
1407 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001408 if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7))
1409 return 2;
1410 if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7))
1411 return 2;
John Bowler736f40f2011-08-25 16:19:44 -05001412 denominator = left - right;
1413
1414 /* Now find the red numerator. */
John Bowlerb11b31a2012-03-21 07:55:46 -05001415 if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7))
1416 return 2;
1417 if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7))
1418 return 2;
John Bowler736f40f2011-08-25 16:19:44 -05001419
1420 /* Overflow is possible here and it indicates an extreme set of PNG cHRM
1421 * chunk values. This calculation actually returns the reciprocal of the
1422 * scale value because this allows us to delay the multiplication of white-y
1423 * into the denominator, which tends to produce a small number.
1424 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001425 if (!png_muldiv(&red_inverse, xy->whitey, denominator, left-right) ||
1426 red_inverse <= xy->whitey /* r+g+b scales = white scale */)
John Bowler736f40f2011-08-25 16:19:44 -05001427 return 1;
1428
1429 /* Similarly for green_inverse: */
John Bowlerb11b31a2012-03-21 07:55:46 -05001430 if (!png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7))
1431 return 2;
1432 if (!png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7))
1433 return 2;
1434 if (!png_muldiv(&green_inverse, xy->whitey, denominator, left-right) ||
1435 green_inverse <= xy->whitey)
John Bowler736f40f2011-08-25 16:19:44 -05001436 return 1;
1437
1438 /* And the blue scale, the checks above guarantee this can't overflow but it
1439 * can still produce 0 for extreme cHRM values.
1440 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001441 blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
John Bowler736f40f2011-08-25 16:19:44 -05001442 png_reciprocal(green_inverse);
1443 if (blue_scale <= 0) return 1;
1444
1445
1446 /* And fill in the png_XYZ: */
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001447 if (!png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse)) return 1;
1448 if (!png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse)) return 1;
1449 if (!png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
John Bowler736f40f2011-08-25 16:19:44 -05001450 red_inverse))
1451 return 1;
1452
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001453 if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse)) return 1;
1454 if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse)) return 1;
1455 if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
John Bowler736f40f2011-08-25 16:19:44 -05001456 green_inverse))
1457 return 1;
1458
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001459 if (!png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1)) return 1;
1460 if (!png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1)) return 1;
1461 if (!png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
John Bowler736f40f2011-08-25 16:19:44 -05001462 PNG_FP_1))
1463 return 1;
1464
1465 return 0; /*success*/
1466}
1467
John Bowlerb11b31a2012-03-21 07:55:46 -05001468static int
1469png_XYZ_normalize(png_XYZ *XYZ)
John Bowler736f40f2011-08-25 16:19:44 -05001470{
John Bowlerb11b31a2012-03-21 07:55:46 -05001471 png_int_32 Y;
1472
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001473 if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
1474 XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
1475 XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
John Bowlerb11b31a2012-03-21 07:55:46 -05001476 return 1;
1477
1478 /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
1479 * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
Glenn Randers-Pehrson025d4152012-08-16 00:51:44 -05001480 * relying on addition of two positive values producing a negative one is not
1481 * safe.
John Bowlerb11b31a2012-03-21 07:55:46 -05001482 */
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001483 Y = XYZ->red_Y;
1484 if (0x7fffffff - Y < XYZ->green_X) return 1;
1485 Y += XYZ->green_Y;
1486 if (0x7fffffff - Y < XYZ->blue_X) return 1;
1487 Y += XYZ->blue_Y;
John Bowlerb11b31a2012-03-21 07:55:46 -05001488
1489 if (Y != PNG_FP_1)
1490 {
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001491 if (!png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y)) return 1;
1492 if (!png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y)) return 1;
1493 if (!png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y)) return 1;
John Bowlerb11b31a2012-03-21 07:55:46 -05001494
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001495 if (!png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y)) return 1;
1496 if (!png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y)) return 1;
1497 if (!png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y)) return 1;
John Bowlerb11b31a2012-03-21 07:55:46 -05001498
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001499 if (!png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y)) return 1;
1500 if (!png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y)) return 1;
1501 if (!png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y)) return 1;
John Bowlerb11b31a2012-03-21 07:55:46 -05001502 }
1503
1504 return 0;
1505}
1506
1507static int
1508png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
1509{
1510 /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
1511 return !(PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
1512 PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
1513 PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) ||
1514 PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) ||
1515 PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
1516 PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
1517 PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) ||
1518 PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta));
1519}
1520
1521/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
1522 * chunk chromaticities. Earlier checks used to simply look for the overflow
1523 * condition (where the determinant of the matrix to solve for XYZ ends up zero
1524 * because the chromaticity values are not all distinct.) Despite this it is
1525 * theoretically possible to produce chromaticities that are apparently valid
1526 * but that rapidly degrade to invalid, potentially crashing, sets because of
1527 * arithmetic inaccuracies when calculations are performed on them. The new
1528 * check is to round-trip xy -> XYZ -> xy and then check that the result is
1529 * within a small percentage of the original.
1530 */
1531static int
1532png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
1533{
1534 int result;
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001535 png_xy xy_test;
John Bowlerb11b31a2012-03-21 07:55:46 -05001536
1537 /* As a side-effect this routine also returns the XYZ endpoints. */
1538 result = png_XYZ_from_xy(XYZ, xy);
1539 if (result) return result;
1540
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001541 result = png_xy_from_XYZ(&xy_test, XYZ);
John Bowlerb11b31a2012-03-21 07:55:46 -05001542 if (result) return result;
1543
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001544 if (png_colorspace_endpoints_match(xy, &xy_test,
John Bowlerb11b31a2012-03-21 07:55:46 -05001545 5/*actually, the math is pretty accurate*/))
1546 return 0;
1547
1548 /* Too much slip */
1549 return 1;
1550}
1551
1552/* This is the check going the other way. The XYZ is modified to normalize it
1553 * (another side-effect) and the xy chromaticities are returned.
1554 */
1555static int
1556png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
1557{
1558 int result;
1559 png_XYZ XYZtemp;
1560
1561 result = png_XYZ_normalize(XYZ);
1562 if (result) return result;
1563
1564 result = png_xy_from_XYZ(xy, XYZ);
1565 if (result) return result;
1566
1567 XYZtemp = *XYZ;
1568 return png_colorspace_check_xy(&XYZtemp, xy);
1569}
1570
1571/* Used to check for an endpoint match against sRGB */
1572static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
1573{
1574 /* color x y */
1575 /* red */ 64000, 33000,
1576 /* green */ 30000, 60000,
1577 /* blue */ 15000, 6000,
1578 /* white */ 31270, 32900
1579};
1580
1581static int
1582png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
1583 png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
1584 int preferred)
1585{
1586 if (colorspace->flags & PNG_COLORSPACE_INVALID)
1587 return 0;
1588
1589 /* The consistency check is performed on the chromaticities; this factors out
1590 * variations because of the normalization (or not) of the end point Y
1591 * values.
1592 */
1593 if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS))
1594 {
1595 /* The end points must be reasonably close to any we already have. The
1596 * following allows an error of up to +/-1%
1597 */
1598 if (!png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 1000))
1599 {
1600 colorspace->flags |= PNG_COLORSPACE_INVALID;
1601 png_benign_error(png_ptr, "inconsistent chromaticities");
1602 return 0; /* failed */
1603 }
1604
1605 /* Only overwrite with preferred values */
1606 if (!preferred)
1607 return 1; /* ok, but no change */
1608 }
1609
1610 colorspace->end_points_xy = *xy;
1611 colorspace->end_points_XYZ = *XYZ;
1612 colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
1613
1614 /* TODO: 4000 is 0.04, and this is sufficient to accomodate the difference
1615 * between the adapted D50 white point and the original D65 one. Is this
1616 * necessary?
1617 */
1618 if (png_colorspace_endpoints_match(xy, &sRGB_xy, 4000))
1619 colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
1620
1621 else
1622 colorspace->flags &= 0xff ^ PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
1623
1624 return 2; /* ok and changed */
1625}
1626
1627int /* PRIVATE */
1628png_colorspace_set_chromaticities(png_const_structrp png_ptr,
1629 png_colorspacerp colorspace, const png_xy *xy, int preferred)
1630{
1631 /* We must check the end points to ensure they are reasonable - in the past
1632 * color management systems have crashed as a result of getting bogus
1633 * colorant values, while this isn't the fault of libpng it is the
1634 * responsibility of libpng because PNG carries the bomb and libpng is in a
1635 * position to protect against it.
1636 */
1637 png_XYZ XYZ;
1638
1639 switch (png_colorspace_check_xy(&XYZ, xy))
John Bowler736f40f2011-08-25 16:19:44 -05001640 {
1641 case 0: /* success */
John Bowlerb11b31a2012-03-21 07:55:46 -05001642 return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
1643 preferred);
John Bowler736f40f2011-08-25 16:19:44 -05001644
1645 case 1:
John Bowlerb11b31a2012-03-21 07:55:46 -05001646 /* We can't invert the chromaticities so we can't produce value XYZ
1647 * values. Likely as not a color management system will fail too.
John Bowler736f40f2011-08-25 16:19:44 -05001648 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001649 colorspace->flags |= PNG_COLORSPACE_INVALID;
1650 png_benign_error(png_ptr, "invalid chromaticities");
John Bowler736f40f2011-08-25 16:19:44 -05001651 break;
1652
1653 default:
1654 /* libpng is broken; this should be a warning but if it happens we
1655 * want error reports so for the moment it is an error.
1656 */
John Bowlerb11b31a2012-03-21 07:55:46 -05001657 colorspace->flags |= PNG_COLORSPACE_INVALID;
1658 png_error(png_ptr, "internal error checking chromaticities");
John Bowler736f40f2011-08-25 16:19:44 -05001659 break;
1660 }
1661
John Bowlerb11b31a2012-03-21 07:55:46 -05001662 return 0; /* failed */
1663}
1664
1665int /* PRIVATE */
1666png_colorspace_set_endpoints(png_const_structrp png_ptr,
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001667 png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
John Bowlerb11b31a2012-03-21 07:55:46 -05001668{
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05001669 png_XYZ XYZ = *XYZ_in;
John Bowlerb11b31a2012-03-21 07:55:46 -05001670 png_xy xy;
1671
1672 switch (png_colorspace_check_XYZ(&xy, &XYZ))
1673 {
1674 case 0:
1675 return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
1676 preferred);
1677
1678 case 1:
1679 /* End points are invalid. */
1680 colorspace->flags |= PNG_COLORSPACE_INVALID;
1681 png_benign_error(png_ptr, "invalid end points");
1682 break;
1683
1684 default:
1685 colorspace->flags |= PNG_COLORSPACE_INVALID;
1686 png_error(png_ptr, "internal error checking chromaticities");
1687 break;
1688 }
1689
1690 return 0; /* failed */
1691}
1692
1693#if defined PNG_sRGB_SUPPORTED || defined PNG_iCCP_SUPPORTED
1694static int
1695profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
1696 png_const_charp name, png_alloc_size_t value, png_const_charp reason)
1697{
1698 size_t pos;
1699 char message[256];
1700
1701 if (colorspace != NULL)
1702 colorspace->flags |= PNG_COLORSPACE_INVALID;
1703
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05001704 pos = png_safecat(message, (sizeof message), 0, "profile '");
John Bowlerb11b31a2012-03-21 07:55:46 -05001705 pos = png_safecat(message, pos+79, pos, name);
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05001706 pos = png_safecat(message, (sizeof message), pos, "': ");
John Bowlerb11b31a2012-03-21 07:55:46 -05001707# ifdef PNG_WARNINGS_SUPPORTED
1708 {
1709 char number[PNG_NUMBER_BUFFER_SIZE];
1710
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05001711 pos = png_safecat(message, (sizeof message), pos,
John Bowlerb11b31a2012-03-21 07:55:46 -05001712 png_format_number(number, number+(sizeof number),
1713 PNG_NUMBER_FORMAT_x, value));
1714 }
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05001715 pos = png_safecat(message, (sizeof message), pos, ": ");
John Bowlerb11b31a2012-03-21 07:55:46 -05001716# endif
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05001717 pos = png_safecat(message, (sizeof message), pos, reason);
John Bowlerb11b31a2012-03-21 07:55:46 -05001718
1719 if (colorspace != NULL)
1720 {
John Bowlerba2dd332012-08-10 10:58:01 -05001721# ifdef PNG_READ_SUPPORTED
1722 if (png_ptr->mode & PNG_IS_READ_STRUCT)
1723 png_chunk_benign_error(png_ptr, message);
John Bowlerb11b31a2012-03-21 07:55:46 -05001724
John Bowlerba2dd332012-08-10 10:58:01 -05001725 else
1726# endif
John Bowlerb11b31a2012-03-21 07:55:46 -05001727 png_app_error(png_ptr, message);
1728 }
1729
1730# ifdef PNG_WARNINGS_SUPPORTED
1731 else
1732 {
1733 if (png_ptr->mode & PNG_IS_READ_STRUCT)
1734 png_chunk_warning(png_ptr, message);
1735
1736 else
1737 png_warning(png_ptr, message);
1738 }
1739# endif
1740
John Bowler736f40f2011-08-25 16:19:44 -05001741 return 0;
1742}
John Bowlerb11b31a2012-03-21 07:55:46 -05001743
1744static int /* PRIVATE */
1745png_colorspace_set_profile(png_const_structrp png_ptr, png_const_charp name,
1746 png_colorspacerp colorspace, png_fixed_point gAMA, const png_xy *xy,
1747 const png_XYZ *XYZ, int intent, int preferred)
1748{
1749 int write_intent, write_gamma, result;
1750
1751 if (colorspace->flags & PNG_COLORSPACE_INVALID)
1752 return 0;
1753
1754 /* Similar to the above routines, but ensure that both the gamma and the
1755 * end-points are checked before doing any assignment.
1756 */
1757 if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_INTENT))
1758 {
1759 if (colorspace->rendering_intent != intent)
1760 return profile_error(png_ptr, colorspace, name, (unsigned)intent,
1761 "inconsistent rendering intents");
1762
1763 write_intent = 0; /* Ok, don't change */
1764 }
1765
1766 else
1767 write_intent = 1; /* Needs to be written */
1768
1769 switch (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, preferred))
1770 {
1771 case 2:
1772 write_gamma = 1;
1773 break;
1774
1775 case 1:
1776 write_gamma = 0; /* current value ok and preferred */
1777 break;
1778
1779 default: /* error */
1780 return 0;
1781 }
1782
1783 /* Everything seems ok up to this point, update the endpoints and, if this
1784 * works, do the gamma and intent too.
1785 */
1786 result = png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, XYZ,
1787 preferred);
1788
1789 switch (result)
1790 {
1791 case 2: /* ok, changed */
1792 case 1: /* ok, no end-point change */
1793 if (write_intent)
1794 {
1795 /* The value of intent must be checked in the caller; bugs in GCC
1796 * force 'int' to be used as the parameter type.
1797 */
1798 colorspace->rendering_intent = (png_uint_16)intent;
1799 colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
1800 result = 2;
1801 }
1802
1803 if (write_gamma)
1804 {
1805 colorspace->gamma = gAMA;
1806 colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
1807 result = 2;
1808 }
1809
1810 return result;
1811
1812 default: /* failure */
1813 return 0;
1814 }
1815}
1816#endif /* sRGB || iCCP */
1817
1818#ifdef PNG_sRGB_SUPPORTED
1819int /* PRIVATE */
1820png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
1821 int intent, int preferred)
1822{
1823 /* sRGB sets known gamma, end points and (from the chunk) intent. */
1824 /* IMPORTANT: these are not necessarily the values found in an ICC profile
1825 * because ICC profiles assume a D50 environment and therefore use XYZ values
1826 * appropriate to a D50 environment. Perhaps we should too; it's just
1827 * slightly weird because the chromaticities of the adapted colorants don't
1828 * match the above values.
1829 */
1830 static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
1831 {
1832 /* color X Y Z */
1833 /* red */ 41239, 21264, 1933,
1834 /* green */ 35758, 71517, 11919,
1835 /* blue */ 18048, 7219, 95053
1836 };
1837
1838 int result;
1839
1840 /* The above XYZ values, which are accurate to 5dp, produce rgb to gray
1841 * coefficients of (6968,23435,2366), which are reduced (because they add up
1842 * to 32769 not 32768) to (6968,23434,2366). These are the values that
1843 * libpng has traditionally used (and are the best values given the 15bit
1844 * algorithm used by the rgb to gray code.)
1845 */
1846 if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
1847 return profile_error(png_ptr, colorspace, "sRGB", (unsigned)intent,
1848 "invalid sRGB rendering intent");
1849
1850 result = png_colorspace_set_profile(png_ptr, "sRGB", colorspace,
1851 PNG_GAMMA_sRGB_INVERSE, &sRGB_xy, &sRGB_XYZ, intent, preferred);
1852
1853 /* The implicit profile is the sRGB one, so: */
1854 if (result)
1855 colorspace->flags |= PNG_COLORSPACE_MATCHES_sRGB;
1856
1857 return result;
1858}
1859#endif /* sRGB */
1860
1861#ifdef PNG_iCCP_SUPPORTED
1862int /* PRIVATE */
1863png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
1864 png_const_charp name, png_uint_32 profile_length)
1865{
1866 if (profile_length < 132)
1867 return profile_error(png_ptr, colorspace, name, profile_length,
1868 "too short");
1869
1870 if (profile_length & 3)
1871 return profile_error(png_ptr, colorspace, name, profile_length,
1872 "invalid length");
1873
1874 return 1;
1875}
1876
1877int /* PRIVATE */
1878png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
1879 png_const_charp name, png_uint_32 profile_length,
1880 png_const_bytep profile/* first 132 bytes only */)
1881{
1882 png_uint_32 temp;
1883
1884 /* Length checks (can't be ignored) */
1885 temp = png_get_uint_32(profile);
1886 if (temp != profile_length)
1887 return profile_error(png_ptr, colorspace, name, temp,
1888 "length does not match profile");
1889
1890 temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
1891 if (temp > 357913930 || /* (2^32-4-132)/12: maxium possible tag count */
1892 profile_length < 132+12*temp) /* truncated tag table */
1893 return profile_error(png_ptr, colorspace, name, temp,
1894 "tag count too large");
1895
1896 /* The 'intent' must be valid or we can't store it, ICC limits the intent to
1897 * 16 bits.
1898 */
1899 temp = png_get_uint_32(profile+64);
1900 if (temp >= 0xffff) /* The ICC limit */
1901 return profile_error(png_ptr, colorspace, name, temp,
1902 "invalid rendering intent");
1903
1904 /* This is just a warning because the profile may be valid in future
1905 * versions.
1906 */
1907 if (temp >= PNG_sRGB_INTENT_LAST)
1908 (void)profile_error(png_ptr, NULL, name, temp,
1909 "intent outside defined range");
1910
1911 /* At this point the tag table can't be checked because it hasn't necessarily
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05001912 * been loaded; however, various header fields can be checked. These checks
John Bowlerb11b31a2012-03-21 07:55:46 -05001913 * are for values permitted by the PNG spec in an ICC profile; the PNG spec
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05001914 * restricts the profiles that can be passed in an iCCP chunk (they must be
John Bowlerb11b31a2012-03-21 07:55:46 -05001915 * appropriate to processing PNG data!)
1916 */
1917
1918 /* Data checks (could be skipped). These checks must be independent of the
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05001919 * version number; however, the version number doesn't accomodate changes in
John Bowlerb11b31a2012-03-21 07:55:46 -05001920 * the header fields (just the known tags and the interpretation of the
1921 * data.)
1922 */
1923 temp = png_get_uint_32(profile+36); /* signature 'ascp' */
1924 if (temp != 0x61637370)
1925 return profile_error(png_ptr, colorspace, name, temp,
1926 "invalid signature");
1927
1928 /* The PNG spec requires this:
1929 * "If the iCCP chunk is present, the image samples conform to the colour
1930 * space represented by the embedded ICC profile as defined by the
1931 * International Color Consortium [ICC]. The colour space of the ICC profile
1932 * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
1933 * 6), or a greyscale colour space for greyscale images (PNG colour types 0
1934 * and 4)."
1935 *
1936 * This code does not check the color type because png_set_iCCP may be called
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05001937 * before png_set_IHDR on write and because, anyway, the PNG spec is
John Bowlerb11b31a2012-03-21 07:55:46 -05001938 * fundamentally flawed: RGB profiles can be used quite meaningfully for
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05001939 * grayscale images and both RGB and palette images might only have gray
1940 * colors in them, so gray profiles may be appropriate.
John Bowlerb11b31a2012-03-21 07:55:46 -05001941 */
1942 temp = png_get_uint_32(profile+16); /* data colour space field */
1943 if (temp != 0x52474220 /* 'RGB ' */ && temp != 0x47524159 /* 'GRAY' */)
1944 return profile_error(png_ptr, colorspace, name, temp,
1945 "invalid color space");
1946
1947 /* It is up to the application to check that the profile class matches the
1948 * application requirements; the spec provides no guidance, but it's pretty
1949 * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
1950 * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these
1951 * cases.
1952 */
1953 temp = png_get_uint_32(profile+12); /* profile/device class */
1954 if (temp != 0x73636E72 /* 'scnr' */ && temp != 0x6D6E7472 /* 'mntr' */ &&
1955 temp != 0x70727472 /* 'prtr' */ && temp != 0x73706163 /* 'spac' */)
1956 (void)profile_error(png_ptr, NULL, name, temp, "unexpected class");
1957
1958 return 1;
1959}
1960
1961int /* PRIVATE */
1962png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
1963 png_const_charp name, png_uint_32 profile_length,
1964 png_const_bytep profile /* header plus whole tag table */)
1965{
1966 png_uint_32 tag_count = png_get_uint_32(profile+128);
1967 png_uint_32 itag;
1968 png_const_bytep tag = profile+132; /* The first tag */
1969
1970 for (itag=0; itag < tag_count; ++itag, tag += 12)
1971 {
1972 png_uint_32 tag_id = png_get_uint_32(tag+0);
1973 png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
1974 png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
1975
1976 /* The ICC specification does not exclude zero length tags, therefore the
1977 * start might actually be anywhere if there is no data, but this would be
1978 * a clear abuse of the intent of the standard so the start is checked for
1979 * being in range.
1980 */
1981 if ((tag_start & 3) != 0 || tag_start > profile_length ||
1982 tag_length > profile_length - tag_start)
1983 return profile_error(png_ptr, colorspace, name, tag_id,
1984 "tag data outside profile");
1985 }
1986
1987 return 1;
1988}
1989
John Bowler921648a2012-03-28 23:36:12 -05001990#ifdef PNG_sRGB_SUPPORTED
1991/* Information about the known ICC sRGB profiles */
1992static const struct
1993{
1994 png_uint_32 adler, crc, length;
1995 png_uint_32 md5[4];
1996 png_uint_16 have_md5;
1997 png_uint_16 intent;
1998
1999# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
2000# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, date, length, fname)\
2001 { adler, crc, length, md5, intent },
2002
2003} png_sRGB_checks[] =
2004{
2005 /* This data comes from contrib/tools/checksum-icc run on downloads of
2006 * all four ICC sRGB profiles from www.color.org.
2007 */
2008 /* adler32, crc32, MD5[4], intent, date, length, file-name */
2009 PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
2010 PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0,
2011 "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
2012
2013 /* ICC sRGB v2 perceptual no black-compensation: */
2014 PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
2015 PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1,
2016 "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
2017
2018 PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
2019 PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0,
2020 "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
2021
2022 /* ICC sRGB v4 perceptual */
2023 PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
2024 PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0,
2025 "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
2026
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05002027 /* The following profiles have no known MD5 checksum. If there is a match
John Bowler921648a2012-03-28 23:36:12 -05002028 * on the (empty) MD5 the other fields are used to attempt a match and
2029 * a warning is produced. The first two of these profiles have a 'cprt' tag
2030 * which suggests that they were also made by Hewlett Packard.
2031 */
2032 PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
2033 PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1,
2034 "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
2035
2036 PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
2037 PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0,
2038 "1998/02/09 06:49:00", 3144, "sRGB Profile.icc")
2039
2040 PNG_ICC_CHECKSUM(0x0398f3fcUL, 0xf29e526dUL,
Glenn Randers-Pehrson96027d92012-03-29 06:15:55 -05002041 PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1,
2042 "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
John Bowler921648a2012-03-28 23:36:12 -05002043};
2044
2045static int
2046png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
2047 png_const_bytep profile, uLong adler)
2048{
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05002049 /* The quick check is to verify just the MD5 signature and trust the
John Bowler921648a2012-03-28 23:36:12 -05002050 * rest of the data. Because the profile has already been verified for
2051 * correctness this is safe. png_colorspace_set_sRGB will check the 'intent'
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05002052 * field too, so if the profile has been edited with an intent not defined
John Bowler921648a2012-03-28 23:36:12 -05002053 * by sRGB (but maybe defined by a later ICC specification) the read of
2054 * the profile will fail at that point.
2055 */
2056 png_uint_32 length = 0;
2057 png_uint_32 intent = 0x10000; /* invalid */
2058#if PNG_sRGB_PROFILE_CHECKS > 1
2059 uLong crc = 0; /* the value for 0 length data */
2060#endif
2061 unsigned int i;
2062
2063 for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
2064 {
2065 if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05002066 png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
2067 png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
John Bowler921648a2012-03-28 23:36:12 -05002068 png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
2069 {
2070 /* This may be one of the old HP profiles without an MD5, in that
2071 * case we can only use the length and Adler32 (note that these
2072 * are not used by default if there is an MD5!)
2073 */
2074# if PNG_sRGB_PROFILE_CHECKS == 0
2075 if (png_sRGB_checks[i].have_md5)
2076 return 1;
2077# endif
2078
2079 /* Profile is unsigned or more checks have been configured in. */
2080 if (length == 0)
2081 {
2082 length = png_get_uint_32(profile);
2083 intent = png_get_uint_32(profile+64);
2084 }
2085
2086 /* Length *and* intent must match */
2087 if (length == png_sRGB_checks[i].length &&
2088 intent == png_sRGB_checks[i].intent)
2089 {
2090 /* Now calculate the alder32 if not done already. */
2091 if (adler == 0)
2092 {
2093 adler = adler32(0, NULL, 0);
2094 adler = adler32(adler, profile, length);
2095 }
2096
2097 if (adler == png_sRGB_checks[i].adler)
2098 {
2099 /* These basic checks suggest that the data has not been
2100 * modified, but if the check level is more than 1 perform
2101 * our own crc32 checksum on the data.
2102 */
2103# if PNG_sRGB_PROFILE_CHECKS > 1
2104 if (crc == 0)
2105 {
2106 crc = crc32(0, NULL, 0);
2107 crc = crc32(crc, profile, length);
2108 }
2109
2110 /* So this check must pass for the 'return' below to happen.
2111 */
2112 if (crc == png_sRGB_checks[i].crc)
2113# endif
2114 {
2115 /* Warn that this being done; this isn't even an error since
2116 * the profile is perfectly valid, but it would be nice if
2117 * people used the up-to-date ones.
2118 */
2119 if (!png_sRGB_checks[i].have_md5)
2120 {
2121# ifdef PNG_READ_SUPPORTED
2122 if (png_ptr->mode & PNG_IS_READ_STRUCT)
2123 png_chunk_warning(png_ptr,
2124 "out-of-date sRGB profile with no signature");
2125 else
2126# endif
2127 png_app_warning(png_ptr,
2128 "out-of-date sRGB profile with no signature");
2129 }
2130
2131 return 1;
2132 }
2133 }
2134 }
2135
2136# if PNG_sRGB_PROFILE_CHECKS > 0
2137 /* The signature matched, but the profile had been changed in some
2138 * way. This is an apparent violation of the ICC terms of use and,
2139 * anyway, the rejection may be unexpected.
2140 */
2141 if (png_sRGB_checks[i].have_md5)
2142 png_benign_error(png_ptr,
2143 "copyright violation: edited ICC profile ignored");
2144# endif
2145 }
2146 }
2147
2148 return 0; /* no match */
2149}
2150#endif
2151
2152int /* PRIVATE */
John Bowlerb11b31a2012-03-21 07:55:46 -05002153png_icc_set_gAMA_and_cHRM(png_const_structrp png_ptr,
2154 png_colorspacerp colorspace, png_const_charp name, png_const_bytep profile,
John Bowler921648a2012-03-28 23:36:12 -05002155 uLong adler, int preferred)
John Bowlerb11b31a2012-03-21 07:55:46 -05002156{
John Bowler921648a2012-03-28 23:36:12 -05002157# ifdef PNG_sRGB_SUPPORTED
Glenn Randers-Pehrson747b5542012-03-29 08:28:19 -05002158 /* 1) Is this profile one of the known ICC sRGB profiles? If it is, just
John Bowler921648a2012-03-28 23:36:12 -05002159 * set the sRGB information.
2160 */
2161 if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler))
2162 return png_colorspace_set_sRGB(png_ptr, colorspace,
2163 (int)/*already checked*/png_get_uint_32(profile+64), preferred);
2164
2165 else
2166# endif
2167
2168 /* 2) Attempt to extract the gAMA and cHRM information from non-sRGB
2169 * profiles.
2170 */
2171 {
2172 /* TODO: implement this! */
2173 PNG_UNUSED(name) /* NYI */
2174 return 1;
2175 }
John Bowlerb11b31a2012-03-21 07:55:46 -05002176}
2177
2178int /* PRIVATE */
2179png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
2180 png_const_charp name, png_uint_32 profile_length,
2181 png_const_bytep profile, int preferred)
2182{
2183 if (colorspace->flags & PNG_COLORSPACE_INVALID)
2184 return 0;
2185
2186 if (png_icc_check_length(png_ptr, colorspace, name, profile_length) &&
2187 png_icc_check_header(png_ptr, colorspace, name, profile_length, profile)
2188 && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
2189 profile))
2190 {
John Bowler921648a2012-03-28 23:36:12 -05002191 png_icc_set_gAMA_and_cHRM(png_ptr, colorspace, name, profile, 0,
2192 preferred);
John Bowlerb11b31a2012-03-21 07:55:46 -05002193 return 1;
2194 }
2195
2196 /* Failure case */
2197 return 0;
2198}
2199#endif /* iCCP */
2200
2201#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2202void /* PRIVATE */
2203png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
2204{
2205 /* Set the rgb_to_gray coefficients from the colorspace. */
2206 if (!png_ptr->rgb_to_gray_coefficients_set &&
2207 (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
2208 {
2209 /* png_set_background has not been called, get the coefficients from the Y
2210 * values of the colorspace colorants.
2211 */
Glenn Randers-Pehrson702053d2012-08-17 21:23:06 -05002212 png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
2213 png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
2214 png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
John Bowlerb11b31a2012-03-21 07:55:46 -05002215 png_fixed_point total = r+g+b;
2216
2217 if (total > 0 &&
2218 r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
2219 g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
2220 b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
2221 r+g+b <= 32769)
2222 {
2223 /* We allow 0 coefficients here. r+g+b may be 32769 if two or
2224 * all of the coefficients were rounded up. Handle this by
2225 * reducing the *largest* coefficient by 1; this matches the
2226 * approach used for the default coefficients in pngrtran.c
2227 */
2228 int add = 0;
2229
2230 if (r+g+b > 32768)
2231 add = -1;
2232 else if (r+g+b < 32768)
2233 add = 1;
2234
2235 if (add != 0)
2236 {
2237 if (g >= r && g >= b)
2238 g += add;
2239 else if (r >= g && r >= b)
2240 r += add;
2241 else
2242 b += add;
2243 }
2244
2245 /* Check for an internal error. */
2246 if (r+g+b != 32768)
2247 png_error(png_ptr,
2248 "internal error handling cHRM coefficients");
2249
2250 else
2251 {
2252 png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r;
2253 png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
2254 }
2255 }
2256
2257 /* This is a png_error at present even though it could be ignored -
2258 * it should never happen, but it is important that if it does, the
2259 * bug is fixed.
2260 */
2261 else
2262 png_error(png_ptr, "internal error handling cHRM->XYZ");
2263 }
2264}
John Bowler736f40f2011-08-25 16:19:44 -05002265#endif
2266
John Bowlerb11b31a2012-03-21 07:55:46 -05002267#endif /* COLORSPACE */
2268
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002269void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06002270png_check_IHDR(png_const_structrp png_ptr,
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002271 png_uint_32 width, png_uint_32 height, int bit_depth,
2272 int color_type, int interlace_type, int compression_type,
2273 int filter_type)
2274{
2275 int error = 0;
2276
2277 /* Check for width and height valid values */
2278 if (width == 0)
2279 {
2280 png_warning(png_ptr, "Image width is zero in IHDR");
2281 error = 1;
2282 }
2283
2284 if (height == 0)
2285 {
2286 png_warning(png_ptr, "Image height is zero in IHDR");
2287 error = 1;
2288 }
2289
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002290# ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonb7040362011-06-11 14:20:22 -05002291 if (width > png_ptr->user_width_max)
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002292
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002293# else
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002294 if (width > PNG_USER_WIDTH_MAX)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002295# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002296 {
2297 png_warning(png_ptr, "Image width exceeds user limit in IHDR");
2298 error = 1;
2299 }
2300
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002301# ifdef PNG_SET_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonb7040362011-06-11 14:20:22 -05002302 if (height > png_ptr->user_height_max)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002303# else
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002304 if (height > PNG_USER_HEIGHT_MAX)
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002305# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002306 {
2307 png_warning(png_ptr, "Image height exceeds user limit in IHDR");
2308 error = 1;
2309 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002310
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002311 if (width > PNG_UINT_31_MAX)
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002312 {
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002313 png_warning(png_ptr, "Invalid image width in IHDR");
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002314 error = 1;
2315 }
2316
Glenn Randers-Pehrsonbc363ec2010-10-12 21:17:00 -05002317 if (height > PNG_UINT_31_MAX)
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002318 {
Glenn Randers-Pehrsondd66f3e2009-09-30 14:58:28 -05002319 png_warning(png_ptr, "Invalid image height in IHDR");
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002320 error = 1;
2321 }
2322
Glenn Randers-Pehrsonbc363ec2010-10-12 21:17:00 -05002323 if (width > (PNG_UINT_32_MAX
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002324 >> 3) /* 8-byte RGBA pixels */
Glenn Randers-Pehrsonc5080812010-10-23 08:26:26 -05002325 - 48 /* bigrowbuf hack */
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002326 - 1 /* filter byte */
2327 - 7*8 /* rounding of width to multiple of 8 pixels */
2328 - 8) /* extra max_pixel_depth pad */
2329 png_warning(png_ptr, "Width is too large for libpng to process pixels");
2330
2331 /* Check other values */
2332 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
2333 bit_depth != 8 && bit_depth != 16)
2334 {
2335 png_warning(png_ptr, "Invalid bit depth in IHDR");
2336 error = 1;
2337 }
2338
2339 if (color_type < 0 || color_type == 1 ||
2340 color_type == 5 || color_type > 6)
2341 {
2342 png_warning(png_ptr, "Invalid color type in IHDR");
2343 error = 1;
2344 }
2345
2346 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
2347 ((color_type == PNG_COLOR_TYPE_RGB ||
2348 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
2349 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
2350 {
2351 png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
2352 error = 1;
2353 }
2354
2355 if (interlace_type >= PNG_INTERLACE_LAST)
2356 {
2357 png_warning(png_ptr, "Unknown interlace method in IHDR");
2358 error = 1;
2359 }
2360
2361 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
2362 {
2363 png_warning(png_ptr, "Unknown compression method in IHDR");
2364 error = 1;
2365 }
2366
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002367# ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002368 /* Accept filter_method 64 (intrapixel differencing) only if
2369 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
2370 * 2. Libpng did not read a PNG signature (this filter_method is only
2371 * used in PNG datastreams that are embedded in MNG datastreams) and
2372 * 3. The application called png_permit_mng_features with a mask that
2373 * included PNG_FLAG_MNG_FILTER_64 and
2374 * 4. The filter_method is 64 and
2375 * 5. The color_type is RGB or RGBA
2376 */
2377 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
2378 png_ptr->mng_features_permitted)
2379 png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
2380
2381 if (filter_type != PNG_FILTER_TYPE_BASE)
2382 {
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05002383 if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002384 (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
2385 ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
2386 (color_type == PNG_COLOR_TYPE_RGB ||
2387 color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05002388 {
2389 png_warning(png_ptr, "Unknown filter method in IHDR");
2390 error = 1;
2391 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002392
Glenn Randers-Pehrson7ec330d2009-09-25 11:45:42 -05002393 if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
2394 {
2395 png_warning(png_ptr, "Invalid filter method in IHDR");
2396 error = 1;
2397 }
2398 }
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002399
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002400# else
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002401 if (filter_type != PNG_FILTER_TYPE_BASE)
2402 {
2403 png_warning(png_ptr, "Unknown filter method in IHDR");
2404 error = 1;
2405 }
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -06002406# endif
Glenn Randers-Pehrson134bbe42009-09-24 18:10:49 -05002407
2408 if (error == 1)
2409 png_error(png_ptr, "Invalid IHDR data");
2410}
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002411
2412#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
2413/* ASCII to fp functions */
2414/* Check an ASCII formated floating point value, see the more detailed
2415 * comments in pngpriv.h
2416 */
John Bowler8d261262011-06-18 13:37:11 -05002417/* The following is used internally to preserve the sticky flags */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002418#define png_fp_add(state, flags) ((state) |= (flags))
John Bowler8d261262011-06-18 13:37:11 -05002419#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002420
2421int /* PRIVATE */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002422png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002423 png_size_tp whereami)
2424{
2425 int state = *statep;
2426 png_size_t i = *whereami;
2427
2428 while (i < size)
2429 {
2430 int type;
2431 /* First find the type of the next character */
John Bowler8d261262011-06-18 13:37:11 -05002432 switch (string[i])
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002433 {
John Bowler8d261262011-06-18 13:37:11 -05002434 case 43: type = PNG_FP_SAW_SIGN; break;
2435 case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
2436 case 46: type = PNG_FP_SAW_DOT; break;
2437 case 48: type = PNG_FP_SAW_DIGIT; break;
2438 case 49: case 50: case 51: case 52:
2439 case 53: case 54: case 55: case 56:
2440 case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
2441 case 69:
2442 case 101: type = PNG_FP_SAW_E; break;
2443 default: goto PNG_FP_End;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002444 }
2445
2446 /* Now deal with this type according to the current
2447 * state, the type is arranged to not overlap the
2448 * bits of the PNG_FP_STATE.
2449 */
John Bowler8d261262011-06-18 13:37:11 -05002450 switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002451 {
John Bowler8d261262011-06-18 13:37:11 -05002452 case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002453 if (state & PNG_FP_SAW_ANY)
2454 goto PNG_FP_End; /* not a part of the number */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002455
John Bowler8d261262011-06-18 13:37:11 -05002456 png_fp_add(state, type);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002457 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002458
John Bowler8d261262011-06-18 13:37:11 -05002459 case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002460 /* Ok as trailer, ok as lead of fraction. */
2461 if (state & PNG_FP_SAW_DOT) /* two dots */
2462 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002463
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002464 else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
John Bowler8d261262011-06-18 13:37:11 -05002465 png_fp_add(state, type);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002466
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002467 else
John Bowler8d261262011-06-18 13:37:11 -05002468 png_fp_set(state, PNG_FP_FRACTION | type);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002469
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002470 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002471
John Bowler8d261262011-06-18 13:37:11 -05002472 case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002473 if (state & PNG_FP_SAW_DOT) /* delayed fraction */
2474 png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002475
John Bowler8d261262011-06-18 13:37:11 -05002476 png_fp_add(state, type | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002477
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002478 break;
John Bowler8d261262011-06-18 13:37:11 -05002479
2480 case PNG_FP_INTEGER + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002481 if ((state & PNG_FP_SAW_DIGIT) == 0)
2482 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002483
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002484 png_fp_set(state, PNG_FP_EXPONENT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002485
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002486 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002487
John Bowler8d261262011-06-18 13:37:11 -05002488 /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:
2489 goto PNG_FP_End; ** no sign in fraction */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002490
John Bowler8d261262011-06-18 13:37:11 -05002491 /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002492 goto PNG_FP_End; ** Because SAW_DOT is always set */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002493
John Bowler8d261262011-06-18 13:37:11 -05002494 case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
2495 png_fp_add(state, type | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002496 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002497
John Bowler8d261262011-06-18 13:37:11 -05002498 case PNG_FP_FRACTION + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002499 /* This is correct because the trailing '.' on an
2500 * integer is handled above - so we can only get here
2501 * with the sequence ".E" (with no preceding digits).
2502 */
2503 if ((state & PNG_FP_SAW_DIGIT) == 0)
2504 goto PNG_FP_End;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002505
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002506 png_fp_set(state, PNG_FP_EXPONENT);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002507
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002508 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002509
John Bowler8d261262011-06-18 13:37:11 -05002510 case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002511 if (state & PNG_FP_SAW_ANY)
2512 goto PNG_FP_End; /* not a part of the number */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002513
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002514 png_fp_add(state, PNG_FP_SAW_SIGN);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002515
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002516 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002517
John Bowler8d261262011-06-18 13:37:11 -05002518 /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002519 goto PNG_FP_End; */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002520
John Bowler8d261262011-06-18 13:37:11 -05002521 case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
2522 png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002523
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002524 break;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002525
John Bowler8d261262011-06-18 13:37:11 -05002526 /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002527 goto PNG_FP_End; */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002528
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002529 default: goto PNG_FP_End; /* I.e. break 2 */
2530 }
2531
2532 /* The character seems ok, continue. */
2533 ++i;
2534 }
2535
2536PNG_FP_End:
2537 /* Here at the end, update the state and return the correct
2538 * return code.
2539 */
2540 *statep = state;
2541 *whereami = i;
2542
2543 return (state & PNG_FP_SAW_DIGIT) != 0;
2544}
2545
2546
2547/* The same but for a complete string. */
2548int
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002549png_check_fp_string(png_const_charp string, png_size_t size)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002550{
2551 int state=0;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002552 png_size_t char_index=0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002553
John Bowler8d261262011-06-18 13:37:11 -05002554 if (png_check_fp_number(string, size, &state, &char_index) &&
2555 (char_index == size || string[char_index] == 0))
2556 return state /* must be non-zero - see above */;
2557
2558 return 0; /* i.e. fail */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002559}
2560#endif /* pCAL or sCAL */
2561
John Bowlerba2dd332012-08-10 10:58:01 -05002562#ifdef PNG_sCAL_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002563# ifdef PNG_FLOATING_POINT_SUPPORTED
2564/* Utility used below - a simple accurate power of ten from an integral
2565 * exponent.
2566 */
2567static double
2568png_pow10(int power)
2569{
2570 int recip = 0;
2571 double d = 1;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002572
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002573 /* Handle negative exponent with a reciprocal at the end because
2574 * 10 is exact whereas .1 is inexact in base 2
2575 */
2576 if (power < 0)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002577 {
2578 if (power < DBL_MIN_10_EXP) return 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002579 recip = 1, power = -power;
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002580 }
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002581
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002582 if (power > 0)
2583 {
2584 /* Decompose power bitwise. */
2585 double mult = 10;
2586 do
2587 {
2588 if (power & 1) d *= mult;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002589 mult *= mult;
2590 power >>= 1;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002591 }
2592 while (power > 0);
2593
2594 if (recip) d = 1/d;
2595 }
2596 /* else power is 0 and d is 1 */
2597
2598 return d;
2599}
2600
2601/* Function to format a floating point value in ASCII with a given
2602 * precision.
2603 */
2604void /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -06002605png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002606 double fp, unsigned int precision)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002607{
2608 /* We use standard functions from math.h, but not printf because
2609 * that would require stdio. The caller must supply a buffer of
2610 * sufficient size or we will png_error. The tests on size and
2611 * the space in ascii[] consumed are indicated below.
2612 */
2613 if (precision < 1)
2614 precision = DBL_DIG;
2615
2616 /* Enforce the limit of the implementation precision too. */
2617 if (precision > DBL_DIG+1)
2618 precision = DBL_DIG+1;
2619
2620 /* Basic sanity checks */
2621 if (size >= precision+5) /* See the requirements below. */
2622 {
2623 if (fp < 0)
2624 {
2625 fp = -fp;
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05002626 *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002627 --size;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002628 }
2629
2630 if (fp >= DBL_MIN && fp <= DBL_MAX)
2631 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002632 int exp_b10; /* A base 10 exponent */
2633 double base; /* 10^exp_b10 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002634
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002635 /* First extract a base 10 exponent of the number,
2636 * the calculation below rounds down when converting
2637 * from base 2 to base 10 (multiply by log10(2) -
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002638 * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002639 * be increased. Note that the arithmetic shift
2640 * performs a floor() unlike C arithmetic - using a
2641 * C multiply would break the following for negative
2642 * exponents.
2643 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002644 (void)frexp(fp, &exp_b10); /* exponent to base 2 */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002645
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002646 exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002647
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002648 /* Avoid underflow here. */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002649 base = png_pow10(exp_b10); /* May underflow */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002650
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002651 while (base < DBL_MIN || base < fp)
2652 {
2653 /* And this may overflow. */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002654 double test = png_pow10(exp_b10+1);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002655
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002656 if (test <= DBL_MAX)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002657 ++exp_b10, base = test;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002658
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002659 else
2660 break;
2661 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002662
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002663 /* Normalize fp and correct exp_b10, after this fp is in the
2664 * range [.1,1) and exp_b10 is both the exponent and the digit
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002665 * *before* which the decimal point should be inserted
2666 * (starting with 0 for the first digit). Note that this
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002667 * works even if 10^exp_b10 is out of range because of the
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002668 * test on DBL_MAX above.
2669 */
2670 fp /= base;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002671 while (fp >= 1) fp /= 10, ++exp_b10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002672
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002673 /* Because of the code above fp may, at this point, be
2674 * less than .1, this is ok because the code below can
2675 * handle the leading zeros this generates, so no attempt
2676 * is made to correct that here.
2677 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002678
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002679 {
2680 int czero, clead, cdigits;
2681 char exponent[10];
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002682
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002683 /* Allow up to two leading zeros - this will not lengthen
2684 * the number compared to using E-n.
2685 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002686 if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002687 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002688 czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */
2689 exp_b10 = 0; /* Dot added below before first output. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002690 }
2691 else
2692 czero = 0; /* No zeros to add */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002693
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002694 /* Generate the digit list, stripping trailing zeros and
2695 * inserting a '.' before a digit if the exponent is 0.
2696 */
2697 clead = czero; /* Count of leading zeros */
2698 cdigits = 0; /* Count of digits in list. */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002699
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002700 do
2701 {
2702 double d;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002703
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002704 fp *= 10;
2705 /* Use modf here, not floor and subtract, so that
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002706 * the separation is done in one step. At the end
2707 * of the loop don't break the number into parts so
2708 * that the final digit is rounded.
2709 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002710 if (cdigits+czero-clead+1 < (int)precision)
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002711 fp = modf(fp, &d);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002712
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002713 else
2714 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002715 d = floor(fp + .5);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002716
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002717 if (d > 9)
2718 {
2719 /* Rounding up to 10, handle that here. */
2720 if (czero > 0)
2721 {
2722 --czero, d = 1;
2723 if (cdigits == 0) --clead;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002724 }
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002725 else
2726 {
2727 while (cdigits > 0 && d > 9)
2728 {
2729 int ch = *--ascii;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002730
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002731 if (exp_b10 != (-1))
2732 ++exp_b10;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002733
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002734 else if (ch == 46)
2735 {
2736 ch = *--ascii, ++size;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002737 /* Advance exp_b10 to '1', so that the
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002738 * decimal point happens after the
2739 * previous digit.
2740 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002741 exp_b10 = 1;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002742 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002743
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002744 --cdigits;
2745 d = ch - 47; /* I.e. 1+(ch-48) */
2746 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002747
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002748 /* Did we reach the beginning? If so adjust the
2749 * exponent but take into account the leading
2750 * decimal point.
2751 */
2752 if (d > 9) /* cdigits == 0 */
2753 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002754 if (exp_b10 == (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002755 {
2756 /* Leading decimal point (plus zeros?), if
2757 * we lose the decimal point here it must
2758 * be reentered below.
2759 */
2760 int ch = *--ascii;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002761
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002762 if (ch == 46)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002763 ++size, exp_b10 = 1;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002764
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002765 /* Else lost a leading zero, so 'exp_b10' is
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002766 * still ok at (-1)
2767 */
2768 }
2769 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002770 ++exp_b10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002771
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002772 /* In all cases we output a '1' */
2773 d = 1;
2774 }
2775 }
2776 }
2777 fp = 0; /* Guarantees termination below. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002778 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002779
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002780 if (d == 0)
2781 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002782 ++czero;
2783 if (cdigits == 0) ++clead;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002784 }
2785 else
2786 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002787 /* Included embedded zeros in the digit count. */
2788 cdigits += czero - clead;
2789 clead = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002790
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002791 while (czero > 0)
2792 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002793 /* exp_b10 == (-1) means we just output the decimal
2794 * place - after the DP don't adjust 'exp_b10' any
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002795 * more!
2796 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002797 if (exp_b10 != (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002798 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002799 if (exp_b10 == 0) *ascii++ = 46, --size;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002800 /* PLUS 1: TOTAL 4 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002801 --exp_b10;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002802 }
2803 *ascii++ = 48, --czero;
2804 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002805
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002806 if (exp_b10 != (-1))
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002807 {
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002808 if (exp_b10 == 0) *ascii++ = 46, --size; /* counted
2809 above */
2810 --exp_b10;
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002811 }
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002812 *ascii++ = (char)(48 + (int)d), ++cdigits;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002813 }
2814 }
2815 while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002816
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002817 /* The total output count (max) is now 4+precision */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002818
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002819 /* Check for an exponent, if we don't need one we are
2820 * done and just need to terminate the string. At
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002821 * this point exp_b10==(-1) is effectively if flag - it got
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002822 * to '-1' because of the decrement after outputing
2823 * the decimal point above (the exponent required is
2824 * *not* -1!)
2825 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002826 if (exp_b10 >= (-1) && exp_b10 <= 2)
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002827 {
2828 /* The following only happens if we didn't output the
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002829 * leading zeros above for negative exponent, so this
2830 * doest add to the digit requirement. Note that the
2831 * two zeros here can only be output if the two leading
2832 * zeros were *not* output, so this doesn't increase
2833 * the output count.
2834 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06002835 while (--exp_b10 >= 0) *ascii++ = 48;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002836
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002837 *ascii = 0;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002838
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002839 /* Total buffer requirement (including the '\0') is
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05002840 * 5+precision - see check at the start.
2841 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002842 return;
2843 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002844
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002845 /* Here if an exponent is required, adjust size for
2846 * the digits we output but did not count. The total
2847 * digit output here so far is at most 1+precision - no
2848 * decimal point and no leading or trailing zeros have
2849 * been output.
2850 */
2851 size -= cdigits;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002852
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05002853 *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002854
John Bowler75156122011-09-09 17:21:44 -05002855 /* The following use of an unsigned temporary avoids ambiguities in
2856 * the signed arithmetic on exp_b10 and permits GCC at least to do
2857 * better optimization.
2858 */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002859 {
John Bowler75156122011-09-09 17:21:44 -05002860 unsigned int uexp_b10;
2861
2862 if (exp_b10 < 0)
2863 {
2864 *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
2865 uexp_b10 = -exp_b10;
2866 }
2867
2868 else
2869 uexp_b10 = exp_b10;
2870
2871 cdigits = 0;
2872
2873 while (uexp_b10 > 0)
2874 {
2875 exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
2876 uexp_b10 /= 10;
2877 }
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002878 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002879
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002880 /* Need another size check here for the exponent digits, so
2881 * this need not be considered above.
2882 */
2883 if ((int)size > cdigits)
2884 {
2885 while (cdigits > 0) *ascii++ = exponent[--cdigits];
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002886
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002887 *ascii = 0;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05002888
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002889 return;
2890 }
2891 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002892 }
2893 else if (!(fp >= DBL_MIN))
2894 {
2895 *ascii++ = 48; /* '0' */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002896 *ascii = 0;
2897 return;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002898 }
2899 else
2900 {
2901 *ascii++ = 105; /* 'i' */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05002902 *ascii++ = 110; /* 'n' */
2903 *ascii++ = 102; /* 'f' */
2904 *ascii = 0;
2905 return;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002906 }
2907 }
2908
2909 /* Here on buffer too small. */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05002910 png_error(png_ptr, "ASCII conversion buffer too small");
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002911}
2912
2913# endif /* FLOATING_POINT */
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002914
2915# ifdef PNG_FIXED_POINT_SUPPORTED
2916/* Function to format a fixed point value in ASCII.
2917 */
2918void /* PRIVATE */
John Bowler4f67e402011-12-28 08:43:37 -06002919png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
2920 png_size_t size, png_fixed_point fp)
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002921{
2922 /* Require space for 10 decimal digits, a decimal point, a minus sign and a
2923 * trailing \0, 13 characters:
2924 */
2925 if (size > 12)
2926 {
2927 png_uint_32 num;
2928
2929 /* Avoid overflow here on the minimum integer. */
2930 if (fp < 0)
2931 *ascii++ = 45, --size, num = -fp;
2932 else
2933 num = fp;
2934
John Bowler75156122011-09-09 17:21:44 -05002935 if (num <= 0x80000000) /* else overflowed */
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002936 {
Glenn Randers-Pehrsonb75b2412011-04-16 19:35:05 -05002937 unsigned int ndigits = 0, first = 16 /* flag value */;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002938 char digits[10];
2939
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002940 while (num)
2941 {
2942 /* Split the low digit off num: */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002943 unsigned int tmp = num/10;
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002944 num -= tmp*10;
2945 digits[ndigits++] = (char)(48 + num);
2946 /* Record the first non-zero digit, note that this is a number
2947 * starting at 1, it's not actually the array index.
2948 */
2949 if (first == 16 && num > 0)
2950 first = ndigits;
2951 num = tmp;
2952 }
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002953
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002954 if (ndigits > 0)
2955 {
2956 while (ndigits > 5) *ascii++ = digits[--ndigits];
2957 /* The remaining digits are fractional digits, ndigits is '5' or
2958 * smaller at this point. It is certainly not zero. Check for a
2959 * non-zero fractional digit:
2960 */
2961 if (first <= 5)
2962 {
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05002963 unsigned int i;
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002964 *ascii++ = 46; /* decimal point */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05002965 /* ndigits may be <5 for small numbers, output leading zeros
2966 * then ndigits digits to first:
2967 */
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002968 i = 5;
2969 while (ndigits < i) *ascii++ = 48, --i;
2970 while (ndigits >= first) *ascii++ = digits[--ndigits];
2971 /* Don't output the trailing zeros! */
2972 }
2973 }
2974 else
2975 *ascii++ = 48;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002976
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05002977 /* And null terminate the string: */
2978 *ascii = 0;
2979 return;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05002980 }
2981 }
2982
2983 /* Here on buffer too small. */
2984 png_error(png_ptr, "ASCII conversion buffer too small");
2985}
2986# endif /* FIXED_POINT */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002987#endif /* READ_SCAL */
2988
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05002989#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
Glenn Randers-Pehrson69541412012-08-10 12:56:57 -05002990 !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
2991 (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
2992 defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
2993 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
2994 (defined(PNG_sCAL_SUPPORTED) && \
2995 defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002996png_fixed_point
John Bowler5d567862011-12-24 09:12:00 -06002997png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05002998{
2999 double r = floor(100000 * fp + .5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003000
Glenn Randers-Pehrson77c3bf12011-01-20 15:56:31 -06003001 if (r > 2147483647. || r < -2147483648.)
3002 png_fixed_error(png_ptr, text);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003003
Glenn Randers-Pehrson77c3bf12011-01-20 15:56:31 -06003004 return (png_fixed_point)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003005}
3006#endif
3007
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -05003008#if defined(PNG_READ_GAMMA_SUPPORTED) || \
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003009 defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003010/* muldiv functions */
3011/* This API takes signed arguments and rounds the result to the nearest
3012 * integer (or, for a fixed point number - the standard argument - to
3013 * the nearest .00001). Overflow and divide by zero are signalled in
3014 * the result, a boolean - true on success, false on overflow.
3015 */
3016int
3017png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003018 png_int_32 divisor)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003019{
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003020 /* Return a * times / divisor, rounded. */
3021 if (divisor != 0)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003022 {
3023 if (a == 0 || times == 0)
3024 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003025 *res = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003026 return 1;
3027 }
3028 else
3029 {
3030#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003031 double r = a;
3032 r *= times;
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003033 r /= divisor;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003034 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003035
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003036 /* A png_fixed_point is a 32-bit integer. */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003037 if (r <= 2147483647. && r >= -2147483648.)
3038 {
3039 *res = (png_fixed_point)r;
3040 return 1;
3041 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003042#else
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003043 int negative = 0;
3044 png_uint_32 A, T, D;
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05003045 png_uint_32 s16, s32, s00;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003046
3047 if (a < 0)
3048 negative = 1, A = -a;
3049 else
3050 A = a;
3051
3052 if (times < 0)
3053 negative = !negative, T = -times;
3054 else
3055 T = times;
3056
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003057 if (divisor < 0)
3058 negative = !negative, D = -divisor;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003059 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003060 D = divisor;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003061
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003062 /* Following can't overflow because the arguments only
3063 * have 31 bits each, however the result may be 32 bits.
3064 */
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05003065 s16 = (A >> 16) * (T & 0xffff) +
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05003066 (A & 0xffff) * (T >> 16);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003067 /* Can't overflow because the a*times bit is only 30
3068 * bits at most.
3069 */
Glenn Randers-Pehrson3b5d6952010-08-19 08:06:12 -05003070 s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
3071 s00 = (A & 0xffff) * (T & 0xffff);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003072
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003073 s16 = (s16 & 0xffff) << 16;
3074 s00 += s16;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003075
3076 if (s00 < s16)
3077 ++s32; /* carry */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003078
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003079 if (s32 < D) /* else overflow */
3080 {
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003081 /* s32.s00 is now the 64-bit product, do a standard
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003082 * division, we know that s32 < D, so the maximum
3083 * required shift is 31.
3084 */
3085 int bitshift = 32;
3086 png_fixed_point result = 0; /* NOTE: signed */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003087
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003088 while (--bitshift >= 0)
3089 {
3090 png_uint_32 d32, d00;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003091
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003092 if (bitshift > 0)
3093 d32 = D >> (32-bitshift), d00 = D << bitshift;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003094
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003095 else
3096 d32 = 0, d00 = D;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003097
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003098 if (s32 > d32)
3099 {
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05003100 if (s00 < d00) --s32; /* carry */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003101 s32 -= d32, s00 -= d00, result += 1<<bitshift;
3102 }
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003103
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003104 else
3105 if (s32 == d32 && s00 >= d00)
3106 s32 = 0, s00 -= d00, result += 1<<bitshift;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003107 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003108
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003109 /* Handle the rounding. */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003110 if (s00 >= (D >> 1))
3111 ++result;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003112
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003113 if (negative)
3114 result = -result;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003115
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003116 /* Check for overflow. */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003117 if ((negative && result <= 0) || (!negative && result >= 0))
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003118 {
3119 *res = result;
3120 return 1;
3121 }
3122 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003123#endif
3124 }
3125 }
3126
3127 return 0;
3128}
3129#endif /* READ_GAMMA || INCH_CONVERSIONS */
3130
3131#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
3132/* The following is for when the caller doesn't much care about the
3133 * result.
3134 */
3135png_fixed_point
John Bowler5d567862011-12-24 09:12:00 -06003136png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003137 png_int_32 divisor)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003138{
3139 png_fixed_point result;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003140
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003141 if (png_muldiv(&result, a, times, divisor))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003142 return result;
3143
3144 png_warning(png_ptr, "fixed point overflow ignored");
3145 return 0;
3146}
3147#endif
3148
John Bowlerba2dd332012-08-10 10:58:01 -05003149#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003150/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
3151png_fixed_point
3152png_reciprocal(png_fixed_point a)
3153{
3154#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
3155 double r = floor(1E10/a+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003156
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003157 if (r <= 2147483647. && r >= -2147483648.)
3158 return (png_fixed_point)r;
3159#else
3160 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003161
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003162 if (png_muldiv(&res, 100000, 100000, a))
3163 return res;
3164#endif
3165
3166 return 0; /* error/overflow */
3167}
3168
John Bowlerba2dd332012-08-10 10:58:01 -05003169/* This is the shared test on whether a gamma value is 'significant' - whether
3170 * it is worth doing gamma correction.
3171 */
3172int /* PRIVATE */
3173png_gamma_significant(png_fixed_point gamma_val)
3174{
3175 return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
3176 gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
3177}
3178#endif
3179
3180#ifdef PNG_READ_GAMMA_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003181/* A local convenience routine. */
3182static png_fixed_point
3183png_product2(png_fixed_point a, png_fixed_point b)
3184{
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -05003185 /* The required result is 1/a * 1/b; the following preserves accuracy. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003186#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
3187 double r = a * 1E-5;
3188 r *= b;
3189 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003190
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003191 if (r <= 2147483647. && r >= -2147483648.)
3192 return (png_fixed_point)r;
3193#else
3194 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003195
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003196 if (png_muldiv(&res, a, b, 100000))
3197 return res;
3198#endif
3199
3200 return 0; /* overflow */
3201}
3202
3203/* The inverse of the above. */
3204png_fixed_point
3205png_reciprocal2(png_fixed_point a, png_fixed_point b)
3206{
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -05003207 /* The required result is 1/a * 1/b; the following preserves accuracy. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003208#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
3209 double r = 1E15/a;
3210 r /= b;
3211 r = floor(r+.5);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003212
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003213 if (r <= 2147483647. && r >= -2147483648.)
3214 return (png_fixed_point)r;
3215#else
3216 /* This may overflow because the range of png_fixed_point isn't symmetric,
3217 * but this API is only used for the product of file and screen gamma so it
3218 * doesn't matter that the smallest number it can produce is 1/21474, not
3219 * 1/100000
3220 */
3221 png_fixed_point res = png_product2(a, b);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003222
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003223 if (res != 0)
3224 return png_reciprocal(res);
3225#endif
3226
3227 return 0; /* overflow */
3228}
3229#endif /* READ_GAMMA */
3230
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003231#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
3232#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
3233/* Fixed point gamma.
3234 *
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003235 * The code to calculate the tables used below can be found in the shell script
3236 * contrib/tools/intgamma.sh
3237 *
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003238 * To calculate gamma this code implements fast log() and exp() calls using only
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003239 * fixed point arithmetic. This code has sufficient precision for either 8-bit
3240 * or 16-bit sample values.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003241 *
3242 * The tables used here were calculated using simple 'bc' programs, but C double
3243 * precision floating point arithmetic would work fine. The programs are given
3244 * at the head of each table.
3245 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003246 * 8-bit log table
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003247 * 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 -05003248 * 255, so it's the base 2 logarithm of a normalized 8-bit floating point
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003249 * mantissa. The numbers are 32-bit fractions.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003250 */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003251static const png_uint_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003252png_8bit_l2[128] =
3253{
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003254 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
3255 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
3256 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
3257 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
3258 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
3259 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
3260 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
3261 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
3262 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
3263 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
3264 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
3265 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
3266 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
3267 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
3268 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
3269 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
3270 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
3271 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
3272 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
3273 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
3274 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
3275 24347096U, 0U
Glenn Randers-Pehrson8888ea42011-11-28 11:29:10 -06003276
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003277#if 0
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003278 /* The following are the values for 16-bit tables - these work fine for the
3279 * 8-bit conversions but produce very slightly larger errors in the 16-bit
3280 * log (about 1.2 as opposed to 0.7 absolute error in the final value). To
3281 * use these all the shifts below must be adjusted appropriately.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003282 */
3283 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
3284 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
3285 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
3286 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
3287 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
3288 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
3289 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
3290 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
3291 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
3292 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
3293 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
3294 1119, 744, 372
3295#endif
3296};
3297
John Bowler8d261262011-06-18 13:37:11 -05003298PNG_STATIC png_int_32
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003299png_log8bit(unsigned int x)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003300{
John Bowler168a4332011-01-16 19:32:22 -06003301 unsigned int lg2 = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003302 /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
3303 * because the log is actually negate that means adding 1. The final
3304 * returned value thus has the range 0 (for 255 input) to 7.994 (for 1
3305 * input), return 7.99998 for the overflow (log 0) case - so the result is
3306 * always at most 19 bits.
3307 */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003308 if ((x &= 0xff) == 0)
Glenn Randers-Pehrsona5815562010-11-20 21:48:29 -06003309 return 0xffffffff;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003310
3311 if ((x & 0xf0) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003312 lg2 = 4, x <<= 4;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003313
3314 if ((x & 0xc0) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003315 lg2 += 2, x <<= 2;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003316
3317 if ((x & 0x80) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003318 lg2 += 1, x <<= 1;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003319
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003320 /* result is at most 19 bits, so this cast is safe: */
John Bowler168a4332011-01-16 19:32:22 -06003321 return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003322}
3323
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003324/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
3325 * 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 -05003326 * get an approximation then multiply the approximation by a correction factor
3327 * determined by the remaining up to 8 bits. This requires an additional step
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003328 * in the 16-bit case.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003329 *
3330 * We want log2(value/65535), we have log2(v'/255), where:
3331 *
3332 * value = v' * 256 + v''
3333 * = v' * f
3334 *
3335 * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
3336 * 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 -05003337 * than 258. The final factor also needs to correct for the fact that our 8-bit
3338 * value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003339 *
3340 * This gives a final formula using a calculated value 'x' which is value/v' and
3341 * scaling by 65536 to match the above table:
3342 *
3343 * log2(x/257) * 65536
3344 *
3345 * Since these numbers are so close to '1' we can use simple linear
3346 * interpolation between the two end values 256/257 (result -368.61) and 258/257
3347 * (result 367.179). The values used below are scaled by a further 64 to give
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003348 * 16-bit precision in the interpolation:
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003349 *
3350 * Start (256): -23591
3351 * Zero (257): 0
3352 * End (258): 23499
3353 */
John Bowler8d261262011-06-18 13:37:11 -05003354PNG_STATIC png_int_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003355png_log16bit(png_uint_32 x)
3356{
John Bowler168a4332011-01-16 19:32:22 -06003357 unsigned int lg2 = 0;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003358
3359 /* As above, but now the input has 16 bits. */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003360 if ((x &= 0xffff) == 0)
3361 return 0xffffffff;
3362
3363 if ((x & 0xff00) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003364 lg2 = 8, x <<= 8;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003365
3366 if ((x & 0xf000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003367 lg2 += 4, x <<= 4;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003368
3369 if ((x & 0xc000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003370 lg2 += 2, x <<= 2;
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003371
3372 if ((x & 0x8000) == 0)
John Bowler168a4332011-01-16 19:32:22 -06003373 lg2 += 1, x <<= 1;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003374
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003375 /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003376 * value.
3377 */
John Bowler168a4332011-01-16 19:32:22 -06003378 lg2 <<= 28;
3379 lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003380
3381 /* Now we need to interpolate the factor, this requires a division by the top
3382 * 8 bits. Do this with maximum precision.
3383 */
3384 x = ((x << 16) + (x >> 9)) / (x >> 8);
3385
3386 /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
3387 * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
3388 * 16 bits to interpolate to get the low bits of the result. Round the
3389 * answer. Note that the end point values are scaled by 64 to retain overall
John Bowler168a4332011-01-16 19:32:22 -06003390 * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003391 * the overall scaling by 6-12. Round at every step.
3392 */
3393 x -= 1U << 24;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003394
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003395 if (x <= 65536U) /* <= '257' */
John Bowler168a4332011-01-16 19:32:22 -06003396 lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003397
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003398 else
John Bowler168a4332011-01-16 19:32:22 -06003399 lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003400
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003401 /* Safe, because the result can't have more than 20 bits: */
John Bowler168a4332011-01-16 19:32:22 -06003402 return (png_int_32)((lg2 + 2048) >> 12);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003403}
3404
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003405/* The 'exp()' case must invert the above, taking a 20-bit fixed point
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003406 * logarithmic value and returning a 16 or 8-bit number as appropriate. In
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003407 * each case only the low 16 bits are relevant - the fraction - since the
3408 * integer bits (the top 4) simply determine a shift.
3409 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003410 * The worst case is the 16-bit distinction between 65535 and 65534, this
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003411 * requires perhaps spurious accuracty in the decoding of the logarithm to
3412 * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
3413 * of getting this accuracy in practice.
3414 *
3415 * To deal with this the following exp() function works out the exponent of the
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003416 * frational part of the logarithm by using an accurate 32-bit value from the
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003417 * top four fractional bits then multiplying in the remaining bits.
3418 */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003419static const png_uint_32
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003420png_32bit_exp[16] =
3421{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003422 /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003423 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
3424 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
3425 2553802834U, 2445529972U, 2341847524U, 2242560872U
3426};
3427
3428/* Adjustment table; provided to explain the numbers in the code below. */
Glenn Randers-Pehrson90a87c82011-12-05 12:05:43 -06003429#if 0
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003430for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
3431 11 44937.64284865548751208448
3432 10 45180.98734845585101160448
3433 9 45303.31936980687359311872
3434 8 45364.65110595323018870784
3435 7 45395.35850361789624614912
3436 6 45410.72259715102037508096
3437 5 45418.40724413220722311168
3438 4 45422.25021786898173001728
3439 3 45424.17186732298419044352
3440 2 45425.13273269940811464704
3441 1 45425.61317555035558641664
3442 0 45425.85339951654943850496
3443#endif
3444
John Bowler8d261262011-06-18 13:37:11 -05003445PNG_STATIC png_uint_32
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003446png_exp(png_fixed_point x)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003447{
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003448 if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003449 {
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003450 /* Obtain a 4-bit approximation */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003451 png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
3452
3453 /* Incorporate the low 12 bits - these decrease the returned value by
3454 * multiplying by a number less than 1 if the bit is set. The multiplier
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003455 * is determined by the above table and the shift. Notice that the values
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003456 * converge on 45426 and this is used to allow linear interpolation of the
3457 * low bits.
3458 */
Glenn Randers-Pehrson233357e2010-07-29 21:49:38 -05003459 if (x & 0x800)
3460 e -= (((e >> 16) * 44938U) + 16U) >> 5;
3461
3462 if (x & 0x400)
3463 e -= (((e >> 16) * 45181U) + 32U) >> 6;
3464
3465 if (x & 0x200)
3466 e -= (((e >> 16) * 45303U) + 64U) >> 7;
3467
3468 if (x & 0x100)
3469 e -= (((e >> 16) * 45365U) + 128U) >> 8;
3470
3471 if (x & 0x080)
3472 e -= (((e >> 16) * 45395U) + 256U) >> 9;
3473
3474 if (x & 0x040)
3475 e -= (((e >> 16) * 45410U) + 512U) >> 10;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003476
3477 /* And handle the low 6 bits in a single block. */
3478 e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
3479
3480 /* Handle the upper bits of x. */
3481 e >>= x >> 16;
3482 return e;
3483 }
3484
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003485 /* Check for overflow */
3486 if (x <= 0)
3487 return png_32bit_exp[0];
3488
3489 /* Else underflow */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003490 return 0;
3491}
3492
John Bowler8d261262011-06-18 13:37:11 -05003493PNG_STATIC png_byte
John Bowler168a4332011-01-16 19:32:22 -06003494png_exp8bit(png_fixed_point lg2)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003495{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003496 /* Get a 32-bit value: */
John Bowler168a4332011-01-16 19:32:22 -06003497 png_uint_32 x = png_exp(lg2);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003498
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003499 /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003500 * second, rounding, step can't overflow because of the first, subtraction,
3501 * step.
3502 */
3503 x -= x >> 8;
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003504 return (png_byte)((x + 0x7fffffU) >> 24);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003505}
3506
John Bowler8d261262011-06-18 13:37:11 -05003507PNG_STATIC png_uint_16
John Bowler168a4332011-01-16 19:32:22 -06003508png_exp16bit(png_fixed_point lg2)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003509{
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003510 /* Get a 32-bit value: */
John Bowler168a4332011-01-16 19:32:22 -06003511 png_uint_32 x = png_exp(lg2);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003512
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003513 /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003514 x -= x >> 16;
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003515 return (png_uint_16)((x + 32767U) >> 16);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003516}
3517#endif /* FLOATING_ARITHMETIC */
3518
3519png_byte
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003520png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003521{
3522 if (value > 0 && value < 255)
3523 {
3524# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003525 double r = floor(255*pow(value/255.,gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003526 return (png_byte)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003527# else
John Bowler168a4332011-01-16 19:32:22 -06003528 png_int_32 lg2 = png_log8bit(value);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003529 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003530
John Bowler168a4332011-01-16 19:32:22 -06003531 if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003532 return png_exp8bit(res);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003533
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003534 /* Overflow. */
3535 value = 0;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003536# endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003537 }
3538
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003539 return (png_byte)value;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003540}
3541
3542png_uint_16
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003543png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003544{
3545 if (value > 0 && value < 65535)
3546 {
3547# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003548 double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003549 return (png_uint_16)r;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003550# else
John Bowler168a4332011-01-16 19:32:22 -06003551 png_int_32 lg2 = png_log16bit(value);
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003552 png_fixed_point res;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003553
John Bowler168a4332011-01-16 19:32:22 -06003554 if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003555 return png_exp16bit(res);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003556
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003557 /* Overflow. */
3558 value = 0;
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003559# endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003560 }
3561
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003562 return (png_uint_16)value;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003563}
3564
3565/* This does the right thing based on the bit_depth field of the
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003566 * png_struct, interpreting values as 8-bit or 16-bit. While the result
3567 * is nominally a 16-bit value if bit depth is 8 then the result is
3568 * 8-bit (as are the arguments.)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003569 */
3570png_uint_16 /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06003571png_gamma_correct(png_structrp png_ptr, unsigned int value,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003572 png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003573{
3574 if (png_ptr->bit_depth == 8)
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003575 return png_gamma_8bit_correct(value, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003576
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003577 else
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003578 return png_gamma_16bit_correct(value, gamma_val);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003579}
3580
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003581/* Internal function to build a single 16-bit table - the table consists of
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003582 * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
3583 * to shift the input values right (or 16-number_of_signifiant_bits).
3584 *
Glenn Randers-Pehrsona774c5d2010-08-26 19:37:55 -05003585 * The caller is responsible for ensuring that the table gets cleaned up on
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003586 * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
3587 * should be somewhere that will be cleaned.
3588 */
3589static void
John Bowler5d567862011-12-24 09:12:00 -06003590png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003591 PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003592{
3593 /* Various values derived from 'shift': */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003594 PNG_CONST unsigned int num = 1U << (8U - shift);
3595 PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
3596 PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
3597 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003598
3599 png_uint_16pp table = *ptable =
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05003600 (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003601
3602 for (i = 0; i < num; i++)
3603 {
3604 png_uint_16p sub_table = table[i] =
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05003605 (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003606
3607 /* The 'threshold' test is repeated here because it can arise for one of
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003608 * the 16-bit tables even if the others don't hit it.
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003609 */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003610 if (png_gamma_significant(gamma_val))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003611 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003612 /* The old code would overflow at the end and this would cause the
3613 * 'pow' function to return a result >1, resulting in an
3614 * arithmetic error. This code follows the spec exactly; ig is
3615 * the recovered input sample, it always has 8-16 bits.
3616 *
3617 * We want input * 65535/max, rounded, the arithmetic fits in 32
3618 * bits (unsigned) so long as max <= 32767.
3619 */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003620 unsigned int j;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003621 for (j = 0; j < 256; j++)
3622 {
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003623 png_uint_32 ig = (j << (8-shift)) + i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003624# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003625 /* Inline the 'max' scaling operation: */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003626 double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5);
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003627 sub_table[j] = (png_uint_16)d;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003628# else
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003629 if (shift)
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -05003630 ig = (ig * 65535U + max_by_2)/max;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003631
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003632 sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003633# endif
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003634 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003635 }
3636 else
3637 {
3638 /* We must still build a table, but do it the fast way. */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003639 unsigned int j;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003640
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003641 for (j = 0; j < 256; j++)
3642 {
3643 png_uint_32 ig = (j << (8-shift)) + i;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003644
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003645 if (shift)
3646 ig = (ig * 65535U + max_by_2)/max;
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003647
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003648 sub_table[j] = (png_uint_16)ig;
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003649 }
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003650 }
3651 }
3652}
3653
3654/* NOTE: this function expects the *inverse* of the overall gamma transformation
3655 * required.
3656 */
3657static void
John Bowler5d567862011-12-24 09:12:00 -06003658png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003659 PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003660{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003661 PNG_CONST unsigned int num = 1U << (8U - shift);
3662 PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
3663 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003664 png_uint_32 last;
3665
3666 png_uint_16pp table = *ptable =
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05003667 (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003668
3669 /* 'num' is the number of tables and also the number of low bits of low
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003670 * bits of the input 16-bit value used to select a table. Each table is
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003671 * itself index by the high 8 bits of the value.
3672 */
3673 for (i = 0; i < num; i++)
3674 table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05003675 256 * (sizeof (png_uint_16)));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003676
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003677 /* 'gamma_val' is set to the reciprocal of the value calculated above, so
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003678 * pow(out,g) is an *input* value. 'last' is the last input value set.
3679 *
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003680 * In the loop 'i' is used to find output values. Since the output is
3681 * 8-bit there are only 256 possible values. The tables are set up to
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003682 * select the closest possible output value for each input by finding
3683 * the input value at the boundary between each pair of output values
3684 * and filling the table up to that boundary with the lower output
3685 * value.
3686 *
Glenn Randers-Pehrson8a7ec522011-05-17 07:14:30 -05003687 * 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 -05003688 * values the code below uses a 16-bit value in i; the values start at
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003689 * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
3690 * entries are filled with 255). Start i at 128 and fill all 'last'
3691 * table entries <= 'max'
3692 */
3693 last = 0;
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003694 for (i = 0; i < 255; ++i) /* 8-bit output value */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003695 {
3696 /* Find the corresponding maximum input value */
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003697 png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003698
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003699 /* Find the boundary value in 16 bits: */
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003700 png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003701
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003702 /* Adjust (round) to (16-shift) bits: */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003703 bound = (bound * max + 32768U)/65535U + 1U;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003704
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003705 while (last < bound)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003706 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003707 table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
3708 last++;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003709 }
3710 }
3711
3712 /* And fill in the final entries. */
3713 while (last < (num << 8))
3714 {
3715 table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
3716 last++;
3717 }
3718}
3719
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003720/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003721 * typically much faster). Note that libpng currently does no sBIT processing
3722 * (apparently contrary to the spec) so a 256 entry table is always generated.
3723 */
3724static void
John Bowler5d567862011-12-24 09:12:00 -06003725png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003726 PNG_CONST png_fixed_point gamma_val)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003727{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05003728 unsigned int i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003729 png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
3730
Glenn Randers-Pehrson2368a922011-01-16 13:32:05 -06003731 if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++)
3732 table[i] = png_gamma_8bit_correct(i, gamma_val);
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003733
Glenn Randers-Pehrson4009a762010-07-31 06:34:36 -05003734 else for (i=0; i<256; ++i)
3735 table[i] = (png_byte)i;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003736}
3737
John Bowler07772cb2011-10-14 18:19:47 -05003738/* Used from png_read_destroy and below to release the memory used by the gamma
3739 * tables.
3740 */
3741void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06003742png_destroy_gamma_table(png_structrp png_ptr)
John Bowler07772cb2011-10-14 18:19:47 -05003743{
3744 png_free(png_ptr, png_ptr->gamma_table);
3745 png_ptr->gamma_table = NULL;
3746
3747 if (png_ptr->gamma_16_table != NULL)
3748 {
3749 int i;
3750 int istop = (1 << (8 - png_ptr->gamma_shift));
3751 for (i = 0; i < istop; i++)
3752 {
3753 png_free(png_ptr, png_ptr->gamma_16_table[i]);
3754 }
3755 png_free(png_ptr, png_ptr->gamma_16_table);
3756 png_ptr->gamma_16_table = NULL;
3757 }
3758
3759#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3760 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
3761 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3762 png_free(png_ptr, png_ptr->gamma_from_1);
3763 png_ptr->gamma_from_1 = NULL;
3764 png_free(png_ptr, png_ptr->gamma_to_1);
3765 png_ptr->gamma_to_1 = NULL;
3766
3767 if (png_ptr->gamma_16_from_1 != NULL)
3768 {
3769 int i;
3770 int istop = (1 << (8 - png_ptr->gamma_shift));
3771 for (i = 0; i < istop; i++)
3772 {
3773 png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
3774 }
3775 png_free(png_ptr, png_ptr->gamma_16_from_1);
3776 png_ptr->gamma_16_from_1 = NULL;
3777 }
3778 if (png_ptr->gamma_16_to_1 != NULL)
3779 {
3780 int i;
3781 int istop = (1 << (8 - png_ptr->gamma_shift));
3782 for (i = 0; i < istop; i++)
3783 {
3784 png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
3785 }
3786 png_free(png_ptr, png_ptr->gamma_16_to_1);
3787 png_ptr->gamma_16_to_1 = NULL;
3788 }
3789#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
3790}
3791
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003792/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
3793 * tables, we don't make a full table if we are reducing to 8-bit in
3794 * the future. Note also how the gamma_16 tables are segmented so that
3795 * we don't need to allocate > 64K chunks for a full 16-bit table.
3796 */
3797void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06003798png_build_gamma_table(png_structrp png_ptr, int bit_depth)
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003799{
3800 png_debug(1, "in png_build_gamma_table");
3801
John Bowler07772cb2011-10-14 18:19:47 -05003802 /* Remove any existing table; this copes with multiple calls to
3803 * png_read_update_info. The warning is because building the gamma tables
3804 * multiple times is a performance hit - it's harmless but the ability to call
3805 * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible
3806 * to warn if the app introduces such a hit.
3807 */
3808 if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
3809 {
3810 png_warning(png_ptr, "gamma table being rebuilt");
3811 png_destroy_gamma_table(png_ptr);
3812 }
3813
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003814 if (bit_depth <= 8)
3815 {
3816 png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
John Bowlerb11b31a2012-03-21 07:55:46 -05003817 png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003818 png_ptr->screen_gamma) : PNG_FP_1);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003819
3820#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
John Bowlerd273ad22011-05-07 21:00:28 -05003821 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003822 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
John Bowlerd273ad22011-05-07 21:00:28 -05003823 if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003824 {
3825 png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
John Bowlerb11b31a2012-03-21 07:55:46 -05003826 png_reciprocal(png_ptr->colorspace.gamma));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003827
3828 png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003829 png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
John Bowlerb11b31a2012-03-21 07:55:46 -05003830 png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003831 }
John Bowlerd273ad22011-05-07 21:00:28 -05003832#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003833 }
3834 else
3835 {
3836 png_byte shift, sig_bit;
3837
3838 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3839 {
3840 sig_bit = png_ptr->sig_bit.red;
3841
3842 if (png_ptr->sig_bit.green > sig_bit)
3843 sig_bit = png_ptr->sig_bit.green;
3844
3845 if (png_ptr->sig_bit.blue > sig_bit)
3846 sig_bit = png_ptr->sig_bit.blue;
3847 }
3848 else
3849 sig_bit = png_ptr->sig_bit.gray;
3850
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003851 /* 16-bit gamma code uses this equation:
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003852 *
3853 * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
3854 *
3855 * Where 'iv' is the input color value and 'ov' is the output value -
3856 * pow(iv, gamma).
3857 *
3858 * Thus the gamma table consists of up to 256 256 entry tables. The table
3859 * is selected by the (8-gamma_shift) most significant of the low 8 bits of
3860 * the color value then indexed by the upper 8 bits:
3861 *
3862 * table[low bits][high 8 bits]
3863 *
3864 * So the table 'n' corresponds to all those 'iv' of:
3865 *
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003866 * <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003867 *
3868 */
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05003869 if (sig_bit > 0 && sig_bit < 16U)
3870 shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003871
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003872 else
3873 shift = 0; /* keep all 16 bits */
3874
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05003875 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003876 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003877 /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
3878 * the significant bits in the *input* when the output will
3879 * eventually be 8 bits. By default it is 11.
3880 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003881 if (shift < (16U - PNG_MAX_GAMMA_8))
3882 shift = (16U - PNG_MAX_GAMMA_8);
3883 }
3884
3885 if (shift > 8U)
3886 shift = 8U; /* Guarantees at least one table! */
3887
3888 png_ptr->gamma_shift = shift;
3889
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003890#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrsonef217b72011-06-15 12:58:27 -05003891 /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
John Bowlerd273ad22011-05-07 21:00:28 -05003892 * PNG_COMPOSE). This effectively smashed the background calculation for
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05003893 * 16-bit output because the 8-bit table assumes the result will be reduced
John Bowlerd273ad22011-05-07 21:00:28 -05003894 * to 8 bits.
3895 */
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05003896 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003897#endif
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003898 png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
John Bowlerb11b31a2012-03-21 07:55:46 -05003899 png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003900 png_ptr->screen_gamma) : PNG_FP_1);
3901
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003902#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003903 else
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003904 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
John Bowlerb11b31a2012-03-21 07:55:46 -05003905 png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003906 png_ptr->screen_gamma) : PNG_FP_1);
Glenn Randers-Pehrson4e487612010-08-26 21:41:04 -05003907#endif
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003908
3909#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
John Bowlerd273ad22011-05-07 21:00:28 -05003910 defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003911 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
John Bowlerd273ad22011-05-07 21:00:28 -05003912 if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003913 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003914 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
John Bowlerb11b31a2012-03-21 07:55:46 -05003915 png_reciprocal(png_ptr->colorspace.gamma));
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003916
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003917 /* Notice that the '16 from 1' table should be full precision, however
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003918 * the lookup on this table still uses gamma_shift, so it can't be.
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05003919 * TODO: fix this.
3920 */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003921 png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
Glenn Randers-Pehrson7b81e2e2010-07-29 22:54:34 -05003922 png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
John Bowlerb11b31a2012-03-21 07:55:46 -05003923 png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003924 }
John Bowlerd273ad22011-05-07 21:00:28 -05003925#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -05003926 }
3927}
3928#endif /* READ_GAMMA */
John Bowler7875d532011-11-07 22:33:49 -06003929
3930/* sRGB support */
3931#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
3932 defined PNG_SIMPLIFIED_WRITE_SUPPORTED
John Bowler0a521d32011-11-11 18:14:59 -06003933/* sRGB conversion tables; these are machine generated with the code in
Glenn Randers-Pehrson5578c372012-02-04 10:31:38 -06003934 * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
3935 * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
3936 * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
3937 * The sRGB to linear table is exact (to the nearest 16 bit linear fraction).
3938 * The inverse (linear to sRGB) table has accuracies as follows:
John Bowler0a521d32011-11-11 18:14:59 -06003939 *
3940 * For all possible (255*65535+1) input values:
3941 *
3942 * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
3943 *
3944 * For the input values corresponding to the 65536 16-bit values:
3945 *
3946 * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
3947 *
3948 * In all cases the inexact readings are off by one.
John Bowler7875d532011-11-07 22:33:49 -06003949 */
John Bowler7875d532011-11-07 22:33:49 -06003950
3951#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
3952/* The convert-to-sRGB table is only currently required for read. */
John Bowler572b0782012-01-31 07:09:34 -06003953const png_uint_16 png_sRGB_table[256] =
John Bowler7875d532011-11-07 22:33:49 -06003954{
3955 0,20,40,60,80,99,119,139,
3956 159,179,199,219,241,264,288,313,
3957 340,367,396,427,458,491,526,562,
3958 599,637,677,718,761,805,851,898,
3959 947,997,1048,1101,1156,1212,1270,1330,
3960 1391,1453,1517,1583,1651,1720,1790,1863,
3961 1937,2013,2090,2170,2250,2333,2418,2504,
3962 2592,2681,2773,2866,2961,3058,3157,3258,
3963 3360,3464,3570,3678,3788,3900,4014,4129,
3964 4247,4366,4488,4611,4736,4864,4993,5124,
3965 5257,5392,5530,5669,5810,5953,6099,6246,
3966 6395,6547,6700,6856,7014,7174,7335,7500,
3967 7666,7834,8004,8177,8352,8528,8708,8889,
3968 9072,9258,9445,9635,9828,10022,10219,10417,
3969 10619,10822,11028,11235,11446,11658,11873,12090,
3970 12309,12530,12754,12980,13209,13440,13673,13909,
3971 14146,14387,14629,14874,15122,15371,15623,15878,
3972 16135,16394,16656,16920,17187,17456,17727,18001,
3973 18277,18556,18837,19121,19407,19696,19987,20281,
3974 20577,20876,21177,21481,21787,22096,22407,22721,
3975 23038,23357,23678,24002,24329,24658,24990,25325,
3976 25662,26001,26344,26688,27036,27386,27739,28094,
3977 28452,28813,29176,29542,29911,30282,30656,31033,
3978 31412,31794,32179,32567,32957,33350,33745,34143,
3979 34544,34948,35355,35764,36176,36591,37008,37429,
3980 37852,38278,38706,39138,39572,40009,40449,40891,
3981 41337,41785,42236,42690,43147,43606,44069,44534,
3982 45002,45473,45947,46423,46903,47385,47871,48359,
3983 48850,49344,49841,50341,50844,51349,51858,52369,
3984 52884,53401,53921,54445,54971,55500,56032,56567,
3985 57105,57646,58190,58737,59287,59840,60396,60955,
3986 61517,62082,62650,63221,63795,64372,64952,65535
3987};
John Bowler0a521d32011-11-11 18:14:59 -06003988
John Bowler7875d532011-11-07 22:33:49 -06003989#endif /* simplified read only */
3990
3991/* The base/delta tables are required for both read and write (but currently
3992 * only the simplified versions.)
3993 */
John Bowler572b0782012-01-31 07:09:34 -06003994const png_uint_16 png_sRGB_base[512] =
John Bowler7875d532011-11-07 22:33:49 -06003995{
John Bowler0a521d32011-11-11 18:14:59 -06003996 128,1782,3383,4644,5675,6564,7357,8074,
3997 8732,9346,9921,10463,10977,11466,11935,12384,
3998 12816,13233,13634,14024,14402,14769,15125,15473,
3999 15812,16142,16466,16781,17090,17393,17690,17981,
John Bowler7875d532011-11-07 22:33:49 -06004000 18266,18546,18822,19093,19359,19621,19879,20133,
John Bowler0a521d32011-11-11 18:14:59 -06004001 20383,20630,20873,21113,21349,21583,21813,22041,
4002 22265,22487,22707,22923,23138,23350,23559,23767,
John Bowler7875d532011-11-07 22:33:49 -06004003 23972,24175,24376,24575,24772,24967,25160,25352,
John Bowler0a521d32011-11-11 18:14:59 -06004004 25542,25730,25916,26101,26284,26465,26645,26823,
4005 27000,27176,27350,27523,27695,27865,28034,28201,
John Bowler7875d532011-11-07 22:33:49 -06004006 28368,28533,28697,28860,29021,29182,29341,29500,
John Bowler0a521d32011-11-11 18:14:59 -06004007 29657,29813,29969,30123,30276,30429,30580,30730,
John Bowler7875d532011-11-07 22:33:49 -06004008 30880,31028,31176,31323,31469,31614,31758,31902,
John Bowler0a521d32011-11-11 18:14:59 -06004009 32045,32186,32327,32468,32607,32746,32884,33021,
4010 33158,33294,33429,33564,33697,33831,33963,34095,
4011 34226,34357,34486,34616,34744,34873,35000,35127,
John Bowler7875d532011-11-07 22:33:49 -06004012 35253,35379,35504,35629,35753,35876,35999,36122,
4013 36244,36365,36486,36606,36726,36845,36964,37083,
John Bowler0a521d32011-11-11 18:14:59 -06004014 37201,37318,37435,37551,37668,37783,37898,38013,
John Bowler7875d532011-11-07 22:33:49 -06004015 38127,38241,38354,38467,38580,38692,38803,38915,
John Bowler0a521d32011-11-11 18:14:59 -06004016 39026,39136,39246,39356,39465,39574,39682,39790,
John Bowler7875d532011-11-07 22:33:49 -06004017 39898,40005,40112,40219,40325,40431,40537,40642,
4018 40747,40851,40955,41059,41163,41266,41369,41471,
John Bowler0a521d32011-11-11 18:14:59 -06004019 41573,41675,41777,41878,41979,42079,42179,42279,
4020 42379,42478,42577,42676,42775,42873,42971,43068,
4021 43165,43262,43359,43456,43552,43648,43743,43839,
4022 43934,44028,44123,44217,44311,44405,44499,44592,
4023 44685,44778,44870,44962,45054,45146,45238,45329,
John Bowler7875d532011-11-07 22:33:49 -06004024 45420,45511,45601,45692,45782,45872,45961,46051,
John Bowler0a521d32011-11-11 18:14:59 -06004025 46140,46229,46318,46406,46494,46583,46670,46758,
4026 46846,46933,47020,47107,47193,47280,47366,47452,
4027 47538,47623,47709,47794,47879,47964,48048,48133,
4028 48217,48301,48385,48468,48552,48635,48718,48801,
4029 48884,48966,49048,49131,49213,49294,49376,49458,
4030 49539,49620,49701,49782,49862,49943,50023,50103,
4031 50183,50263,50342,50422,50501,50580,50659,50738,
4032 50816,50895,50973,51051,51129,51207,51285,51362,
4033 51439,51517,51594,51671,51747,51824,51900,51977,
4034 52053,52129,52205,52280,52356,52432,52507,52582,
John Bowler7875d532011-11-07 22:33:49 -06004035 52657,52732,52807,52881,52956,53030,53104,53178,
John Bowler0a521d32011-11-11 18:14:59 -06004036 53252,53326,53400,53473,53546,53620,53693,53766,
John Bowler7875d532011-11-07 22:33:49 -06004037 53839,53911,53984,54056,54129,54201,54273,54345,
4038 54417,54489,54560,54632,54703,54774,54845,54916,
John Bowler0a521d32011-11-11 18:14:59 -06004039 54987,55058,55129,55199,55269,55340,55410,55480,
4040 55550,55620,55689,55759,55828,55898,55967,56036,
4041 56105,56174,56243,56311,56380,56448,56517,56585,
John Bowler7875d532011-11-07 22:33:49 -06004042 56653,56721,56789,56857,56924,56992,57059,57127,
4043 57194,57261,57328,57395,57462,57529,57595,57662,
4044 57728,57795,57861,57927,57993,58059,58125,58191,
4045 58256,58322,58387,58453,58518,58583,58648,58713,
4046 58778,58843,58908,58972,59037,59101,59165,59230,
4047 59294,59358,59422,59486,59549,59613,59677,59740,
4048 59804,59867,59930,59993,60056,60119,60182,60245,
4049 60308,60370,60433,60495,60558,60620,60682,60744,
4050 60806,60868,60930,60992,61054,61115,61177,61238,
4051 61300,61361,61422,61483,61544,61605,61666,61727,
John Bowler0a521d32011-11-11 18:14:59 -06004052 61788,61848,61909,61969,62030,62090,62150,62211,
John Bowler7875d532011-11-07 22:33:49 -06004053 62271,62331,62391,62450,62510,62570,62630,62689,
4054 62749,62808,62867,62927,62986,63045,63104,63163,
John Bowler0a521d32011-11-11 18:14:59 -06004055 63222,63281,63340,63398,63457,63515,63574,63632,
John Bowler7875d532011-11-07 22:33:49 -06004056 63691,63749,63807,63865,63923,63981,64039,64097,
John Bowler0a521d32011-11-11 18:14:59 -06004057 64155,64212,64270,64328,64385,64443,64500,64557,
4058 64614,64672,64729,64786,64843,64900,64956,65013,
4059 65070,65126,65183,65239,65296,65352,65409,65465
John Bowler7875d532011-11-07 22:33:49 -06004060};
4061
John Bowler572b0782012-01-31 07:09:34 -06004062const png_byte png_sRGB_delta[512] =
John Bowler7875d532011-11-07 22:33:49 -06004063{
John Bowler0a521d32011-11-11 18:14:59 -06004064 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
John Bowler7875d532011-11-07 22:33:49 -06004065 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
4066 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
John Bowler0a521d32011-11-11 18:14:59 -06004067 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
John Bowler7875d532011-11-07 22:33:49 -06004068 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
4069 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
4070 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
4071 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
4072 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
4073 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
4074 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
4075 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
4076 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
4077 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
4078 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
4079 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
4080 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
4081 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
4082 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
4083 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4084 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4085 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4086 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
4087 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4088 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4089 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4090 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4091 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4092 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
4093 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
4094 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
4095 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
4096};
John Bowler7875d532011-11-07 22:33:49 -06004097#endif /* SIMPLIFIED READ/WRITE sRGB support */
4098
4099/* SIMPLIFIED READ/WRITE SUPPORT */
4100#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
4101 defined PNG_SIMPLIFIED_WRITE_SUPPORTED
4102static int
4103png_image_free_function(png_voidp argument)
4104{
John Bowler4fa96a42011-11-16 16:39:16 -06004105 png_imagep image = png_voidcast(png_imagep, argument);
John Bowler7875d532011-11-07 22:33:49 -06004106 png_controlp cp = image->opaque;
4107 png_control c;
4108
4109 /* Double check that we have a png_ptr - it should be impossible to get here
4110 * without one.
4111 */
4112 if (cp->png_ptr == NULL)
4113 return 0;
4114
4115 /* First free any data held in the control structure. */
4116# ifdef PNG_STDIO_SUPPORTED
4117 if (cp->owned_file)
4118 {
John Bowler4fa96a42011-11-16 16:39:16 -06004119 FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
John Bowler7875d532011-11-07 22:33:49 -06004120 cp->owned_file = 0;
4121
4122 /* Ignore errors here. */
4123 if (fp != NULL)
4124 {
4125 cp->png_ptr->io_ptr = NULL;
4126 (void)fclose(fp);
4127 }
4128 }
4129# endif
4130
4131 /* Copy the control structure so that the original, allocated, version can be
4132 * safely freed. Notice that a png_error here stops the remainder of the
4133 * cleanup, but this is probably fine because that would indicate bad memory
4134 * problems anyway.
4135 */
4136 c = *cp;
4137 image->opaque = &c;
4138 png_free(c.png_ptr, cp);
4139
4140 /* Then the structures, calling the correct API. */
4141 if (c.for_write)
4142 {
4143# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
4144 png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
4145# else
4146 png_error(c.png_ptr, "simplified write not supported");
4147# endif
4148 }
4149 else
4150 {
4151# ifdef PNG_SIMPLIFIED_READ_SUPPORTED
4152 png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
4153# else
4154 png_error(c.png_ptr, "simplified read not supported");
4155# endif
4156 }
4157
4158 /* Success. */
4159 return 1;
4160}
4161
4162void PNGAPI
4163png_image_free(png_imagep image)
4164{
4165 /* Safely call the real function, but only if doing so is safe at this point
4166 * (if not inside an error handling context). Otherwise assume
4167 * png_safe_execute will call this API after the return.
4168 */
4169 if (image != NULL && image->opaque != NULL &&
4170 image->opaque->error_buf == NULL)
4171 {
4172 /* Ignore errors here: */
4173 (void)png_safe_execute(image, png_image_free_function, image);
4174 image->opaque = NULL;
4175 }
4176}
4177
4178int /* PRIVATE */
4179png_image_error(png_imagep image, png_const_charp error_message)
4180{
4181 /* Utility to log an error. */
Glenn Randers-Pehrson432c1742012-08-09 20:14:48 -05004182 png_safecat(image->message, (sizeof image->message), 0, error_message);
John Bowler04336ba2012-01-16 07:48:36 -06004183 image->warning_or_error |= PNG_IMAGE_ERROR;
John Bowler7875d532011-11-07 22:33:49 -06004184 png_image_free(image);
4185 return 0;
4186}
4187
4188#endif /* SIMPLIFIED READ/WRITE */
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05004189#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */