17dd7cddfSDavid du Colombier /* pngrutil.c - utilities to read a PNG file
27dd7cddfSDavid du Colombier *
3*593dc095SDavid du Colombier * libpng version 1.2.8 - December 3, 2004
47dd7cddfSDavid du Colombier * For conditions of distribution and use, see copyright notice in png.h
5*593dc095SDavid du Colombier * Copyright (c) 1998-2004 Glenn Randers-Pehrson
6*593dc095SDavid du Colombier * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7*593dc095SDavid du Colombier * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
87dd7cddfSDavid du Colombier *
9*593dc095SDavid du Colombier * This file contains routines that are only called from within
107dd7cddfSDavid du Colombier * libpng itself during the course of reading an image.
117dd7cddfSDavid du Colombier */
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier #define PNG_INTERNAL
147dd7cddfSDavid du Colombier #include "png.h"
157dd7cddfSDavid du Colombier
16*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
17*593dc095SDavid du Colombier /* strtod() function is not supported on WindowsCE */
18*593dc095SDavid du Colombier # ifdef PNG_FLOATING_POINT_SUPPORTED
strtod(const char * nptr,char ** endptr)19*593dc095SDavid du Colombier __inline double strtod(const char *nptr, char **endptr)
20*593dc095SDavid du Colombier {
21*593dc095SDavid du Colombier double result = 0;
22*593dc095SDavid du Colombier int len;
23*593dc095SDavid du Colombier wchar_t *str, *end;
24*593dc095SDavid du Colombier
25*593dc095SDavid du Colombier len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
26*593dc095SDavid du Colombier str = (wchar_t *)malloc(len * sizeof(wchar_t));
27*593dc095SDavid du Colombier if ( NULL != str )
28*593dc095SDavid du Colombier {
29*593dc095SDavid du Colombier MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
30*593dc095SDavid du Colombier result = wcstod(str, &end);
31*593dc095SDavid du Colombier len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
32*593dc095SDavid du Colombier *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
33*593dc095SDavid du Colombier free(str);
34*593dc095SDavid du Colombier }
35*593dc095SDavid du Colombier return result;
36*593dc095SDavid du Colombier }
37*593dc095SDavid du Colombier # endif
38*593dc095SDavid du Colombier #endif
39*593dc095SDavid du Colombier
40*593dc095SDavid du Colombier png_uint_32 /* PRIVATE */
png_get_uint_31(png_structp png_ptr,png_bytep buf)41*593dc095SDavid du Colombier png_get_uint_31(png_structp png_ptr, png_bytep buf)
42*593dc095SDavid du Colombier {
43*593dc095SDavid du Colombier png_uint_32 i = png_get_uint_32(buf);
44*593dc095SDavid du Colombier if (i > PNG_UINT_31_MAX)
45*593dc095SDavid du Colombier png_error(png_ptr, "PNG unsigned integer out of range.\n");
46*593dc095SDavid du Colombier return (i);
47*593dc095SDavid du Colombier }
487dd7cddfSDavid du Colombier #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
49*593dc095SDavid du Colombier /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
50*593dc095SDavid du Colombier png_uint_32 /* PRIVATE */
png_get_uint_32(png_bytep buf)517dd7cddfSDavid du Colombier png_get_uint_32(png_bytep buf)
527dd7cddfSDavid du Colombier {
53*593dc095SDavid du Colombier png_uint_32 i = ((png_uint_32)(*buf) << 24) +
547dd7cddfSDavid du Colombier ((png_uint_32)(*(buf + 1)) << 16) +
557dd7cddfSDavid du Colombier ((png_uint_32)(*(buf + 2)) << 8) +
567dd7cddfSDavid du Colombier (png_uint_32)(*(buf + 3));
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier return (i);
597dd7cddfSDavid du Colombier }
607dd7cddfSDavid du Colombier
61*593dc095SDavid du Colombier #if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
62*593dc095SDavid du Colombier /* Grab a signed 32-bit integer from a buffer in big-endian format. The
637dd7cddfSDavid du Colombier * data is stored in the PNG file in two's complement format, and it is
647dd7cddfSDavid du Colombier * assumed that the machine format for signed integers is the same. */
65*593dc095SDavid du Colombier png_int_32 /* PRIVATE */
png_get_int_32(png_bytep buf)667dd7cddfSDavid du Colombier png_get_int_32(png_bytep buf)
677dd7cddfSDavid du Colombier {
68*593dc095SDavid du Colombier png_int_32 i = ((png_int_32)(*buf) << 24) +
697dd7cddfSDavid du Colombier ((png_int_32)(*(buf + 1)) << 16) +
707dd7cddfSDavid du Colombier ((png_int_32)(*(buf + 2)) << 8) +
717dd7cddfSDavid du Colombier (png_int_32)(*(buf + 3));
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier return (i);
747dd7cddfSDavid du Colombier }
757dd7cddfSDavid du Colombier #endif /* PNG_READ_pCAL_SUPPORTED */
767dd7cddfSDavid du Colombier
77*593dc095SDavid du Colombier /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
78*593dc095SDavid du Colombier png_uint_16 /* PRIVATE */
png_get_uint_16(png_bytep buf)797dd7cddfSDavid du Colombier png_get_uint_16(png_bytep buf)
807dd7cddfSDavid du Colombier {
81*593dc095SDavid du Colombier png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
827dd7cddfSDavid du Colombier (png_uint_16)(*(buf + 1)));
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier return (i);
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier /* Read data, and (optionally) run it through the CRC. */
89*593dc095SDavid du Colombier void /* PRIVATE */
png_crc_read(png_structp png_ptr,png_bytep buf,png_size_t length)907dd7cddfSDavid du Colombier png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
917dd7cddfSDavid du Colombier {
927dd7cddfSDavid du Colombier png_read_data(png_ptr, buf, length);
937dd7cddfSDavid du Colombier png_calculate_crc(png_ptr, buf, length);
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier /* Optionally skip data and then check the CRC. Depending on whether we
977dd7cddfSDavid du Colombier are reading a ancillary or critical chunk, and how the program has set
987dd7cddfSDavid du Colombier things up, we may calculate the CRC on the data and print a message.
997dd7cddfSDavid du Colombier Returns '1' if there was a CRC error, '0' otherwise. */
100*593dc095SDavid du Colombier int /* PRIVATE */
png_crc_finish(png_structp png_ptr,png_uint_32 skip)1017dd7cddfSDavid du Colombier png_crc_finish(png_structp png_ptr, png_uint_32 skip)
1027dd7cddfSDavid du Colombier {
103*593dc095SDavid du Colombier png_size_t i;
104*593dc095SDavid du Colombier png_size_t istop = png_ptr->zbuf_size;
1057dd7cddfSDavid du Colombier
106*593dc095SDavid du Colombier for (i = (png_size_t)skip; i > istop; i -= istop)
1077dd7cddfSDavid du Colombier {
1087dd7cddfSDavid du Colombier png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier if (i)
1117dd7cddfSDavid du Colombier {
112*593dc095SDavid du Colombier png_crc_read(png_ptr, png_ptr->zbuf, i);
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier if (png_crc_error(png_ptr))
1167dd7cddfSDavid du Colombier {
117*593dc095SDavid du Colombier if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
1187dd7cddfSDavid du Colombier !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
1197dd7cddfSDavid du Colombier (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
120*593dc095SDavid du Colombier (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
1217dd7cddfSDavid du Colombier {
1227dd7cddfSDavid du Colombier png_chunk_warning(png_ptr, "CRC error");
1237dd7cddfSDavid du Colombier }
1247dd7cddfSDavid du Colombier else
1257dd7cddfSDavid du Colombier {
1267dd7cddfSDavid du Colombier png_chunk_error(png_ptr, "CRC error");
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier return (1);
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier return (0);
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier /* Compare the CRC stored in the PNG file with that calculated by libpng from
1357dd7cddfSDavid du Colombier the data it has read thus far. */
136*593dc095SDavid du Colombier int /* PRIVATE */
png_crc_error(png_structp png_ptr)1377dd7cddfSDavid du Colombier png_crc_error(png_structp png_ptr)
1387dd7cddfSDavid du Colombier {
1397dd7cddfSDavid du Colombier png_byte crc_bytes[4];
1407dd7cddfSDavid du Colombier png_uint_32 crc;
1417dd7cddfSDavid du Colombier int need_crc = 1;
1427dd7cddfSDavid du Colombier
1437dd7cddfSDavid du Colombier if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
1447dd7cddfSDavid du Colombier {
1457dd7cddfSDavid du Colombier if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
1467dd7cddfSDavid du Colombier (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
1477dd7cddfSDavid du Colombier need_crc = 0;
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier else /* critical */
1507dd7cddfSDavid du Colombier {
1517dd7cddfSDavid du Colombier if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
1527dd7cddfSDavid du Colombier need_crc = 0;
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier png_read_data(png_ptr, crc_bytes, 4);
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier if (need_crc)
1587dd7cddfSDavid du Colombier {
1597dd7cddfSDavid du Colombier crc = png_get_uint_32(crc_bytes);
1607dd7cddfSDavid du Colombier return ((int)(crc != png_ptr->crc));
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier else
1637dd7cddfSDavid du Colombier return (0);
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier
166*593dc095SDavid du Colombier #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
167*593dc095SDavid du Colombier defined(PNG_READ_iCCP_SUPPORTED)
168*593dc095SDavid du Colombier /*
169*593dc095SDavid du Colombier * Decompress trailing data in a chunk. The assumption is that chunkdata
170*593dc095SDavid du Colombier * points at an allocated area holding the contents of a chunk with a
171*593dc095SDavid du Colombier * trailing compressed part. What we get back is an allocated area
172*593dc095SDavid du Colombier * holding the original prefix part and an uncompressed version of the
173*593dc095SDavid du Colombier * trailing part (the malloc area passed in is freed).
174*593dc095SDavid du Colombier */
175*593dc095SDavid du Colombier png_charp /* PRIVATE */
png_decompress_chunk(png_structp png_ptr,int comp_type,png_charp chunkdata,png_size_t chunklength,png_size_t prefix_size,png_size_t * newlength)176*593dc095SDavid du Colombier png_decompress_chunk(png_structp png_ptr, int comp_type,
177*593dc095SDavid du Colombier png_charp chunkdata, png_size_t chunklength,
178*593dc095SDavid du Colombier png_size_t prefix_size, png_size_t *newlength)
179*593dc095SDavid du Colombier {
180*593dc095SDavid du Colombier static char msg[] = "Error decoding compressed text";
181*593dc095SDavid du Colombier png_charp text;
182*593dc095SDavid du Colombier png_size_t text_size;
183*593dc095SDavid du Colombier
184*593dc095SDavid du Colombier if (comp_type == PNG_COMPRESSION_TYPE_BASE)
185*593dc095SDavid du Colombier {
186*593dc095SDavid du Colombier int ret = Z_OK;
187*593dc095SDavid du Colombier png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
188*593dc095SDavid du Colombier png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
189*593dc095SDavid du Colombier png_ptr->zstream.next_out = png_ptr->zbuf;
190*593dc095SDavid du Colombier png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
191*593dc095SDavid du Colombier
192*593dc095SDavid du Colombier text_size = 0;
193*593dc095SDavid du Colombier text = NULL;
194*593dc095SDavid du Colombier
195*593dc095SDavid du Colombier while (png_ptr->zstream.avail_in)
196*593dc095SDavid du Colombier {
197*593dc095SDavid du Colombier ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
198*593dc095SDavid du Colombier if (ret != Z_OK && ret != Z_STREAM_END)
199*593dc095SDavid du Colombier {
200*593dc095SDavid du Colombier if (png_ptr->zstream.msg != NULL)
201*593dc095SDavid du Colombier png_warning(png_ptr, png_ptr->zstream.msg);
202*593dc095SDavid du Colombier else
203*593dc095SDavid du Colombier png_warning(png_ptr, msg);
204*593dc095SDavid du Colombier inflateReset(&png_ptr->zstream);
205*593dc095SDavid du Colombier png_ptr->zstream.avail_in = 0;
206*593dc095SDavid du Colombier
207*593dc095SDavid du Colombier if (text == NULL)
208*593dc095SDavid du Colombier {
209*593dc095SDavid du Colombier text_size = prefix_size + png_sizeof(msg) + 1;
210*593dc095SDavid du Colombier text = (png_charp)png_malloc_warn(png_ptr, text_size);
211*593dc095SDavid du Colombier if (text == NULL)
212*593dc095SDavid du Colombier {
213*593dc095SDavid du Colombier png_free(png_ptr,chunkdata);
214*593dc095SDavid du Colombier png_error(png_ptr,"Not enough memory to decompress chunk");
215*593dc095SDavid du Colombier }
216*593dc095SDavid du Colombier png_memcpy(text, chunkdata, prefix_size);
217*593dc095SDavid du Colombier }
218*593dc095SDavid du Colombier
219*593dc095SDavid du Colombier text[text_size - 1] = 0x00;
220*593dc095SDavid du Colombier
221*593dc095SDavid du Colombier /* Copy what we can of the error message into the text chunk */
222*593dc095SDavid du Colombier text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
223*593dc095SDavid du Colombier text_size = png_sizeof(msg) > text_size ? text_size :
224*593dc095SDavid du Colombier png_sizeof(msg);
225*593dc095SDavid du Colombier png_memcpy(text + prefix_size, msg, text_size + 1);
226*593dc095SDavid du Colombier break;
227*593dc095SDavid du Colombier }
228*593dc095SDavid du Colombier if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
229*593dc095SDavid du Colombier {
230*593dc095SDavid du Colombier if (text == NULL)
231*593dc095SDavid du Colombier {
232*593dc095SDavid du Colombier text_size = prefix_size +
233*593dc095SDavid du Colombier png_ptr->zbuf_size - png_ptr->zstream.avail_out;
234*593dc095SDavid du Colombier text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
235*593dc095SDavid du Colombier if (text == NULL)
236*593dc095SDavid du Colombier {
237*593dc095SDavid du Colombier png_free(png_ptr,chunkdata);
238*593dc095SDavid du Colombier png_error(png_ptr,"Not enough memory to decompress chunk.");
239*593dc095SDavid du Colombier }
240*593dc095SDavid du Colombier png_memcpy(text + prefix_size, png_ptr->zbuf,
241*593dc095SDavid du Colombier text_size - prefix_size);
242*593dc095SDavid du Colombier png_memcpy(text, chunkdata, prefix_size);
243*593dc095SDavid du Colombier *(text + text_size) = 0x00;
244*593dc095SDavid du Colombier }
245*593dc095SDavid du Colombier else
246*593dc095SDavid du Colombier {
247*593dc095SDavid du Colombier png_charp tmp;
248*593dc095SDavid du Colombier
249*593dc095SDavid du Colombier tmp = text;
250*593dc095SDavid du Colombier text = (png_charp)png_malloc_warn(png_ptr,
251*593dc095SDavid du Colombier (png_uint_32)(text_size +
252*593dc095SDavid du Colombier png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
253*593dc095SDavid du Colombier if (text == NULL)
254*593dc095SDavid du Colombier {
255*593dc095SDavid du Colombier png_free(png_ptr, tmp);
256*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
257*593dc095SDavid du Colombier png_error(png_ptr,"Not enough memory to decompress chunk..");
258*593dc095SDavid du Colombier }
259*593dc095SDavid du Colombier png_memcpy(text, tmp, text_size);
260*593dc095SDavid du Colombier png_free(png_ptr, tmp);
261*593dc095SDavid du Colombier png_memcpy(text + text_size, png_ptr->zbuf,
262*593dc095SDavid du Colombier (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
263*593dc095SDavid du Colombier text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
264*593dc095SDavid du Colombier *(text + text_size) = 0x00;
265*593dc095SDavid du Colombier }
266*593dc095SDavid du Colombier if (ret == Z_STREAM_END)
267*593dc095SDavid du Colombier break;
268*593dc095SDavid du Colombier else
269*593dc095SDavid du Colombier {
270*593dc095SDavid du Colombier png_ptr->zstream.next_out = png_ptr->zbuf;
271*593dc095SDavid du Colombier png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
272*593dc095SDavid du Colombier }
273*593dc095SDavid du Colombier }
274*593dc095SDavid du Colombier }
275*593dc095SDavid du Colombier if (ret != Z_STREAM_END)
276*593dc095SDavid du Colombier {
277*593dc095SDavid du Colombier #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
278*593dc095SDavid du Colombier char umsg[50];
279*593dc095SDavid du Colombier
280*593dc095SDavid du Colombier if (ret == Z_BUF_ERROR)
281*593dc095SDavid du Colombier sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
282*593dc095SDavid du Colombier png_ptr->chunk_name);
283*593dc095SDavid du Colombier else if (ret == Z_DATA_ERROR)
284*593dc095SDavid du Colombier sprintf(umsg,"Data error in compressed datastream in %s chunk",
285*593dc095SDavid du Colombier png_ptr->chunk_name);
286*593dc095SDavid du Colombier else
287*593dc095SDavid du Colombier sprintf(umsg,"Incomplete compressed datastream in %s chunk",
288*593dc095SDavid du Colombier png_ptr->chunk_name);
289*593dc095SDavid du Colombier png_warning(png_ptr, umsg);
290*593dc095SDavid du Colombier #else
291*593dc095SDavid du Colombier png_warning(png_ptr,
292*593dc095SDavid du Colombier "Incomplete compressed datastream in chunk other than IDAT");
293*593dc095SDavid du Colombier #endif
294*593dc095SDavid du Colombier text_size=prefix_size;
295*593dc095SDavid du Colombier if (text == NULL)
296*593dc095SDavid du Colombier {
297*593dc095SDavid du Colombier text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
298*593dc095SDavid du Colombier if (text == NULL)
299*593dc095SDavid du Colombier {
300*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
301*593dc095SDavid du Colombier png_error(png_ptr,"Not enough memory for text.");
302*593dc095SDavid du Colombier }
303*593dc095SDavid du Colombier png_memcpy(text, chunkdata, prefix_size);
304*593dc095SDavid du Colombier }
305*593dc095SDavid du Colombier *(text + text_size) = 0x00;
306*593dc095SDavid du Colombier }
307*593dc095SDavid du Colombier
308*593dc095SDavid du Colombier inflateReset(&png_ptr->zstream);
309*593dc095SDavid du Colombier png_ptr->zstream.avail_in = 0;
310*593dc095SDavid du Colombier
311*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
312*593dc095SDavid du Colombier chunkdata = text;
313*593dc095SDavid du Colombier *newlength=text_size;
314*593dc095SDavid du Colombier }
315*593dc095SDavid du Colombier else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
316*593dc095SDavid du Colombier {
317*593dc095SDavid du Colombier #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
318*593dc095SDavid du Colombier char umsg[50];
319*593dc095SDavid du Colombier
320*593dc095SDavid du Colombier sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
321*593dc095SDavid du Colombier png_warning(png_ptr, umsg);
322*593dc095SDavid du Colombier #else
323*593dc095SDavid du Colombier png_warning(png_ptr, "Unknown zTXt compression type");
324*593dc095SDavid du Colombier #endif
325*593dc095SDavid du Colombier
326*593dc095SDavid du Colombier *(chunkdata + prefix_size) = 0x00;
327*593dc095SDavid du Colombier *newlength=prefix_size;
328*593dc095SDavid du Colombier }
329*593dc095SDavid du Colombier
330*593dc095SDavid du Colombier return chunkdata;
331*593dc095SDavid du Colombier }
332*593dc095SDavid du Colombier #endif
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier /* read and check the IDHR chunk */
335*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_IHDR(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)3367dd7cddfSDavid du Colombier png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
3377dd7cddfSDavid du Colombier {
3387dd7cddfSDavid du Colombier png_byte buf[13];
3397dd7cddfSDavid du Colombier png_uint_32 width, height;
3407dd7cddfSDavid du Colombier int bit_depth, color_type, compression_type, filter_type;
3417dd7cddfSDavid du Colombier int interlace_type;
3427dd7cddfSDavid du Colombier
3437dd7cddfSDavid du Colombier png_debug(1, "in png_handle_IHDR\n");
3447dd7cddfSDavid du Colombier
345*593dc095SDavid du Colombier if (png_ptr->mode & PNG_HAVE_IHDR)
3467dd7cddfSDavid du Colombier png_error(png_ptr, "Out of place IHDR");
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier /* check the length */
3497dd7cddfSDavid du Colombier if (length != 13)
3507dd7cddfSDavid du Colombier png_error(png_ptr, "Invalid IHDR chunk");
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier png_ptr->mode |= PNG_HAVE_IHDR;
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 13);
3557dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 0);
3567dd7cddfSDavid du Colombier
357*593dc095SDavid du Colombier width = png_get_uint_31(png_ptr, buf);
358*593dc095SDavid du Colombier height = png_get_uint_31(png_ptr, buf + 4);
3597dd7cddfSDavid du Colombier bit_depth = buf[8];
3607dd7cddfSDavid du Colombier color_type = buf[9];
3617dd7cddfSDavid du Colombier compression_type = buf[10];
3627dd7cddfSDavid du Colombier filter_type = buf[11];
3637dd7cddfSDavid du Colombier interlace_type = buf[12];
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier /* set internal variables */
3667dd7cddfSDavid du Colombier png_ptr->width = width;
3677dd7cddfSDavid du Colombier png_ptr->height = height;
3687dd7cddfSDavid du Colombier png_ptr->bit_depth = (png_byte)bit_depth;
3697dd7cddfSDavid du Colombier png_ptr->interlaced = (png_byte)interlace_type;
3707dd7cddfSDavid du Colombier png_ptr->color_type = (png_byte)color_type;
371*593dc095SDavid du Colombier #if defined(PNG_MNG_FEATURES_SUPPORTED)
372*593dc095SDavid du Colombier png_ptr->filter_type = (png_byte)filter_type;
373*593dc095SDavid du Colombier #endif
374*593dc095SDavid du Colombier png_ptr->compression_type = (png_byte)compression_type;
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier /* find number of channels */
3777dd7cddfSDavid du Colombier switch (png_ptr->color_type)
3787dd7cddfSDavid du Colombier {
3797dd7cddfSDavid du Colombier case PNG_COLOR_TYPE_GRAY:
3807dd7cddfSDavid du Colombier case PNG_COLOR_TYPE_PALETTE:
3817dd7cddfSDavid du Colombier png_ptr->channels = 1;
3827dd7cddfSDavid du Colombier break;
3837dd7cddfSDavid du Colombier case PNG_COLOR_TYPE_RGB:
3847dd7cddfSDavid du Colombier png_ptr->channels = 3;
3857dd7cddfSDavid du Colombier break;
3867dd7cddfSDavid du Colombier case PNG_COLOR_TYPE_GRAY_ALPHA:
3877dd7cddfSDavid du Colombier png_ptr->channels = 2;
3887dd7cddfSDavid du Colombier break;
3897dd7cddfSDavid du Colombier case PNG_COLOR_TYPE_RGB_ALPHA:
3907dd7cddfSDavid du Colombier png_ptr->channels = 4;
3917dd7cddfSDavid du Colombier break;
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier /* set up other useful info */
3957dd7cddfSDavid du Colombier png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
3967dd7cddfSDavid du Colombier png_ptr->channels);
397*593dc095SDavid du Colombier png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
3987dd7cddfSDavid du Colombier png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
3997dd7cddfSDavid du Colombier png_debug1(3,"channels = %d\n", png_ptr->channels);
400*593dc095SDavid du Colombier png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
4017dd7cddfSDavid du Colombier png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
4027dd7cddfSDavid du Colombier color_type, interlace_type, compression_type, filter_type);
4037dd7cddfSDavid du Colombier }
4047dd7cddfSDavid du Colombier
4057dd7cddfSDavid du Colombier /* read and check the palette */
406*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_PLTE(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)4077dd7cddfSDavid du Colombier png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
4087dd7cddfSDavid du Colombier {
409*593dc095SDavid du Colombier png_color palette[PNG_MAX_PALETTE_LENGTH];
4107dd7cddfSDavid du Colombier int num, i;
411*593dc095SDavid du Colombier #ifndef PNG_NO_POINTER_INDEXING
412*593dc095SDavid du Colombier png_colorp pal_ptr;
413*593dc095SDavid du Colombier #endif
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier png_debug(1, "in png_handle_PLTE\n");
4167dd7cddfSDavid du Colombier
4177dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
4187dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before PLTE");
4197dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
4207dd7cddfSDavid du Colombier {
4217dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid PLTE after IDAT");
4227dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
4237dd7cddfSDavid du Colombier return;
4247dd7cddfSDavid du Colombier }
4257dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_PLTE)
4267dd7cddfSDavid du Colombier png_error(png_ptr, "Duplicate PLTE chunk");
4277dd7cddfSDavid du Colombier
4287dd7cddfSDavid du Colombier png_ptr->mode |= PNG_HAVE_PLTE;
4297dd7cddfSDavid du Colombier
430*593dc095SDavid du Colombier if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
431*593dc095SDavid du Colombier {
432*593dc095SDavid du Colombier png_warning(png_ptr,
433*593dc095SDavid du Colombier "Ignoring PLTE chunk in grayscale PNG");
434*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
435*593dc095SDavid du Colombier return;
436*593dc095SDavid du Colombier }
4377dd7cddfSDavid du Colombier #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
4387dd7cddfSDavid du Colombier if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
4417dd7cddfSDavid du Colombier return;
4427dd7cddfSDavid du Colombier }
4437dd7cddfSDavid du Colombier #endif
4447dd7cddfSDavid du Colombier
445*593dc095SDavid du Colombier if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
4467dd7cddfSDavid du Colombier {
4477dd7cddfSDavid du Colombier if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
4487dd7cddfSDavid du Colombier {
4497dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid palette chunk");
4507dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
4517dd7cddfSDavid du Colombier return;
4527dd7cddfSDavid du Colombier }
4537dd7cddfSDavid du Colombier else
4547dd7cddfSDavid du Colombier {
4557dd7cddfSDavid du Colombier png_error(png_ptr, "Invalid palette chunk");
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier }
4587dd7cddfSDavid du Colombier
4597dd7cddfSDavid du Colombier num = (int)length / 3;
460*593dc095SDavid du Colombier
461*593dc095SDavid du Colombier #ifndef PNG_NO_POINTER_INDEXING
462*593dc095SDavid du Colombier for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
463*593dc095SDavid du Colombier {
464*593dc095SDavid du Colombier png_byte buf[3];
465*593dc095SDavid du Colombier
466*593dc095SDavid du Colombier png_crc_read(png_ptr, buf, 3);
467*593dc095SDavid du Colombier pal_ptr->red = buf[0];
468*593dc095SDavid du Colombier pal_ptr->green = buf[1];
469*593dc095SDavid du Colombier pal_ptr->blue = buf[2];
470*593dc095SDavid du Colombier }
471*593dc095SDavid du Colombier #else
4727dd7cddfSDavid du Colombier for (i = 0; i < num; i++)
4737dd7cddfSDavid du Colombier {
4747dd7cddfSDavid du Colombier png_byte buf[3];
4757dd7cddfSDavid du Colombier
4767dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 3);
4777dd7cddfSDavid du Colombier /* don't depend upon png_color being any order */
4787dd7cddfSDavid du Colombier palette[i].red = buf[0];
4797dd7cddfSDavid du Colombier palette[i].green = buf[1];
4807dd7cddfSDavid du Colombier palette[i].blue = buf[2];
4817dd7cddfSDavid du Colombier }
482*593dc095SDavid du Colombier #endif
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
4857dd7cddfSDavid du Colombier whatever the normal CRC configuration tells us. However, if we
4867dd7cddfSDavid du Colombier have an RGB image, the PLTE can be considered ancillary, so
4877dd7cddfSDavid du Colombier we will act as though it is. */
4887dd7cddfSDavid du Colombier #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
4897dd7cddfSDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
4907dd7cddfSDavid du Colombier #endif
4917dd7cddfSDavid du Colombier {
4927dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 0);
4937dd7cddfSDavid du Colombier }
4947dd7cddfSDavid du Colombier #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
4957dd7cddfSDavid du Colombier else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
4967dd7cddfSDavid du Colombier {
4977dd7cddfSDavid du Colombier /* If we don't want to use the data from an ancillary chunk,
4987dd7cddfSDavid du Colombier we have two options: an error abort, or a warning and we
4997dd7cddfSDavid du Colombier ignore the data in this chunk (which should be OK, since
5007dd7cddfSDavid du Colombier it's considered ancillary for a RGB or RGBA image). */
5017dd7cddfSDavid du Colombier if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
5027dd7cddfSDavid du Colombier {
5037dd7cddfSDavid du Colombier if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
5047dd7cddfSDavid du Colombier {
5057dd7cddfSDavid du Colombier png_chunk_error(png_ptr, "CRC error");
5067dd7cddfSDavid du Colombier }
5077dd7cddfSDavid du Colombier else
5087dd7cddfSDavid du Colombier {
5097dd7cddfSDavid du Colombier png_chunk_warning(png_ptr, "CRC error");
5107dd7cddfSDavid du Colombier return;
5117dd7cddfSDavid du Colombier }
5127dd7cddfSDavid du Colombier }
5137dd7cddfSDavid du Colombier /* Otherwise, we (optionally) emit a warning and use the chunk. */
5147dd7cddfSDavid du Colombier else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
5157dd7cddfSDavid du Colombier {
5167dd7cddfSDavid du Colombier png_chunk_warning(png_ptr, "CRC error");
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier }
5197dd7cddfSDavid du Colombier #endif
520*593dc095SDavid du Colombier
5217dd7cddfSDavid du Colombier png_set_PLTE(png_ptr, info_ptr, palette, num);
522*593dc095SDavid du Colombier
523*593dc095SDavid du Colombier #if defined(PNG_READ_tRNS_SUPPORTED)
524*593dc095SDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
525*593dc095SDavid du Colombier {
526*593dc095SDavid du Colombier if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
527*593dc095SDavid du Colombier {
528*593dc095SDavid du Colombier if (png_ptr->num_trans > (png_uint_16)num)
529*593dc095SDavid du Colombier {
530*593dc095SDavid du Colombier png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
531*593dc095SDavid du Colombier png_ptr->num_trans = (png_uint_16)num;
532*593dc095SDavid du Colombier }
533*593dc095SDavid du Colombier if (info_ptr->num_trans > (png_uint_16)num)
534*593dc095SDavid du Colombier {
535*593dc095SDavid du Colombier png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
536*593dc095SDavid du Colombier info_ptr->num_trans = (png_uint_16)num;
537*593dc095SDavid du Colombier }
538*593dc095SDavid du Colombier }
539*593dc095SDavid du Colombier }
540*593dc095SDavid du Colombier #endif
541*593dc095SDavid du Colombier
5427dd7cddfSDavid du Colombier }
5437dd7cddfSDavid du Colombier
544*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_IEND(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)5457dd7cddfSDavid du Colombier png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
5467dd7cddfSDavid du Colombier {
5477dd7cddfSDavid du Colombier png_debug(1, "in png_handle_IEND\n");
5487dd7cddfSDavid du Colombier
5497dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
5507dd7cddfSDavid du Colombier {
5517dd7cddfSDavid du Colombier png_error(png_ptr, "No image in file");
5527dd7cddfSDavid du Colombier }
5537dd7cddfSDavid du Colombier
554*593dc095SDavid du Colombier png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
5557dd7cddfSDavid du Colombier
5567dd7cddfSDavid du Colombier if (length != 0)
5577dd7cddfSDavid du Colombier {
5587dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect IEND chunk length");
5597dd7cddfSDavid du Colombier }
5607dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
561*593dc095SDavid du Colombier
562*593dc095SDavid du Colombier if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
563*593dc095SDavid du Colombier return;
5647dd7cddfSDavid du Colombier }
5657dd7cddfSDavid du Colombier
5667dd7cddfSDavid du Colombier #if defined(PNG_READ_gAMA_SUPPORTED)
567*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_gAMA(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)5687dd7cddfSDavid du Colombier png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
5697dd7cddfSDavid du Colombier {
570*593dc095SDavid du Colombier png_fixed_point igamma;
571*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
5727dd7cddfSDavid du Colombier float file_gamma;
573*593dc095SDavid du Colombier #endif
5747dd7cddfSDavid du Colombier png_byte buf[4];
5757dd7cddfSDavid du Colombier
5767dd7cddfSDavid du Colombier png_debug(1, "in png_handle_gAMA\n");
5777dd7cddfSDavid du Colombier
5787dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
5797dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before gAMA");
5807dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
5817dd7cddfSDavid du Colombier {
5827dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid gAMA after IDAT");
5837dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
5847dd7cddfSDavid du Colombier return;
5857dd7cddfSDavid du Colombier }
5867dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_PLTE)
5877dd7cddfSDavid du Colombier /* Should be an error, but we can cope with it */
5887dd7cddfSDavid du Colombier png_warning(png_ptr, "Out of place gAMA chunk");
5897dd7cddfSDavid du Colombier
590*593dc095SDavid du Colombier if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
5917dd7cddfSDavid du Colombier #if defined(PNG_READ_sRGB_SUPPORTED)
5927dd7cddfSDavid du Colombier && !(info_ptr->valid & PNG_INFO_sRGB)
5937dd7cddfSDavid du Colombier #endif
5947dd7cddfSDavid du Colombier )
5957dd7cddfSDavid du Colombier {
5967dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate gAMA chunk");
5977dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
5987dd7cddfSDavid du Colombier return;
5997dd7cddfSDavid du Colombier }
6007dd7cddfSDavid du Colombier
6017dd7cddfSDavid du Colombier if (length != 4)
6027dd7cddfSDavid du Colombier {
6037dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect gAMA chunk length");
6047dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
6057dd7cddfSDavid du Colombier return;
6067dd7cddfSDavid du Colombier }
6077dd7cddfSDavid du Colombier
6087dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
6097dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
6107dd7cddfSDavid du Colombier return;
6117dd7cddfSDavid du Colombier
612*593dc095SDavid du Colombier igamma = (png_fixed_point)png_get_uint_32(buf);
6137dd7cddfSDavid du Colombier /* check for zero gamma */
6147dd7cddfSDavid du Colombier if (igamma == 0)
615*593dc095SDavid du Colombier {
616*593dc095SDavid du Colombier png_warning(png_ptr,
617*593dc095SDavid du Colombier "Ignoring gAMA chunk with gamma=0");
6187dd7cddfSDavid du Colombier return;
619*593dc095SDavid du Colombier }
6207dd7cddfSDavid du Colombier
6217dd7cddfSDavid du Colombier #if defined(PNG_READ_sRGB_SUPPORTED)
6227dd7cddfSDavid du Colombier if (info_ptr->valid & PNG_INFO_sRGB)
623*593dc095SDavid du Colombier if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
6247dd7cddfSDavid du Colombier {
6257dd7cddfSDavid du Colombier png_warning(png_ptr,
6267dd7cddfSDavid du Colombier "Ignoring incorrect gAMA value when sRGB is also present");
627*593dc095SDavid du Colombier #ifndef PNG_NO_CONSOLE_IO
628*593dc095SDavid du Colombier fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
6297dd7cddfSDavid du Colombier #endif
6307dd7cddfSDavid du Colombier return;
6317dd7cddfSDavid du Colombier }
6327dd7cddfSDavid du Colombier #endif /* PNG_READ_sRGB_SUPPORTED */
6337dd7cddfSDavid du Colombier
634*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
6357dd7cddfSDavid du Colombier file_gamma = (float)igamma / (float)100000.0;
6367dd7cddfSDavid du Colombier # ifdef PNG_READ_GAMMA_SUPPORTED
6377dd7cddfSDavid du Colombier png_ptr->gamma = file_gamma;
6387dd7cddfSDavid du Colombier # endif
6397dd7cddfSDavid du Colombier png_set_gAMA(png_ptr, info_ptr, file_gamma);
640*593dc095SDavid du Colombier #endif
641*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
642*593dc095SDavid du Colombier png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
643*593dc095SDavid du Colombier #endif
6447dd7cddfSDavid du Colombier }
6457dd7cddfSDavid du Colombier #endif
6467dd7cddfSDavid du Colombier
6477dd7cddfSDavid du Colombier #if defined(PNG_READ_sBIT_SUPPORTED)
648*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_sBIT(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)6497dd7cddfSDavid du Colombier png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
6507dd7cddfSDavid du Colombier {
6517dd7cddfSDavid du Colombier png_size_t truelen;
6527dd7cddfSDavid du Colombier png_byte buf[4];
6537dd7cddfSDavid du Colombier
6547dd7cddfSDavid du Colombier png_debug(1, "in png_handle_sBIT\n");
6557dd7cddfSDavid du Colombier
6567dd7cddfSDavid du Colombier buf[0] = buf[1] = buf[2] = buf[3] = 0;
6577dd7cddfSDavid du Colombier
6587dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
6597dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before sBIT");
6607dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
6617dd7cddfSDavid du Colombier {
6627dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid sBIT after IDAT");
6637dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
6647dd7cddfSDavid du Colombier return;
6657dd7cddfSDavid du Colombier }
6667dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_PLTE)
6677dd7cddfSDavid du Colombier {
6687dd7cddfSDavid du Colombier /* Should be an error, but we can cope with it */
6697dd7cddfSDavid du Colombier png_warning(png_ptr, "Out of place sBIT chunk");
6707dd7cddfSDavid du Colombier }
671*593dc095SDavid du Colombier if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
6727dd7cddfSDavid du Colombier {
6737dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate sBIT chunk");
6747dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
6757dd7cddfSDavid du Colombier return;
6767dd7cddfSDavid du Colombier }
6777dd7cddfSDavid du Colombier
6787dd7cddfSDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
6797dd7cddfSDavid du Colombier truelen = 3;
6807dd7cddfSDavid du Colombier else
6817dd7cddfSDavid du Colombier truelen = (png_size_t)png_ptr->channels;
6827dd7cddfSDavid du Colombier
683*593dc095SDavid du Colombier if (length != truelen || length > 4)
6847dd7cddfSDavid du Colombier {
6857dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect sBIT chunk length");
6867dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
6877dd7cddfSDavid du Colombier return;
6887dd7cddfSDavid du Colombier }
6897dd7cddfSDavid du Colombier
6907dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, truelen);
6917dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
6927dd7cddfSDavid du Colombier return;
6937dd7cddfSDavid du Colombier
6947dd7cddfSDavid du Colombier if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
6957dd7cddfSDavid du Colombier {
6967dd7cddfSDavid du Colombier png_ptr->sig_bit.red = buf[0];
6977dd7cddfSDavid du Colombier png_ptr->sig_bit.green = buf[1];
6987dd7cddfSDavid du Colombier png_ptr->sig_bit.blue = buf[2];
6997dd7cddfSDavid du Colombier png_ptr->sig_bit.alpha = buf[3];
7007dd7cddfSDavid du Colombier }
7017dd7cddfSDavid du Colombier else
7027dd7cddfSDavid du Colombier {
7037dd7cddfSDavid du Colombier png_ptr->sig_bit.gray = buf[0];
704*593dc095SDavid du Colombier png_ptr->sig_bit.red = buf[0];
705*593dc095SDavid du Colombier png_ptr->sig_bit.green = buf[0];
706*593dc095SDavid du Colombier png_ptr->sig_bit.blue = buf[0];
7077dd7cddfSDavid du Colombier png_ptr->sig_bit.alpha = buf[1];
7087dd7cddfSDavid du Colombier }
7097dd7cddfSDavid du Colombier png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
7107dd7cddfSDavid du Colombier }
7117dd7cddfSDavid du Colombier #endif
7127dd7cddfSDavid du Colombier
7137dd7cddfSDavid du Colombier #if defined(PNG_READ_cHRM_SUPPORTED)
714*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_cHRM(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)7157dd7cddfSDavid du Colombier png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
7167dd7cddfSDavid du Colombier {
7177dd7cddfSDavid du Colombier png_byte buf[4];
718*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
7197dd7cddfSDavid du Colombier float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
720*593dc095SDavid du Colombier #endif
721*593dc095SDavid du Colombier png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
722*593dc095SDavid du Colombier int_y_green, int_x_blue, int_y_blue;
723*593dc095SDavid du Colombier
724*593dc095SDavid du Colombier png_uint_32 uint_x, uint_y;
7257dd7cddfSDavid du Colombier
7267dd7cddfSDavid du Colombier png_debug(1, "in png_handle_cHRM\n");
7277dd7cddfSDavid du Colombier
7287dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
729*593dc095SDavid du Colombier png_error(png_ptr, "Missing IHDR before cHRM");
7307dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
7317dd7cddfSDavid du Colombier {
7327dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid cHRM after IDAT");
7337dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
7347dd7cddfSDavid du Colombier return;
7357dd7cddfSDavid du Colombier }
7367dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_PLTE)
7377dd7cddfSDavid du Colombier /* Should be an error, but we can cope with it */
7387dd7cddfSDavid du Colombier png_warning(png_ptr, "Missing PLTE before cHRM");
7397dd7cddfSDavid du Colombier
740*593dc095SDavid du Colombier if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
7417dd7cddfSDavid du Colombier #if defined(PNG_READ_sRGB_SUPPORTED)
7427dd7cddfSDavid du Colombier && !(info_ptr->valid & PNG_INFO_sRGB)
7437dd7cddfSDavid du Colombier #endif
7447dd7cddfSDavid du Colombier )
7457dd7cddfSDavid du Colombier {
7467dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate cHRM chunk");
7477dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
7487dd7cddfSDavid du Colombier return;
7497dd7cddfSDavid du Colombier }
7507dd7cddfSDavid du Colombier
7517dd7cddfSDavid du Colombier if (length != 32)
7527dd7cddfSDavid du Colombier {
7537dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect cHRM chunk length");
7547dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
7557dd7cddfSDavid du Colombier return;
7567dd7cddfSDavid du Colombier }
7577dd7cddfSDavid du Colombier
7587dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
759*593dc095SDavid du Colombier uint_x = png_get_uint_32(buf);
7607dd7cddfSDavid du Colombier
7617dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
762*593dc095SDavid du Colombier uint_y = png_get_uint_32(buf);
7637dd7cddfSDavid du Colombier
764*593dc095SDavid du Colombier if (uint_x > 80000L || uint_y > 80000L ||
765*593dc095SDavid du Colombier uint_x + uint_y > 100000L)
7667dd7cddfSDavid du Colombier {
7677dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid cHRM white point");
7687dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 24);
7697dd7cddfSDavid du Colombier return;
7707dd7cddfSDavid du Colombier }
771*593dc095SDavid du Colombier int_x_white = (png_fixed_point)uint_x;
772*593dc095SDavid du Colombier int_y_white = (png_fixed_point)uint_y;
7737dd7cddfSDavid du Colombier
7747dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
775*593dc095SDavid du Colombier uint_x = png_get_uint_32(buf);
7767dd7cddfSDavid du Colombier
7777dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
778*593dc095SDavid du Colombier uint_y = png_get_uint_32(buf);
7797dd7cddfSDavid du Colombier
780*593dc095SDavid du Colombier if (uint_x > 80000L || uint_y > 80000L ||
781*593dc095SDavid du Colombier uint_x + uint_y > 100000L)
7827dd7cddfSDavid du Colombier {
7837dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid cHRM red point");
7847dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 16);
7857dd7cddfSDavid du Colombier return;
7867dd7cddfSDavid du Colombier }
787*593dc095SDavid du Colombier int_x_red = (png_fixed_point)uint_x;
788*593dc095SDavid du Colombier int_y_red = (png_fixed_point)uint_y;
7897dd7cddfSDavid du Colombier
7907dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
791*593dc095SDavid du Colombier uint_x = png_get_uint_32(buf);
7927dd7cddfSDavid du Colombier
7937dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
794*593dc095SDavid du Colombier uint_y = png_get_uint_32(buf);
7957dd7cddfSDavid du Colombier
796*593dc095SDavid du Colombier if (uint_x > 80000L || uint_y > 80000L ||
797*593dc095SDavid du Colombier uint_x + uint_y > 100000L)
7987dd7cddfSDavid du Colombier {
7997dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid cHRM green point");
8007dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 8);
8017dd7cddfSDavid du Colombier return;
8027dd7cddfSDavid du Colombier }
803*593dc095SDavid du Colombier int_x_green = (png_fixed_point)uint_x;
804*593dc095SDavid du Colombier int_y_green = (png_fixed_point)uint_y;
8057dd7cddfSDavid du Colombier
8067dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
807*593dc095SDavid du Colombier uint_x = png_get_uint_32(buf);
8087dd7cddfSDavid du Colombier
8097dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 4);
810*593dc095SDavid du Colombier uint_y = png_get_uint_32(buf);
8117dd7cddfSDavid du Colombier
812*593dc095SDavid du Colombier if (uint_x > 80000L || uint_y > 80000L ||
813*593dc095SDavid du Colombier uint_x + uint_y > 100000L)
8147dd7cddfSDavid du Colombier {
8157dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid cHRM blue point");
8167dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 0);
8177dd7cddfSDavid du Colombier return;
8187dd7cddfSDavid du Colombier }
819*593dc095SDavid du Colombier int_x_blue = (png_fixed_point)uint_x;
820*593dc095SDavid du Colombier int_y_blue = (png_fixed_point)uint_y;
8217dd7cddfSDavid du Colombier
822*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
823*593dc095SDavid du Colombier white_x = (float)int_x_white / (float)100000.0;
824*593dc095SDavid du Colombier white_y = (float)int_y_white / (float)100000.0;
825*593dc095SDavid du Colombier red_x = (float)int_x_red / (float)100000.0;
826*593dc095SDavid du Colombier red_y = (float)int_y_red / (float)100000.0;
827*593dc095SDavid du Colombier green_x = (float)int_x_green / (float)100000.0;
828*593dc095SDavid du Colombier green_y = (float)int_y_green / (float)100000.0;
829*593dc095SDavid du Colombier blue_x = (float)int_x_blue / (float)100000.0;
830*593dc095SDavid du Colombier blue_y = (float)int_y_blue / (float)100000.0;
831*593dc095SDavid du Colombier #endif
8327dd7cddfSDavid du Colombier
8337dd7cddfSDavid du Colombier #if defined(PNG_READ_sRGB_SUPPORTED)
8347dd7cddfSDavid du Colombier if (info_ptr->valid & PNG_INFO_sRGB)
8357dd7cddfSDavid du Colombier {
836*593dc095SDavid du Colombier if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
837*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
838*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
839*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
840*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
841*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
842*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
843*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
8447dd7cddfSDavid du Colombier {
8457dd7cddfSDavid du Colombier
8467dd7cddfSDavid du Colombier png_warning(png_ptr,
8477dd7cddfSDavid du Colombier "Ignoring incorrect cHRM value when sRGB is also present");
848*593dc095SDavid du Colombier #ifndef PNG_NO_CONSOLE_IO
849*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
8507dd7cddfSDavid du Colombier fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
8517dd7cddfSDavid du Colombier white_x, white_y, red_x, red_y);
8527dd7cddfSDavid du Colombier fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
8537dd7cddfSDavid du Colombier green_x, green_y, blue_x, blue_y);
854*593dc095SDavid du Colombier #else
855*593dc095SDavid du Colombier fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
856*593dc095SDavid du Colombier int_x_white, int_y_white, int_x_red, int_y_red);
857*593dc095SDavid du Colombier fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
858*593dc095SDavid du Colombier int_x_green, int_y_green, int_x_blue, int_y_blue);
8597dd7cddfSDavid du Colombier #endif
860*593dc095SDavid du Colombier #endif /* PNG_NO_CONSOLE_IO */
8617dd7cddfSDavid du Colombier }
862*593dc095SDavid du Colombier png_crc_finish(png_ptr, 0);
8637dd7cddfSDavid du Colombier return;
8647dd7cddfSDavid du Colombier }
8657dd7cddfSDavid du Colombier #endif /* PNG_READ_sRGB_SUPPORTED */
8667dd7cddfSDavid du Colombier
867*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
8687dd7cddfSDavid du Colombier png_set_cHRM(png_ptr, info_ptr,
8697dd7cddfSDavid du Colombier white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
870*593dc095SDavid du Colombier #endif
871*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
872*593dc095SDavid du Colombier png_set_cHRM_fixed(png_ptr, info_ptr,
873*593dc095SDavid du Colombier int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
874*593dc095SDavid du Colombier int_y_green, int_x_blue, int_y_blue);
875*593dc095SDavid du Colombier #endif
876*593dc095SDavid du Colombier if (png_crc_finish(png_ptr, 0))
877*593dc095SDavid du Colombier return;
8787dd7cddfSDavid du Colombier }
8797dd7cddfSDavid du Colombier #endif
8807dd7cddfSDavid du Colombier
8817dd7cddfSDavid du Colombier #if defined(PNG_READ_sRGB_SUPPORTED)
882*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_sRGB(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)8837dd7cddfSDavid du Colombier png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
8847dd7cddfSDavid du Colombier {
8857dd7cddfSDavid du Colombier int intent;
8867dd7cddfSDavid du Colombier png_byte buf[1];
8877dd7cddfSDavid du Colombier
8887dd7cddfSDavid du Colombier png_debug(1, "in png_handle_sRGB\n");
8897dd7cddfSDavid du Colombier
8907dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
8917dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before sRGB");
8927dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
8937dd7cddfSDavid du Colombier {
8947dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid sRGB after IDAT");
8957dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
8967dd7cddfSDavid du Colombier return;
8977dd7cddfSDavid du Colombier }
8987dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_PLTE)
8997dd7cddfSDavid du Colombier /* Should be an error, but we can cope with it */
9007dd7cddfSDavid du Colombier png_warning(png_ptr, "Out of place sRGB chunk");
9017dd7cddfSDavid du Colombier
902*593dc095SDavid du Colombier if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
9037dd7cddfSDavid du Colombier {
9047dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate sRGB chunk");
9057dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
9067dd7cddfSDavid du Colombier return;
9077dd7cddfSDavid du Colombier }
9087dd7cddfSDavid du Colombier
9097dd7cddfSDavid du Colombier if (length != 1)
9107dd7cddfSDavid du Colombier {
9117dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect sRGB chunk length");
9127dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
9137dd7cddfSDavid du Colombier return;
9147dd7cddfSDavid du Colombier }
9157dd7cddfSDavid du Colombier
9167dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 1);
9177dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
9187dd7cddfSDavid du Colombier return;
9197dd7cddfSDavid du Colombier
9207dd7cddfSDavid du Colombier intent = buf[0];
9217dd7cddfSDavid du Colombier /* check for bad intent */
9227dd7cddfSDavid du Colombier if (intent >= PNG_sRGB_INTENT_LAST)
9237dd7cddfSDavid du Colombier {
9247dd7cddfSDavid du Colombier png_warning(png_ptr, "Unknown sRGB intent");
9257dd7cddfSDavid du Colombier return;
9267dd7cddfSDavid du Colombier }
9277dd7cddfSDavid du Colombier
9287dd7cddfSDavid du Colombier #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
9297dd7cddfSDavid du Colombier if ((info_ptr->valid & PNG_INFO_gAMA))
930*593dc095SDavid du Colombier {
931*593dc095SDavid du Colombier png_fixed_point igamma;
932*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
933*593dc095SDavid du Colombier igamma=info_ptr->int_gamma;
934*593dc095SDavid du Colombier #else
935*593dc095SDavid du Colombier # ifdef PNG_FLOATING_POINT_SUPPORTED
936*593dc095SDavid du Colombier igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
937*593dc095SDavid du Colombier # endif
938*593dc095SDavid du Colombier #endif
939*593dc095SDavid du Colombier if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
9407dd7cddfSDavid du Colombier {
9417dd7cddfSDavid du Colombier png_warning(png_ptr,
9427dd7cddfSDavid du Colombier "Ignoring incorrect gAMA value when sRGB is also present");
943*593dc095SDavid du Colombier #ifndef PNG_NO_CONSOLE_IO
944*593dc095SDavid du Colombier # ifdef PNG_FIXED_POINT_SUPPORTED
945*593dc095SDavid du Colombier fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
946*593dc095SDavid du Colombier # else
947*593dc095SDavid du Colombier # ifdef PNG_FLOATING_POINT_SUPPORTED
948*593dc095SDavid du Colombier fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
9497dd7cddfSDavid du Colombier # endif
950*593dc095SDavid du Colombier # endif
951*593dc095SDavid du Colombier #endif
952*593dc095SDavid du Colombier }
9537dd7cddfSDavid du Colombier }
9547dd7cddfSDavid du Colombier #endif /* PNG_READ_gAMA_SUPPORTED */
9557dd7cddfSDavid du Colombier
9567dd7cddfSDavid du Colombier #ifdef PNG_READ_cHRM_SUPPORTED
957*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
9587dd7cddfSDavid du Colombier if (info_ptr->valid & PNG_INFO_cHRM)
959*593dc095SDavid du Colombier if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
960*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
961*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
962*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
963*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
964*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
965*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
966*593dc095SDavid du Colombier PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
9677dd7cddfSDavid du Colombier {
9687dd7cddfSDavid du Colombier png_warning(png_ptr,
9697dd7cddfSDavid du Colombier "Ignoring incorrect cHRM value when sRGB is also present");
9707dd7cddfSDavid du Colombier }
971*593dc095SDavid du Colombier #endif /* PNG_FIXED_POINT_SUPPORTED */
9727dd7cddfSDavid du Colombier #endif /* PNG_READ_cHRM_SUPPORTED */
9737dd7cddfSDavid du Colombier
9747dd7cddfSDavid du Colombier png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
9757dd7cddfSDavid du Colombier }
9767dd7cddfSDavid du Colombier #endif /* PNG_READ_sRGB_SUPPORTED */
9777dd7cddfSDavid du Colombier
978*593dc095SDavid du Colombier #if defined(PNG_READ_iCCP_SUPPORTED)
979*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_iCCP(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)980*593dc095SDavid du Colombier png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
981*593dc095SDavid du Colombier /* Note: this does not properly handle chunks that are > 64K under DOS */
982*593dc095SDavid du Colombier {
983*593dc095SDavid du Colombier png_charp chunkdata;
984*593dc095SDavid du Colombier png_byte compression_type;
985*593dc095SDavid du Colombier png_bytep pC;
986*593dc095SDavid du Colombier png_charp profile;
987*593dc095SDavid du Colombier png_uint_32 skip = 0;
988*593dc095SDavid du Colombier png_uint_32 profile_size, profile_length;
989*593dc095SDavid du Colombier png_size_t slength, prefix_length, data_length;
990*593dc095SDavid du Colombier
991*593dc095SDavid du Colombier png_debug(1, "in png_handle_iCCP\n");
992*593dc095SDavid du Colombier
993*593dc095SDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
994*593dc095SDavid du Colombier png_error(png_ptr, "Missing IHDR before iCCP");
995*593dc095SDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
996*593dc095SDavid du Colombier {
997*593dc095SDavid du Colombier png_warning(png_ptr, "Invalid iCCP after IDAT");
998*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
999*593dc095SDavid du Colombier return;
1000*593dc095SDavid du Colombier }
1001*593dc095SDavid du Colombier else if (png_ptr->mode & PNG_HAVE_PLTE)
1002*593dc095SDavid du Colombier /* Should be an error, but we can cope with it */
1003*593dc095SDavid du Colombier png_warning(png_ptr, "Out of place iCCP chunk");
1004*593dc095SDavid du Colombier
1005*593dc095SDavid du Colombier if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1006*593dc095SDavid du Colombier {
1007*593dc095SDavid du Colombier png_warning(png_ptr, "Duplicate iCCP chunk");
1008*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1009*593dc095SDavid du Colombier return;
1010*593dc095SDavid du Colombier }
1011*593dc095SDavid du Colombier
1012*593dc095SDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
1013*593dc095SDavid du Colombier if (length > (png_uint_32)65535L)
1014*593dc095SDavid du Colombier {
1015*593dc095SDavid du Colombier png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1016*593dc095SDavid du Colombier skip = length - (png_uint_32)65535L;
1017*593dc095SDavid du Colombier length = (png_uint_32)65535L;
1018*593dc095SDavid du Colombier }
1019*593dc095SDavid du Colombier #endif
1020*593dc095SDavid du Colombier
1021*593dc095SDavid du Colombier chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1022*593dc095SDavid du Colombier slength = (png_size_t)length;
1023*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1024*593dc095SDavid du Colombier
1025*593dc095SDavid du Colombier if (png_crc_finish(png_ptr, skip))
1026*593dc095SDavid du Colombier {
1027*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1028*593dc095SDavid du Colombier return;
1029*593dc095SDavid du Colombier }
1030*593dc095SDavid du Colombier
1031*593dc095SDavid du Colombier chunkdata[slength] = 0x00;
1032*593dc095SDavid du Colombier
1033*593dc095SDavid du Colombier for (profile = chunkdata; *profile; profile++)
1034*593dc095SDavid du Colombier /* empty loop to find end of name */ ;
1035*593dc095SDavid du Colombier
1036*593dc095SDavid du Colombier ++profile;
1037*593dc095SDavid du Colombier
1038*593dc095SDavid du Colombier /* there should be at least one zero (the compression type byte)
1039*593dc095SDavid du Colombier following the separator, and we should be on it */
1040*593dc095SDavid du Colombier if ( profile >= chunkdata + slength)
1041*593dc095SDavid du Colombier {
1042*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1043*593dc095SDavid du Colombier png_warning(png_ptr, "Malformed iCCP chunk");
1044*593dc095SDavid du Colombier return;
1045*593dc095SDavid du Colombier }
1046*593dc095SDavid du Colombier
1047*593dc095SDavid du Colombier /* compression_type should always be zero */
1048*593dc095SDavid du Colombier compression_type = *profile++;
1049*593dc095SDavid du Colombier if (compression_type)
1050*593dc095SDavid du Colombier {
1051*593dc095SDavid du Colombier png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1052*593dc095SDavid du Colombier compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1053*593dc095SDavid du Colombier wrote nonzero) */
1054*593dc095SDavid du Colombier }
1055*593dc095SDavid du Colombier
1056*593dc095SDavid du Colombier prefix_length = profile - chunkdata;
1057*593dc095SDavid du Colombier chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1058*593dc095SDavid du Colombier slength, prefix_length, &data_length);
1059*593dc095SDavid du Colombier
1060*593dc095SDavid du Colombier profile_length = data_length - prefix_length;
1061*593dc095SDavid du Colombier
1062*593dc095SDavid du Colombier if ( prefix_length > data_length || profile_length < 4)
1063*593dc095SDavid du Colombier {
1064*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1065*593dc095SDavid du Colombier png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1066*593dc095SDavid du Colombier return;
1067*593dc095SDavid du Colombier }
1068*593dc095SDavid du Colombier
1069*593dc095SDavid du Colombier /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1070*593dc095SDavid du Colombier pC = (png_bytep)(chunkdata+prefix_length);
1071*593dc095SDavid du Colombier profile_size = ((*(pC ))<<24) |
1072*593dc095SDavid du Colombier ((*(pC+1))<<16) |
1073*593dc095SDavid du Colombier ((*(pC+2))<< 8) |
1074*593dc095SDavid du Colombier ((*(pC+3)) );
1075*593dc095SDavid du Colombier
1076*593dc095SDavid du Colombier if(profile_size < profile_length)
1077*593dc095SDavid du Colombier profile_length = profile_size;
1078*593dc095SDavid du Colombier
1079*593dc095SDavid du Colombier if(profile_size > profile_length)
1080*593dc095SDavid du Colombier {
1081*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1082*593dc095SDavid du Colombier png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1083*593dc095SDavid du Colombier return;
1084*593dc095SDavid du Colombier }
1085*593dc095SDavid du Colombier
1086*593dc095SDavid du Colombier png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1087*593dc095SDavid du Colombier chunkdata + prefix_length, profile_length);
1088*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1089*593dc095SDavid du Colombier }
1090*593dc095SDavid du Colombier #endif /* PNG_READ_iCCP_SUPPORTED */
1091*593dc095SDavid du Colombier
1092*593dc095SDavid du Colombier #if defined(PNG_READ_sPLT_SUPPORTED)
1093*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_sPLT(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1094*593dc095SDavid du Colombier png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1095*593dc095SDavid du Colombier /* Note: this does not properly handle chunks that are > 64K under DOS */
1096*593dc095SDavid du Colombier {
1097*593dc095SDavid du Colombier png_bytep chunkdata;
1098*593dc095SDavid du Colombier png_bytep entry_start;
1099*593dc095SDavid du Colombier png_sPLT_t new_palette;
1100*593dc095SDavid du Colombier #ifdef PNG_NO_POINTER_INDEXING
1101*593dc095SDavid du Colombier png_sPLT_entryp pp;
1102*593dc095SDavid du Colombier #endif
1103*593dc095SDavid du Colombier int data_length, entry_size, i;
1104*593dc095SDavid du Colombier png_uint_32 skip = 0;
1105*593dc095SDavid du Colombier png_size_t slength;
1106*593dc095SDavid du Colombier
1107*593dc095SDavid du Colombier png_debug(1, "in png_handle_sPLT\n");
1108*593dc095SDavid du Colombier
1109*593dc095SDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
1110*593dc095SDavid du Colombier png_error(png_ptr, "Missing IHDR before sPLT");
1111*593dc095SDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
1112*593dc095SDavid du Colombier {
1113*593dc095SDavid du Colombier png_warning(png_ptr, "Invalid sPLT after IDAT");
1114*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1115*593dc095SDavid du Colombier return;
1116*593dc095SDavid du Colombier }
1117*593dc095SDavid du Colombier
1118*593dc095SDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
1119*593dc095SDavid du Colombier if (length > (png_uint_32)65535L)
1120*593dc095SDavid du Colombier {
1121*593dc095SDavid du Colombier png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1122*593dc095SDavid du Colombier skip = length - (png_uint_32)65535L;
1123*593dc095SDavid du Colombier length = (png_uint_32)65535L;
1124*593dc095SDavid du Colombier }
1125*593dc095SDavid du Colombier #endif
1126*593dc095SDavid du Colombier
1127*593dc095SDavid du Colombier chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1128*593dc095SDavid du Colombier slength = (png_size_t)length;
1129*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1130*593dc095SDavid du Colombier
1131*593dc095SDavid du Colombier if (png_crc_finish(png_ptr, skip))
1132*593dc095SDavid du Colombier {
1133*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1134*593dc095SDavid du Colombier return;
1135*593dc095SDavid du Colombier }
1136*593dc095SDavid du Colombier
1137*593dc095SDavid du Colombier chunkdata[slength] = 0x00;
1138*593dc095SDavid du Colombier
1139*593dc095SDavid du Colombier for (entry_start = chunkdata; *entry_start; entry_start++)
1140*593dc095SDavid du Colombier /* empty loop to find end of name */ ;
1141*593dc095SDavid du Colombier ++entry_start;
1142*593dc095SDavid du Colombier
1143*593dc095SDavid du Colombier /* a sample depth should follow the separator, and we should be on it */
1144*593dc095SDavid du Colombier if (entry_start > chunkdata + slength)
1145*593dc095SDavid du Colombier {
1146*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1147*593dc095SDavid du Colombier png_warning(png_ptr, "malformed sPLT chunk");
1148*593dc095SDavid du Colombier return;
1149*593dc095SDavid du Colombier }
1150*593dc095SDavid du Colombier
1151*593dc095SDavid du Colombier new_palette.depth = *entry_start++;
1152*593dc095SDavid du Colombier entry_size = (new_palette.depth == 8 ? 6 : 10);
1153*593dc095SDavid du Colombier data_length = (slength - (entry_start - chunkdata));
1154*593dc095SDavid du Colombier
1155*593dc095SDavid du Colombier /* integrity-check the data length */
1156*593dc095SDavid du Colombier if (data_length % entry_size)
1157*593dc095SDavid du Colombier {
1158*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1159*593dc095SDavid du Colombier png_warning(png_ptr, "sPLT chunk has bad length");
1160*593dc095SDavid du Colombier return;
1161*593dc095SDavid du Colombier }
1162*593dc095SDavid du Colombier
1163*593dc095SDavid du Colombier new_palette.nentries = (png_uint_32) (data_length / entry_size);
1164*593dc095SDavid du Colombier if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
1165*593dc095SDavid du Colombier png_sizeof(png_sPLT_entry)))
1166*593dc095SDavid du Colombier {
1167*593dc095SDavid du Colombier png_warning(png_ptr, "sPLT chunk too long");
1168*593dc095SDavid du Colombier return;
1169*593dc095SDavid du Colombier }
1170*593dc095SDavid du Colombier new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1171*593dc095SDavid du Colombier png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1172*593dc095SDavid du Colombier if (new_palette.entries == NULL)
1173*593dc095SDavid du Colombier {
1174*593dc095SDavid du Colombier png_warning(png_ptr, "sPLT chunk requires too much memory");
1175*593dc095SDavid du Colombier return;
1176*593dc095SDavid du Colombier }
1177*593dc095SDavid du Colombier
1178*593dc095SDavid du Colombier #ifndef PNG_NO_POINTER_INDEXING
1179*593dc095SDavid du Colombier for (i = 0; i < new_palette.nentries; i++)
1180*593dc095SDavid du Colombier {
1181*593dc095SDavid du Colombier png_sPLT_entryp pp = new_palette.entries + i;
1182*593dc095SDavid du Colombier
1183*593dc095SDavid du Colombier if (new_palette.depth == 8)
1184*593dc095SDavid du Colombier {
1185*593dc095SDavid du Colombier pp->red = *entry_start++;
1186*593dc095SDavid du Colombier pp->green = *entry_start++;
1187*593dc095SDavid du Colombier pp->blue = *entry_start++;
1188*593dc095SDavid du Colombier pp->alpha = *entry_start++;
1189*593dc095SDavid du Colombier }
1190*593dc095SDavid du Colombier else
1191*593dc095SDavid du Colombier {
1192*593dc095SDavid du Colombier pp->red = png_get_uint_16(entry_start); entry_start += 2;
1193*593dc095SDavid du Colombier pp->green = png_get_uint_16(entry_start); entry_start += 2;
1194*593dc095SDavid du Colombier pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1195*593dc095SDavid du Colombier pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1196*593dc095SDavid du Colombier }
1197*593dc095SDavid du Colombier pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1198*593dc095SDavid du Colombier }
1199*593dc095SDavid du Colombier #else
1200*593dc095SDavid du Colombier pp = new_palette.entries;
1201*593dc095SDavid du Colombier for (i = 0; i < new_palette.nentries; i++)
1202*593dc095SDavid du Colombier {
1203*593dc095SDavid du Colombier
1204*593dc095SDavid du Colombier if (new_palette.depth == 8)
1205*593dc095SDavid du Colombier {
1206*593dc095SDavid du Colombier pp[i].red = *entry_start++;
1207*593dc095SDavid du Colombier pp[i].green = *entry_start++;
1208*593dc095SDavid du Colombier pp[i].blue = *entry_start++;
1209*593dc095SDavid du Colombier pp[i].alpha = *entry_start++;
1210*593dc095SDavid du Colombier }
1211*593dc095SDavid du Colombier else
1212*593dc095SDavid du Colombier {
1213*593dc095SDavid du Colombier pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1214*593dc095SDavid du Colombier pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1215*593dc095SDavid du Colombier pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1216*593dc095SDavid du Colombier pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1217*593dc095SDavid du Colombier }
1218*593dc095SDavid du Colombier pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1219*593dc095SDavid du Colombier }
1220*593dc095SDavid du Colombier #endif
1221*593dc095SDavid du Colombier
1222*593dc095SDavid du Colombier /* discard all chunk data except the name and stash that */
1223*593dc095SDavid du Colombier new_palette.name = (png_charp)chunkdata;
1224*593dc095SDavid du Colombier
1225*593dc095SDavid du Colombier png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1226*593dc095SDavid du Colombier
1227*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
1228*593dc095SDavid du Colombier png_free(png_ptr, new_palette.entries);
1229*593dc095SDavid du Colombier }
1230*593dc095SDavid du Colombier #endif /* PNG_READ_sPLT_SUPPORTED */
1231*593dc095SDavid du Colombier
12327dd7cddfSDavid du Colombier #if defined(PNG_READ_tRNS_SUPPORTED)
1233*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_tRNS(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)12347dd7cddfSDavid du Colombier png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
12357dd7cddfSDavid du Colombier {
1236*593dc095SDavid du Colombier png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1237*593dc095SDavid du Colombier
12387dd7cddfSDavid du Colombier png_debug(1, "in png_handle_tRNS\n");
12397dd7cddfSDavid du Colombier
12407dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
12417dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before tRNS");
12427dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
12437dd7cddfSDavid du Colombier {
12447dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid tRNS after IDAT");
12457dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
12467dd7cddfSDavid du Colombier return;
12477dd7cddfSDavid du Colombier }
1248*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
12497dd7cddfSDavid du Colombier {
1250*593dc095SDavid du Colombier png_warning(png_ptr, "Duplicate tRNS chunk");
12517dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
12527dd7cddfSDavid du Colombier return;
12537dd7cddfSDavid du Colombier }
12547dd7cddfSDavid du Colombier
1255*593dc095SDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
12567dd7cddfSDavid du Colombier {
1257*593dc095SDavid du Colombier png_byte buf[2];
12587dd7cddfSDavid du Colombier
12597dd7cddfSDavid du Colombier if (length != 2)
12607dd7cddfSDavid du Colombier {
12617dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect tRNS chunk length");
12627dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
12637dd7cddfSDavid du Colombier return;
12647dd7cddfSDavid du Colombier }
12657dd7cddfSDavid du Colombier
12667dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 2);
12677dd7cddfSDavid du Colombier png_ptr->num_trans = 1;
12687dd7cddfSDavid du Colombier png_ptr->trans_values.gray = png_get_uint_16(buf);
12697dd7cddfSDavid du Colombier }
1270*593dc095SDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1271*593dc095SDavid du Colombier {
1272*593dc095SDavid du Colombier png_byte buf[6];
1273*593dc095SDavid du Colombier
1274*593dc095SDavid du Colombier if (length != 6)
1275*593dc095SDavid du Colombier {
1276*593dc095SDavid du Colombier png_warning(png_ptr, "Incorrect tRNS chunk length");
1277*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1278*593dc095SDavid du Colombier return;
1279*593dc095SDavid du Colombier }
1280*593dc095SDavid du Colombier png_crc_read(png_ptr, buf, (png_size_t)length);
1281*593dc095SDavid du Colombier png_ptr->num_trans = 1;
1282*593dc095SDavid du Colombier png_ptr->trans_values.red = png_get_uint_16(buf);
1283*593dc095SDavid du Colombier png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1284*593dc095SDavid du Colombier png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1285*593dc095SDavid du Colombier }
1286*593dc095SDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1287*593dc095SDavid du Colombier {
1288*593dc095SDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_PLTE))
1289*593dc095SDavid du Colombier {
1290*593dc095SDavid du Colombier /* Should be an error, but we can cope with it. */
1291*593dc095SDavid du Colombier png_warning(png_ptr, "Missing PLTE before tRNS");
1292*593dc095SDavid du Colombier }
1293*593dc095SDavid du Colombier if (length > (png_uint_32)png_ptr->num_palette ||
1294*593dc095SDavid du Colombier length > PNG_MAX_PALETTE_LENGTH)
1295*593dc095SDavid du Colombier {
1296*593dc095SDavid du Colombier png_warning(png_ptr, "Incorrect tRNS chunk length");
1297*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1298*593dc095SDavid du Colombier return;
1299*593dc095SDavid du Colombier }
1300*593dc095SDavid du Colombier if (length == 0)
1301*593dc095SDavid du Colombier {
1302*593dc095SDavid du Colombier png_warning(png_ptr, "Zero length tRNS chunk");
1303*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1304*593dc095SDavid du Colombier return;
1305*593dc095SDavid du Colombier }
1306*593dc095SDavid du Colombier png_crc_read(png_ptr, readbuf, (png_size_t)length);
1307*593dc095SDavid du Colombier png_ptr->num_trans = (png_uint_16)length;
1308*593dc095SDavid du Colombier }
13097dd7cddfSDavid du Colombier else
13107dd7cddfSDavid du Colombier {
13117dd7cddfSDavid du Colombier png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
13127dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
13137dd7cddfSDavid du Colombier return;
13147dd7cddfSDavid du Colombier }
13157dd7cddfSDavid du Colombier
13167dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
13177dd7cddfSDavid du Colombier return;
13187dd7cddfSDavid du Colombier
1319*593dc095SDavid du Colombier png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
13207dd7cddfSDavid du Colombier &(png_ptr->trans_values));
13217dd7cddfSDavid du Colombier }
13227dd7cddfSDavid du Colombier #endif
13237dd7cddfSDavid du Colombier
13247dd7cddfSDavid du Colombier #if defined(PNG_READ_bKGD_SUPPORTED)
1325*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_bKGD(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)13267dd7cddfSDavid du Colombier png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
13277dd7cddfSDavid du Colombier {
13287dd7cddfSDavid du Colombier png_size_t truelen;
13297dd7cddfSDavid du Colombier png_byte buf[6];
13307dd7cddfSDavid du Colombier
13317dd7cddfSDavid du Colombier png_debug(1, "in png_handle_bKGD\n");
13327dd7cddfSDavid du Colombier
13337dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
13347dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before bKGD");
13357dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
13367dd7cddfSDavid du Colombier {
13377dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid bKGD after IDAT");
13387dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
13397dd7cddfSDavid du Colombier return;
13407dd7cddfSDavid du Colombier }
13417dd7cddfSDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
13427dd7cddfSDavid du Colombier !(png_ptr->mode & PNG_HAVE_PLTE))
13437dd7cddfSDavid du Colombier {
13447dd7cddfSDavid du Colombier png_warning(png_ptr, "Missing PLTE before bKGD");
13457dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
13467dd7cddfSDavid du Colombier return;
13477dd7cddfSDavid du Colombier }
1348*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
13497dd7cddfSDavid du Colombier {
13507dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate bKGD chunk");
13517dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
13527dd7cddfSDavid du Colombier return;
13537dd7cddfSDavid du Colombier }
13547dd7cddfSDavid du Colombier
13557dd7cddfSDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
13567dd7cddfSDavid du Colombier truelen = 1;
13577dd7cddfSDavid du Colombier else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
13587dd7cddfSDavid du Colombier truelen = 6;
13597dd7cddfSDavid du Colombier else
13607dd7cddfSDavid du Colombier truelen = 2;
13617dd7cddfSDavid du Colombier
13627dd7cddfSDavid du Colombier if (length != truelen)
13637dd7cddfSDavid du Colombier {
13647dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect bKGD chunk length");
13657dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
13667dd7cddfSDavid du Colombier return;
13677dd7cddfSDavid du Colombier }
13687dd7cddfSDavid du Colombier
13697dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, truelen);
13707dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
13717dd7cddfSDavid du Colombier return;
13727dd7cddfSDavid du Colombier
13737dd7cddfSDavid du Colombier /* We convert the index value into RGB components so that we can allow
13747dd7cddfSDavid du Colombier * arbitrary RGB values for background when we have transparency, and
13757dd7cddfSDavid du Colombier * so it is easy to determine the RGB values of the background color
13767dd7cddfSDavid du Colombier * from the info_ptr struct. */
13777dd7cddfSDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
13787dd7cddfSDavid du Colombier {
13797dd7cddfSDavid du Colombier png_ptr->background.index = buf[0];
1380*593dc095SDavid du Colombier if(info_ptr->num_palette)
1381*593dc095SDavid du Colombier {
1382*593dc095SDavid du Colombier if(buf[0] > info_ptr->num_palette)
1383*593dc095SDavid du Colombier {
1384*593dc095SDavid du Colombier png_warning(png_ptr, "Incorrect bKGD chunk index value");
1385*593dc095SDavid du Colombier return;
1386*593dc095SDavid du Colombier }
1387*593dc095SDavid du Colombier png_ptr->background.red =
1388*593dc095SDavid du Colombier (png_uint_16)png_ptr->palette[buf[0]].red;
1389*593dc095SDavid du Colombier png_ptr->background.green =
1390*593dc095SDavid du Colombier (png_uint_16)png_ptr->palette[buf[0]].green;
1391*593dc095SDavid du Colombier png_ptr->background.blue =
1392*593dc095SDavid du Colombier (png_uint_16)png_ptr->palette[buf[0]].blue;
1393*593dc095SDavid du Colombier }
13947dd7cddfSDavid du Colombier }
13957dd7cddfSDavid du Colombier else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
13967dd7cddfSDavid du Colombier {
13977dd7cddfSDavid du Colombier png_ptr->background.red =
13987dd7cddfSDavid du Colombier png_ptr->background.green =
13997dd7cddfSDavid du Colombier png_ptr->background.blue =
14007dd7cddfSDavid du Colombier png_ptr->background.gray = png_get_uint_16(buf);
14017dd7cddfSDavid du Colombier }
14027dd7cddfSDavid du Colombier else
14037dd7cddfSDavid du Colombier {
14047dd7cddfSDavid du Colombier png_ptr->background.red = png_get_uint_16(buf);
14057dd7cddfSDavid du Colombier png_ptr->background.green = png_get_uint_16(buf + 2);
14067dd7cddfSDavid du Colombier png_ptr->background.blue = png_get_uint_16(buf + 4);
14077dd7cddfSDavid du Colombier }
14087dd7cddfSDavid du Colombier
14097dd7cddfSDavid du Colombier png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
14107dd7cddfSDavid du Colombier }
14117dd7cddfSDavid du Colombier #endif
14127dd7cddfSDavid du Colombier
14137dd7cddfSDavid du Colombier #if defined(PNG_READ_hIST_SUPPORTED)
1414*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_hIST(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)14157dd7cddfSDavid du Colombier png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
14167dd7cddfSDavid du Colombier {
1417*593dc095SDavid du Colombier unsigned int num, i;
1418*593dc095SDavid du Colombier png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
14197dd7cddfSDavid du Colombier
14207dd7cddfSDavid du Colombier png_debug(1, "in png_handle_hIST\n");
14217dd7cddfSDavid du Colombier
14227dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
14237dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before hIST");
14247dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
14257dd7cddfSDavid du Colombier {
14267dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid hIST after IDAT");
14277dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14287dd7cddfSDavid du Colombier return;
14297dd7cddfSDavid du Colombier }
14307dd7cddfSDavid du Colombier else if (!(png_ptr->mode & PNG_HAVE_PLTE))
14317dd7cddfSDavid du Colombier {
14327dd7cddfSDavid du Colombier png_warning(png_ptr, "Missing PLTE before hIST");
14337dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14347dd7cddfSDavid du Colombier return;
14357dd7cddfSDavid du Colombier }
1436*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
14377dd7cddfSDavid du Colombier {
14387dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate hIST chunk");
14397dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14407dd7cddfSDavid du Colombier return;
14417dd7cddfSDavid du Colombier }
14427dd7cddfSDavid du Colombier
1443*593dc095SDavid du Colombier num = length / 2 ;
1444*593dc095SDavid du Colombier if (num != (unsigned int) png_ptr->num_palette || num >
1445*593dc095SDavid du Colombier (unsigned int) PNG_MAX_PALETTE_LENGTH)
14467dd7cddfSDavid du Colombier {
14477dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect hIST chunk length");
14487dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14497dd7cddfSDavid du Colombier return;
14507dd7cddfSDavid du Colombier }
14517dd7cddfSDavid du Colombier
14527dd7cddfSDavid du Colombier for (i = 0; i < num; i++)
14537dd7cddfSDavid du Colombier {
14547dd7cddfSDavid du Colombier png_byte buf[2];
14557dd7cddfSDavid du Colombier
14567dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 2);
1457*593dc095SDavid du Colombier readbuf[i] = png_get_uint_16(buf);
14587dd7cddfSDavid du Colombier }
14597dd7cddfSDavid du Colombier
14607dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
14617dd7cddfSDavid du Colombier return;
14627dd7cddfSDavid du Colombier
1463*593dc095SDavid du Colombier png_set_hIST(png_ptr, info_ptr, readbuf);
14647dd7cddfSDavid du Colombier }
14657dd7cddfSDavid du Colombier #endif
14667dd7cddfSDavid du Colombier
14677dd7cddfSDavid du Colombier #if defined(PNG_READ_pHYs_SUPPORTED)
1468*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_pHYs(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)14697dd7cddfSDavid du Colombier png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
14707dd7cddfSDavid du Colombier {
14717dd7cddfSDavid du Colombier png_byte buf[9];
14727dd7cddfSDavid du Colombier png_uint_32 res_x, res_y;
14737dd7cddfSDavid du Colombier int unit_type;
14747dd7cddfSDavid du Colombier
14757dd7cddfSDavid du Colombier png_debug(1, "in png_handle_pHYs\n");
14767dd7cddfSDavid du Colombier
14777dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
1478*593dc095SDavid du Colombier png_error(png_ptr, "Missing IHDR before pHYs");
14797dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
14807dd7cddfSDavid du Colombier {
1481*593dc095SDavid du Colombier png_warning(png_ptr, "Invalid pHYs after IDAT");
14827dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14837dd7cddfSDavid du Colombier return;
14847dd7cddfSDavid du Colombier }
1485*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
14867dd7cddfSDavid du Colombier {
1487*593dc095SDavid du Colombier png_warning(png_ptr, "Duplicate pHYs chunk");
14887dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14897dd7cddfSDavid du Colombier return;
14907dd7cddfSDavid du Colombier }
14917dd7cddfSDavid du Colombier
14927dd7cddfSDavid du Colombier if (length != 9)
14937dd7cddfSDavid du Colombier {
14947dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect pHYs chunk length");
14957dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
14967dd7cddfSDavid du Colombier return;
14977dd7cddfSDavid du Colombier }
14987dd7cddfSDavid du Colombier
14997dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 9);
15007dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
15017dd7cddfSDavid du Colombier return;
15027dd7cddfSDavid du Colombier
15037dd7cddfSDavid du Colombier res_x = png_get_uint_32(buf);
15047dd7cddfSDavid du Colombier res_y = png_get_uint_32(buf + 4);
15057dd7cddfSDavid du Colombier unit_type = buf[8];
15067dd7cddfSDavid du Colombier png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
15077dd7cddfSDavid du Colombier }
15087dd7cddfSDavid du Colombier #endif
15097dd7cddfSDavid du Colombier
15107dd7cddfSDavid du Colombier #if defined(PNG_READ_oFFs_SUPPORTED)
1511*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_oFFs(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)15127dd7cddfSDavid du Colombier png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
15137dd7cddfSDavid du Colombier {
15147dd7cddfSDavid du Colombier png_byte buf[9];
1515*593dc095SDavid du Colombier png_int_32 offset_x, offset_y;
15167dd7cddfSDavid du Colombier int unit_type;
15177dd7cddfSDavid du Colombier
15187dd7cddfSDavid du Colombier png_debug(1, "in png_handle_oFFs\n");
15197dd7cddfSDavid du Colombier
15207dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
15217dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before oFFs");
15227dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
15237dd7cddfSDavid du Colombier {
15247dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid oFFs after IDAT");
15257dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
15267dd7cddfSDavid du Colombier return;
15277dd7cddfSDavid du Colombier }
1528*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
15297dd7cddfSDavid du Colombier {
15307dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate oFFs chunk");
15317dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
15327dd7cddfSDavid du Colombier return;
15337dd7cddfSDavid du Colombier }
15347dd7cddfSDavid du Colombier
15357dd7cddfSDavid du Colombier if (length != 9)
15367dd7cddfSDavid du Colombier {
15377dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect oFFs chunk length");
15387dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
15397dd7cddfSDavid du Colombier return;
15407dd7cddfSDavid du Colombier }
15417dd7cddfSDavid du Colombier
15427dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 9);
15437dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
15447dd7cddfSDavid du Colombier return;
15457dd7cddfSDavid du Colombier
1546*593dc095SDavid du Colombier offset_x = png_get_int_32(buf);
1547*593dc095SDavid du Colombier offset_y = png_get_int_32(buf + 4);
15487dd7cddfSDavid du Colombier unit_type = buf[8];
15497dd7cddfSDavid du Colombier png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
15507dd7cddfSDavid du Colombier }
15517dd7cddfSDavid du Colombier #endif
15527dd7cddfSDavid du Colombier
15537dd7cddfSDavid du Colombier #if defined(PNG_READ_pCAL_SUPPORTED)
1554*593dc095SDavid du Colombier /* read the pCAL chunk (described in the PNG Extensions document) */
1555*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_pCAL(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)15567dd7cddfSDavid du Colombier png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
15577dd7cddfSDavid du Colombier {
15587dd7cddfSDavid du Colombier png_charp purpose;
15597dd7cddfSDavid du Colombier png_int_32 X0, X1;
15607dd7cddfSDavid du Colombier png_byte type, nparams;
15617dd7cddfSDavid du Colombier png_charp buf, units, endptr;
15627dd7cddfSDavid du Colombier png_charpp params;
1563*593dc095SDavid du Colombier png_size_t slength;
15647dd7cddfSDavid du Colombier int i;
15657dd7cddfSDavid du Colombier
15667dd7cddfSDavid du Colombier png_debug(1, "in png_handle_pCAL\n");
15677dd7cddfSDavid du Colombier
15687dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
15697dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before pCAL");
15707dd7cddfSDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
15717dd7cddfSDavid du Colombier {
15727dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid pCAL after IDAT");
15737dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
15747dd7cddfSDavid du Colombier return;
15757dd7cddfSDavid du Colombier }
1576*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
15777dd7cddfSDavid du Colombier {
15787dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate pCAL chunk");
15797dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
15807dd7cddfSDavid du Colombier return;
15817dd7cddfSDavid du Colombier }
15827dd7cddfSDavid du Colombier
1583*593dc095SDavid du Colombier png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
15847dd7cddfSDavid du Colombier length + 1);
1585*593dc095SDavid du Colombier purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
1586*593dc095SDavid du Colombier if (purpose == NULL)
1587*593dc095SDavid du Colombier {
1588*593dc095SDavid du Colombier png_warning(png_ptr, "No memory for pCAL purpose.");
1589*593dc095SDavid du Colombier return;
1590*593dc095SDavid du Colombier }
1591*593dc095SDavid du Colombier slength = (png_size_t)length;
1592*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)purpose, slength);
15937dd7cddfSDavid du Colombier
15947dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
15957dd7cddfSDavid du Colombier {
15967dd7cddfSDavid du Colombier png_free(png_ptr, purpose);
15977dd7cddfSDavid du Colombier return;
15987dd7cddfSDavid du Colombier }
15997dd7cddfSDavid du Colombier
1600*593dc095SDavid du Colombier purpose[slength] = 0x00; /* null terminate the last string */
16017dd7cddfSDavid du Colombier
16027dd7cddfSDavid du Colombier png_debug(3, "Finding end of pCAL purpose string\n");
1603*593dc095SDavid du Colombier for (buf = purpose; *buf; buf++)
16047dd7cddfSDavid du Colombier /* empty loop */ ;
16057dd7cddfSDavid du Colombier
1606*593dc095SDavid du Colombier endptr = purpose + slength;
16077dd7cddfSDavid du Colombier
16087dd7cddfSDavid du Colombier /* We need to have at least 12 bytes after the purpose string
16097dd7cddfSDavid du Colombier in order to get the parameter information. */
16107dd7cddfSDavid du Colombier if (endptr <= buf + 12)
16117dd7cddfSDavid du Colombier {
16127dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid pCAL data");
16137dd7cddfSDavid du Colombier png_free(png_ptr, purpose);
16147dd7cddfSDavid du Colombier return;
16157dd7cddfSDavid du Colombier }
16167dd7cddfSDavid du Colombier
16177dd7cddfSDavid du Colombier png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
16187dd7cddfSDavid du Colombier X0 = png_get_int_32((png_bytep)buf+1);
16197dd7cddfSDavid du Colombier X1 = png_get_int_32((png_bytep)buf+5);
16207dd7cddfSDavid du Colombier type = buf[9];
16217dd7cddfSDavid du Colombier nparams = buf[10];
16227dd7cddfSDavid du Colombier units = buf + 11;
16237dd7cddfSDavid du Colombier
16247dd7cddfSDavid du Colombier png_debug(3, "Checking pCAL equation type and number of parameters\n");
16257dd7cddfSDavid du Colombier /* Check that we have the right number of parameters for known
16267dd7cddfSDavid du Colombier equation types. */
16277dd7cddfSDavid du Colombier if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
16287dd7cddfSDavid du Colombier (type == PNG_EQUATION_BASE_E && nparams != 3) ||
16297dd7cddfSDavid du Colombier (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
16307dd7cddfSDavid du Colombier (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
16317dd7cddfSDavid du Colombier {
16327dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid pCAL parameters for equation type");
16337dd7cddfSDavid du Colombier png_free(png_ptr, purpose);
16347dd7cddfSDavid du Colombier return;
16357dd7cddfSDavid du Colombier }
16367dd7cddfSDavid du Colombier else if (type >= PNG_EQUATION_LAST)
16377dd7cddfSDavid du Colombier {
16387dd7cddfSDavid du Colombier png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
16397dd7cddfSDavid du Colombier }
16407dd7cddfSDavid du Colombier
1641*593dc095SDavid du Colombier for (buf = units; *buf; buf++)
1642*593dc095SDavid du Colombier /* Empty loop to move past the units string. */ ;
16437dd7cddfSDavid du Colombier
16447dd7cddfSDavid du Colombier png_debug(3, "Allocating pCAL parameters array\n");
1645*593dc095SDavid du Colombier params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
1646*593dc095SDavid du Colombier *png_sizeof(png_charp))) ;
1647*593dc095SDavid du Colombier if (params == NULL)
1648*593dc095SDavid du Colombier {
1649*593dc095SDavid du Colombier png_free(png_ptr, purpose);
1650*593dc095SDavid du Colombier png_warning(png_ptr, "No memory for pCAL params.");
1651*593dc095SDavid du Colombier return;
1652*593dc095SDavid du Colombier }
16537dd7cddfSDavid du Colombier
16547dd7cddfSDavid du Colombier /* Get pointers to the start of each parameter string. */
16557dd7cddfSDavid du Colombier for (i = 0; i < (int)nparams; i++)
16567dd7cddfSDavid du Colombier {
16577dd7cddfSDavid du Colombier buf++; /* Skip the null string terminator from previous parameter. */
16587dd7cddfSDavid du Colombier
16597dd7cddfSDavid du Colombier png_debug1(3, "Reading pCAL parameter %d\n", i);
1660*593dc095SDavid du Colombier for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1661*593dc095SDavid du Colombier /* Empty loop to move past each parameter string */ ;
16627dd7cddfSDavid du Colombier
16637dd7cddfSDavid du Colombier /* Make sure we haven't run out of data yet */
16647dd7cddfSDavid du Colombier if (buf > endptr)
16657dd7cddfSDavid du Colombier {
16667dd7cddfSDavid du Colombier png_warning(png_ptr, "Invalid pCAL data");
16677dd7cddfSDavid du Colombier png_free(png_ptr, purpose);
16687dd7cddfSDavid du Colombier png_free(png_ptr, params);
16697dd7cddfSDavid du Colombier return;
16707dd7cddfSDavid du Colombier }
16717dd7cddfSDavid du Colombier }
16727dd7cddfSDavid du Colombier
16737dd7cddfSDavid du Colombier png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
16747dd7cddfSDavid du Colombier units, params);
16757dd7cddfSDavid du Colombier
16767dd7cddfSDavid du Colombier png_free(png_ptr, purpose);
16777dd7cddfSDavid du Colombier png_free(png_ptr, params);
16787dd7cddfSDavid du Colombier }
16797dd7cddfSDavid du Colombier #endif
16807dd7cddfSDavid du Colombier
1681*593dc095SDavid du Colombier #if defined(PNG_READ_sCAL_SUPPORTED)
1682*593dc095SDavid du Colombier /* read the sCAL chunk */
1683*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_sCAL(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1684*593dc095SDavid du Colombier png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1685*593dc095SDavid du Colombier {
1686*593dc095SDavid du Colombier png_charp buffer, ep;
1687*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
1688*593dc095SDavid du Colombier double width, height;
1689*593dc095SDavid du Colombier png_charp vp;
1690*593dc095SDavid du Colombier #else
1691*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
1692*593dc095SDavid du Colombier png_charp swidth, sheight;
1693*593dc095SDavid du Colombier #endif
1694*593dc095SDavid du Colombier #endif
1695*593dc095SDavid du Colombier png_size_t slength;
1696*593dc095SDavid du Colombier
1697*593dc095SDavid du Colombier png_debug(1, "in png_handle_sCAL\n");
1698*593dc095SDavid du Colombier
1699*593dc095SDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
1700*593dc095SDavid du Colombier png_error(png_ptr, "Missing IHDR before sCAL");
1701*593dc095SDavid du Colombier else if (png_ptr->mode & PNG_HAVE_IDAT)
1702*593dc095SDavid du Colombier {
1703*593dc095SDavid du Colombier png_warning(png_ptr, "Invalid sCAL after IDAT");
1704*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1705*593dc095SDavid du Colombier return;
1706*593dc095SDavid du Colombier }
1707*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1708*593dc095SDavid du Colombier {
1709*593dc095SDavid du Colombier png_warning(png_ptr, "Duplicate sCAL chunk");
1710*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
1711*593dc095SDavid du Colombier return;
1712*593dc095SDavid du Colombier }
1713*593dc095SDavid du Colombier
1714*593dc095SDavid du Colombier png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1715*593dc095SDavid du Colombier length + 1);
1716*593dc095SDavid du Colombier buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
1717*593dc095SDavid du Colombier if (buffer == NULL)
1718*593dc095SDavid du Colombier {
1719*593dc095SDavid du Colombier png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1720*593dc095SDavid du Colombier return;
1721*593dc095SDavid du Colombier }
1722*593dc095SDavid du Colombier slength = (png_size_t)length;
1723*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)buffer, slength);
1724*593dc095SDavid du Colombier
1725*593dc095SDavid du Colombier if (png_crc_finish(png_ptr, 0))
1726*593dc095SDavid du Colombier {
1727*593dc095SDavid du Colombier png_free(png_ptr, buffer);
1728*593dc095SDavid du Colombier return;
1729*593dc095SDavid du Colombier }
1730*593dc095SDavid du Colombier
1731*593dc095SDavid du Colombier buffer[slength] = 0x00; /* null terminate the last string */
1732*593dc095SDavid du Colombier
1733*593dc095SDavid du Colombier ep = buffer + 1; /* skip unit byte */
1734*593dc095SDavid du Colombier
1735*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
1736*593dc095SDavid du Colombier width = strtod(ep, &vp);
1737*593dc095SDavid du Colombier if (*vp)
1738*593dc095SDavid du Colombier {
1739*593dc095SDavid du Colombier png_warning(png_ptr, "malformed width string in sCAL chunk");
1740*593dc095SDavid du Colombier return;
1741*593dc095SDavid du Colombier }
1742*593dc095SDavid du Colombier #else
1743*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
1744*593dc095SDavid du Colombier swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1745*593dc095SDavid du Colombier if (swidth == NULL)
1746*593dc095SDavid du Colombier {
1747*593dc095SDavid du Colombier png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1748*593dc095SDavid du Colombier return;
1749*593dc095SDavid du Colombier }
1750*593dc095SDavid du Colombier png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1751*593dc095SDavid du Colombier #endif
1752*593dc095SDavid du Colombier #endif
1753*593dc095SDavid du Colombier
1754*593dc095SDavid du Colombier for (ep = buffer; *ep; ep++)
1755*593dc095SDavid du Colombier /* empty loop */ ;
1756*593dc095SDavid du Colombier ep++;
1757*593dc095SDavid du Colombier
1758*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
1759*593dc095SDavid du Colombier height = strtod(ep, &vp);
1760*593dc095SDavid du Colombier if (*vp)
1761*593dc095SDavid du Colombier {
1762*593dc095SDavid du Colombier png_warning(png_ptr, "malformed height string in sCAL chunk");
1763*593dc095SDavid du Colombier return;
1764*593dc095SDavid du Colombier }
1765*593dc095SDavid du Colombier #else
1766*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
1767*593dc095SDavid du Colombier sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1768*593dc095SDavid du Colombier if (swidth == NULL)
1769*593dc095SDavid du Colombier {
1770*593dc095SDavid du Colombier png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1771*593dc095SDavid du Colombier return;
1772*593dc095SDavid du Colombier }
1773*593dc095SDavid du Colombier png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1774*593dc095SDavid du Colombier #endif
1775*593dc095SDavid du Colombier #endif
1776*593dc095SDavid du Colombier
1777*593dc095SDavid du Colombier if (buffer + slength < ep
1778*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
1779*593dc095SDavid du Colombier || width <= 0. || height <= 0.
1780*593dc095SDavid du Colombier #endif
1781*593dc095SDavid du Colombier )
1782*593dc095SDavid du Colombier {
1783*593dc095SDavid du Colombier png_warning(png_ptr, "Invalid sCAL data");
1784*593dc095SDavid du Colombier png_free(png_ptr, buffer);
1785*593dc095SDavid du Colombier #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1786*593dc095SDavid du Colombier png_free(png_ptr, swidth);
1787*593dc095SDavid du Colombier png_free(png_ptr, sheight);
1788*593dc095SDavid du Colombier #endif
1789*593dc095SDavid du Colombier return;
1790*593dc095SDavid du Colombier }
1791*593dc095SDavid du Colombier
1792*593dc095SDavid du Colombier
1793*593dc095SDavid du Colombier #ifdef PNG_FLOATING_POINT_SUPPORTED
1794*593dc095SDavid du Colombier png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1795*593dc095SDavid du Colombier #else
1796*593dc095SDavid du Colombier #ifdef PNG_FIXED_POINT_SUPPORTED
1797*593dc095SDavid du Colombier png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1798*593dc095SDavid du Colombier #endif
1799*593dc095SDavid du Colombier #endif
1800*593dc095SDavid du Colombier
1801*593dc095SDavid du Colombier png_free(png_ptr, buffer);
1802*593dc095SDavid du Colombier #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1803*593dc095SDavid du Colombier png_free(png_ptr, swidth);
1804*593dc095SDavid du Colombier png_free(png_ptr, sheight);
1805*593dc095SDavid du Colombier #endif
1806*593dc095SDavid du Colombier }
1807*593dc095SDavid du Colombier #endif
1808*593dc095SDavid du Colombier
18097dd7cddfSDavid du Colombier #if defined(PNG_READ_tIME_SUPPORTED)
1810*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_tIME(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)18117dd7cddfSDavid du Colombier png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
18127dd7cddfSDavid du Colombier {
18137dd7cddfSDavid du Colombier png_byte buf[7];
18147dd7cddfSDavid du Colombier png_time mod_time;
18157dd7cddfSDavid du Colombier
18167dd7cddfSDavid du Colombier png_debug(1, "in png_handle_tIME\n");
18177dd7cddfSDavid du Colombier
18187dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
18197dd7cddfSDavid du Colombier png_error(png_ptr, "Out of place tIME chunk");
1820*593dc095SDavid du Colombier else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
18217dd7cddfSDavid du Colombier {
18227dd7cddfSDavid du Colombier png_warning(png_ptr, "Duplicate tIME chunk");
18237dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
18247dd7cddfSDavid du Colombier return;
18257dd7cddfSDavid du Colombier }
18267dd7cddfSDavid du Colombier
18277dd7cddfSDavid du Colombier if (png_ptr->mode & PNG_HAVE_IDAT)
18287dd7cddfSDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
18297dd7cddfSDavid du Colombier
18307dd7cddfSDavid du Colombier if (length != 7)
18317dd7cddfSDavid du Colombier {
18327dd7cddfSDavid du Colombier png_warning(png_ptr, "Incorrect tIME chunk length");
18337dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
18347dd7cddfSDavid du Colombier return;
18357dd7cddfSDavid du Colombier }
18367dd7cddfSDavid du Colombier
18377dd7cddfSDavid du Colombier png_crc_read(png_ptr, buf, 7);
18387dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
18397dd7cddfSDavid du Colombier return;
18407dd7cddfSDavid du Colombier
18417dd7cddfSDavid du Colombier mod_time.second = buf[6];
18427dd7cddfSDavid du Colombier mod_time.minute = buf[5];
18437dd7cddfSDavid du Colombier mod_time.hour = buf[4];
18447dd7cddfSDavid du Colombier mod_time.day = buf[3];
18457dd7cddfSDavid du Colombier mod_time.month = buf[2];
18467dd7cddfSDavid du Colombier mod_time.year = png_get_uint_16(buf);
18477dd7cddfSDavid du Colombier
18487dd7cddfSDavid du Colombier png_set_tIME(png_ptr, info_ptr, &mod_time);
18497dd7cddfSDavid du Colombier }
18507dd7cddfSDavid du Colombier #endif
18517dd7cddfSDavid du Colombier
18527dd7cddfSDavid du Colombier #if defined(PNG_READ_tEXt_SUPPORTED)
18537dd7cddfSDavid du Colombier /* Note: this does not properly handle chunks that are > 64K under DOS */
1854*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_tEXt(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)18557dd7cddfSDavid du Colombier png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
18567dd7cddfSDavid du Colombier {
18577dd7cddfSDavid du Colombier png_textp text_ptr;
18587dd7cddfSDavid du Colombier png_charp key;
18597dd7cddfSDavid du Colombier png_charp text;
18607dd7cddfSDavid du Colombier png_uint_32 skip = 0;
1861*593dc095SDavid du Colombier png_size_t slength;
1862*593dc095SDavid du Colombier int ret;
18637dd7cddfSDavid du Colombier
18647dd7cddfSDavid du Colombier png_debug(1, "in png_handle_tEXt\n");
18657dd7cddfSDavid du Colombier
18667dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
18677dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before tEXt");
18687dd7cddfSDavid du Colombier
18697dd7cddfSDavid du Colombier if (png_ptr->mode & PNG_HAVE_IDAT)
18707dd7cddfSDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
18717dd7cddfSDavid du Colombier
18727dd7cddfSDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
18737dd7cddfSDavid du Colombier if (length > (png_uint_32)65535L)
18747dd7cddfSDavid du Colombier {
18757dd7cddfSDavid du Colombier png_warning(png_ptr, "tEXt chunk too large to fit in memory");
18767dd7cddfSDavid du Colombier skip = length - (png_uint_32)65535L;
18777dd7cddfSDavid du Colombier length = (png_uint_32)65535L;
18787dd7cddfSDavid du Colombier }
18797dd7cddfSDavid du Colombier #endif
18807dd7cddfSDavid du Colombier
1881*593dc095SDavid du Colombier key = (png_charp)png_malloc_warn(png_ptr, length + 1);
1882*593dc095SDavid du Colombier if (key == NULL)
1883*593dc095SDavid du Colombier {
1884*593dc095SDavid du Colombier png_warning(png_ptr, "No memory to process text chunk.");
1885*593dc095SDavid du Colombier return;
1886*593dc095SDavid du Colombier }
1887*593dc095SDavid du Colombier slength = (png_size_t)length;
1888*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)key, slength);
18897dd7cddfSDavid du Colombier
18907dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, skip))
18917dd7cddfSDavid du Colombier {
18927dd7cddfSDavid du Colombier png_free(png_ptr, key);
18937dd7cddfSDavid du Colombier return;
18947dd7cddfSDavid du Colombier }
18957dd7cddfSDavid du Colombier
1896*593dc095SDavid du Colombier key[slength] = 0x00;
18977dd7cddfSDavid du Colombier
18987dd7cddfSDavid du Colombier for (text = key; *text; text++)
18997dd7cddfSDavid du Colombier /* empty loop to find end of key */ ;
19007dd7cddfSDavid du Colombier
1901*593dc095SDavid du Colombier if (text != key + slength)
19027dd7cddfSDavid du Colombier text++;
19037dd7cddfSDavid du Colombier
1904*593dc095SDavid du Colombier text_ptr = (png_textp)png_malloc_warn(png_ptr,
1905*593dc095SDavid du Colombier (png_uint_32)png_sizeof(png_text));
1906*593dc095SDavid du Colombier if (text_ptr == NULL)
1907*593dc095SDavid du Colombier {
1908*593dc095SDavid du Colombier png_warning(png_ptr, "Not enough memory to process text chunk.");
1909*593dc095SDavid du Colombier png_free(png_ptr, key);
1910*593dc095SDavid du Colombier return;
1911*593dc095SDavid du Colombier }
19127dd7cddfSDavid du Colombier text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
19137dd7cddfSDavid du Colombier text_ptr->key = key;
1914*593dc095SDavid du Colombier #ifdef PNG_iTXt_SUPPORTED
1915*593dc095SDavid du Colombier text_ptr->lang = NULL;
1916*593dc095SDavid du Colombier text_ptr->lang_key = NULL;
1917*593dc095SDavid du Colombier text_ptr->itxt_length = 0;
1918*593dc095SDavid du Colombier #endif
19197dd7cddfSDavid du Colombier text_ptr->text = text;
1920*593dc095SDavid du Colombier text_ptr->text_length = png_strlen(text);
19217dd7cddfSDavid du Colombier
1922*593dc095SDavid du Colombier ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
19237dd7cddfSDavid du Colombier
1924*593dc095SDavid du Colombier png_free(png_ptr, key);
19257dd7cddfSDavid du Colombier png_free(png_ptr, text_ptr);
1926*593dc095SDavid du Colombier if (ret)
1927*593dc095SDavid du Colombier png_warning(png_ptr, "Insufficient memory to process text chunk.");
19287dd7cddfSDavid du Colombier }
19297dd7cddfSDavid du Colombier #endif
19307dd7cddfSDavid du Colombier
19317dd7cddfSDavid du Colombier #if defined(PNG_READ_zTXt_SUPPORTED)
19327dd7cddfSDavid du Colombier /* note: this does not correctly handle chunks that are > 64K under DOS */
1933*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_zTXt(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)19347dd7cddfSDavid du Colombier png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
19357dd7cddfSDavid du Colombier {
19367dd7cddfSDavid du Colombier png_textp text_ptr;
1937*593dc095SDavid du Colombier png_charp chunkdata;
19387dd7cddfSDavid du Colombier png_charp text;
1939*593dc095SDavid du Colombier int comp_type;
1940*593dc095SDavid du Colombier int ret;
1941*593dc095SDavid du Colombier png_size_t slength, prefix_len, data_len;
19427dd7cddfSDavid du Colombier
19437dd7cddfSDavid du Colombier png_debug(1, "in png_handle_zTXt\n");
19447dd7cddfSDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
19457dd7cddfSDavid du Colombier png_error(png_ptr, "Missing IHDR before zTXt");
19467dd7cddfSDavid du Colombier
19477dd7cddfSDavid du Colombier if (png_ptr->mode & PNG_HAVE_IDAT)
19487dd7cddfSDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
19497dd7cddfSDavid du Colombier
19507dd7cddfSDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
19517dd7cddfSDavid du Colombier /* We will no doubt have problems with chunks even half this size, but
19527dd7cddfSDavid du Colombier there is no hard and fast rule to tell us where to stop. */
19537dd7cddfSDavid du Colombier if (length > (png_uint_32)65535L)
19547dd7cddfSDavid du Colombier {
19557dd7cddfSDavid du Colombier png_warning(png_ptr,"zTXt chunk too large to fit in memory");
19567dd7cddfSDavid du Colombier png_crc_finish(png_ptr, length);
19577dd7cddfSDavid du Colombier return;
19587dd7cddfSDavid du Colombier }
19597dd7cddfSDavid du Colombier #endif
19607dd7cddfSDavid du Colombier
1961*593dc095SDavid du Colombier chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1962*593dc095SDavid du Colombier if (chunkdata == NULL)
1963*593dc095SDavid du Colombier {
1964*593dc095SDavid du Colombier png_warning(png_ptr,"Out of memory processing zTXt chunk.");
1965*593dc095SDavid du Colombier return;
1966*593dc095SDavid du Colombier }
1967*593dc095SDavid du Colombier slength = (png_size_t)length;
1968*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
19697dd7cddfSDavid du Colombier if (png_crc_finish(png_ptr, 0))
19707dd7cddfSDavid du Colombier {
1971*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
19727dd7cddfSDavid du Colombier return;
19737dd7cddfSDavid du Colombier }
19747dd7cddfSDavid du Colombier
1975*593dc095SDavid du Colombier chunkdata[slength] = 0x00;
19767dd7cddfSDavid du Colombier
1977*593dc095SDavid du Colombier for (text = chunkdata; *text; text++)
19787dd7cddfSDavid du Colombier /* empty loop */ ;
19797dd7cddfSDavid du Colombier
1980*593dc095SDavid du Colombier /* zTXt must have some text after the chunkdataword */
1981*593dc095SDavid du Colombier if (text == chunkdata + slength)
19827dd7cddfSDavid du Colombier {
1983*593dc095SDavid du Colombier comp_type = PNG_TEXT_COMPRESSION_NONE;
19847dd7cddfSDavid du Colombier png_warning(png_ptr, "Zero length zTXt chunk");
19857dd7cddfSDavid du Colombier }
19867dd7cddfSDavid du Colombier else
19877dd7cddfSDavid du Colombier {
1988*593dc095SDavid du Colombier comp_type = *(++text);
1989*593dc095SDavid du Colombier if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
19907dd7cddfSDavid du Colombier {
1991*593dc095SDavid du Colombier png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1992*593dc095SDavid du Colombier comp_type = PNG_TEXT_COMPRESSION_zTXt;
19937dd7cddfSDavid du Colombier }
1994*593dc095SDavid du Colombier text++; /* skip the compression_method byte */
1995*593dc095SDavid du Colombier }
1996*593dc095SDavid du Colombier prefix_len = text - chunkdata;
1997*593dc095SDavid du Colombier
1998*593dc095SDavid du Colombier chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1999*593dc095SDavid du Colombier (png_size_t)length, prefix_len, &data_len);
2000*593dc095SDavid du Colombier
2001*593dc095SDavid du Colombier text_ptr = (png_textp)png_malloc_warn(png_ptr,
2002*593dc095SDavid du Colombier (png_uint_32)png_sizeof(png_text));
2003*593dc095SDavid du Colombier if (text_ptr == NULL)
20047dd7cddfSDavid du Colombier {
2005*593dc095SDavid du Colombier png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
2006*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
2007*593dc095SDavid du Colombier return;
20087dd7cddfSDavid du Colombier }
20097dd7cddfSDavid du Colombier text_ptr->compression = comp_type;
2010*593dc095SDavid du Colombier text_ptr->key = chunkdata;
2011*593dc095SDavid du Colombier #ifdef PNG_iTXt_SUPPORTED
2012*593dc095SDavid du Colombier text_ptr->lang = NULL;
2013*593dc095SDavid du Colombier text_ptr->lang_key = NULL;
2014*593dc095SDavid du Colombier text_ptr->itxt_length = 0;
2015*593dc095SDavid du Colombier #endif
2016*593dc095SDavid du Colombier text_ptr->text = chunkdata + prefix_len;
2017*593dc095SDavid du Colombier text_ptr->text_length = data_len;
20187dd7cddfSDavid du Colombier
2019*593dc095SDavid du Colombier ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
20207dd7cddfSDavid du Colombier
20217dd7cddfSDavid du Colombier png_free(png_ptr, text_ptr);
2022*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
2023*593dc095SDavid du Colombier if (ret)
2024*593dc095SDavid du Colombier png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2025*593dc095SDavid du Colombier }
2026*593dc095SDavid du Colombier #endif
2027*593dc095SDavid du Colombier
2028*593dc095SDavid du Colombier #if defined(PNG_READ_iTXt_SUPPORTED)
2029*593dc095SDavid du Colombier /* note: this does not correctly handle chunks that are > 64K under DOS */
2030*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_iTXt(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)2031*593dc095SDavid du Colombier png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2032*593dc095SDavid du Colombier {
2033*593dc095SDavid du Colombier png_textp text_ptr;
2034*593dc095SDavid du Colombier png_charp chunkdata;
2035*593dc095SDavid du Colombier png_charp key, lang, text, lang_key;
2036*593dc095SDavid du Colombier int comp_flag;
2037*593dc095SDavid du Colombier int comp_type = 0;
2038*593dc095SDavid du Colombier int ret;
2039*593dc095SDavid du Colombier png_size_t slength, prefix_len, data_len;
2040*593dc095SDavid du Colombier
2041*593dc095SDavid du Colombier png_debug(1, "in png_handle_iTXt\n");
2042*593dc095SDavid du Colombier
2043*593dc095SDavid du Colombier if (!(png_ptr->mode & PNG_HAVE_IHDR))
2044*593dc095SDavid du Colombier png_error(png_ptr, "Missing IHDR before iTXt");
2045*593dc095SDavid du Colombier
2046*593dc095SDavid du Colombier if (png_ptr->mode & PNG_HAVE_IDAT)
2047*593dc095SDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
2048*593dc095SDavid du Colombier
2049*593dc095SDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
2050*593dc095SDavid du Colombier /* We will no doubt have problems with chunks even half this size, but
2051*593dc095SDavid du Colombier there is no hard and fast rule to tell us where to stop. */
2052*593dc095SDavid du Colombier if (length > (png_uint_32)65535L)
2053*593dc095SDavid du Colombier {
2054*593dc095SDavid du Colombier png_warning(png_ptr,"iTXt chunk too large to fit in memory");
2055*593dc095SDavid du Colombier png_crc_finish(png_ptr, length);
2056*593dc095SDavid du Colombier return;
2057*593dc095SDavid du Colombier }
2058*593dc095SDavid du Colombier #endif
2059*593dc095SDavid du Colombier
2060*593dc095SDavid du Colombier chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2061*593dc095SDavid du Colombier if (chunkdata == NULL)
2062*593dc095SDavid du Colombier {
2063*593dc095SDavid du Colombier png_warning(png_ptr, "No memory to process iTXt chunk.");
2064*593dc095SDavid du Colombier return;
2065*593dc095SDavid du Colombier }
2066*593dc095SDavid du Colombier slength = (png_size_t)length;
2067*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
2068*593dc095SDavid du Colombier if (png_crc_finish(png_ptr, 0))
2069*593dc095SDavid du Colombier {
2070*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
2071*593dc095SDavid du Colombier return;
2072*593dc095SDavid du Colombier }
2073*593dc095SDavid du Colombier
2074*593dc095SDavid du Colombier chunkdata[slength] = 0x00;
2075*593dc095SDavid du Colombier
2076*593dc095SDavid du Colombier for (lang = chunkdata; *lang; lang++)
2077*593dc095SDavid du Colombier /* empty loop */ ;
2078*593dc095SDavid du Colombier lang++; /* skip NUL separator */
2079*593dc095SDavid du Colombier
2080*593dc095SDavid du Colombier /* iTXt must have a language tag (possibly empty), two compression bytes,
2081*593dc095SDavid du Colombier translated keyword (possibly empty), and possibly some text after the
2082*593dc095SDavid du Colombier keyword */
2083*593dc095SDavid du Colombier
2084*593dc095SDavid du Colombier if (lang >= chunkdata + slength)
2085*593dc095SDavid du Colombier {
2086*593dc095SDavid du Colombier comp_flag = PNG_TEXT_COMPRESSION_NONE;
2087*593dc095SDavid du Colombier png_warning(png_ptr, "Zero length iTXt chunk");
2088*593dc095SDavid du Colombier }
2089*593dc095SDavid du Colombier else
2090*593dc095SDavid du Colombier {
2091*593dc095SDavid du Colombier comp_flag = *lang++;
2092*593dc095SDavid du Colombier comp_type = *lang++;
2093*593dc095SDavid du Colombier }
2094*593dc095SDavid du Colombier
2095*593dc095SDavid du Colombier for (lang_key = lang; *lang_key; lang_key++)
2096*593dc095SDavid du Colombier /* empty loop */ ;
2097*593dc095SDavid du Colombier lang_key++; /* skip NUL separator */
2098*593dc095SDavid du Colombier
2099*593dc095SDavid du Colombier for (text = lang_key; *text; text++)
2100*593dc095SDavid du Colombier /* empty loop */ ;
2101*593dc095SDavid du Colombier text++; /* skip NUL separator */
2102*593dc095SDavid du Colombier
2103*593dc095SDavid du Colombier prefix_len = text - chunkdata;
2104*593dc095SDavid du Colombier
2105*593dc095SDavid du Colombier key=chunkdata;
2106*593dc095SDavid du Colombier if (comp_flag)
2107*593dc095SDavid du Colombier chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2108*593dc095SDavid du Colombier (size_t)length, prefix_len, &data_len);
2109*593dc095SDavid du Colombier else
2110*593dc095SDavid du Colombier data_len=png_strlen(chunkdata + prefix_len);
2111*593dc095SDavid du Colombier text_ptr = (png_textp)png_malloc_warn(png_ptr,
2112*593dc095SDavid du Colombier (png_uint_32)png_sizeof(png_text));
2113*593dc095SDavid du Colombier if (text_ptr == NULL)
2114*593dc095SDavid du Colombier {
2115*593dc095SDavid du Colombier png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
2116*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
2117*593dc095SDavid du Colombier return;
2118*593dc095SDavid du Colombier }
2119*593dc095SDavid du Colombier text_ptr->compression = (int)comp_flag + 1;
2120*593dc095SDavid du Colombier text_ptr->lang_key = chunkdata+(lang_key-key);
2121*593dc095SDavid du Colombier text_ptr->lang = chunkdata+(lang-key);
2122*593dc095SDavid du Colombier text_ptr->itxt_length = data_len;
2123*593dc095SDavid du Colombier text_ptr->text_length = 0;
2124*593dc095SDavid du Colombier text_ptr->key = chunkdata;
2125*593dc095SDavid du Colombier text_ptr->text = chunkdata + prefix_len;
2126*593dc095SDavid du Colombier
2127*593dc095SDavid du Colombier ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2128*593dc095SDavid du Colombier
2129*593dc095SDavid du Colombier png_free(png_ptr, text_ptr);
2130*593dc095SDavid du Colombier png_free(png_ptr, chunkdata);
2131*593dc095SDavid du Colombier if (ret)
2132*593dc095SDavid du Colombier png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
21337dd7cddfSDavid du Colombier }
21347dd7cddfSDavid du Colombier #endif
21357dd7cddfSDavid du Colombier
21367dd7cddfSDavid du Colombier /* This function is called when we haven't found a handler for a
21377dd7cddfSDavid du Colombier chunk. If there isn't a problem with the chunk itself (ie bad
2138*593dc095SDavid du Colombier chunk name, CRC, or a critical chunk), the chunk is silently ignored
2139*593dc095SDavid du Colombier -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2140*593dc095SDavid du Colombier case it will be saved away to be written out later. */
2141*593dc095SDavid du Colombier void /* PRIVATE */
png_handle_unknown(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)21427dd7cddfSDavid du Colombier png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
21437dd7cddfSDavid du Colombier {
2144*593dc095SDavid du Colombier png_uint_32 skip = 0;
2145*593dc095SDavid du Colombier
21467dd7cddfSDavid du Colombier png_debug(1, "in png_handle_unknown\n");
21477dd7cddfSDavid du Colombier
2148*593dc095SDavid du Colombier if (png_ptr->mode & PNG_HAVE_IDAT)
2149*593dc095SDavid du Colombier {
2150*593dc095SDavid du Colombier #ifdef PNG_USE_LOCAL_ARRAYS
2151*593dc095SDavid du Colombier PNG_IDAT;
2152*593dc095SDavid du Colombier #endif
2153*593dc095SDavid du Colombier if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2154*593dc095SDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
2155*593dc095SDavid du Colombier }
2156*593dc095SDavid du Colombier
21577dd7cddfSDavid du Colombier png_check_chunk_name(png_ptr, png_ptr->chunk_name);
21587dd7cddfSDavid du Colombier
21597dd7cddfSDavid du Colombier if (!(png_ptr->chunk_name[0] & 0x20))
21607dd7cddfSDavid du Colombier {
2161*593dc095SDavid du Colombier #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2162*593dc095SDavid du Colombier if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2163*593dc095SDavid du Colombier PNG_HANDLE_CHUNK_ALWAYS
2164*593dc095SDavid du Colombier #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2165*593dc095SDavid du Colombier && png_ptr->read_user_chunk_fn == NULL
2166*593dc095SDavid du Colombier #endif
2167*593dc095SDavid du Colombier )
2168*593dc095SDavid du Colombier #endif
21697dd7cddfSDavid du Colombier png_chunk_error(png_ptr, "unknown critical chunk");
21707dd7cddfSDavid du Colombier }
21717dd7cddfSDavid du Colombier
2172*593dc095SDavid du Colombier #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2173*593dc095SDavid du Colombier if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2174*593dc095SDavid du Colombier {
2175*593dc095SDavid du Colombier png_unknown_chunk chunk;
21767dd7cddfSDavid du Colombier
2177*593dc095SDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
2178*593dc095SDavid du Colombier if (length > (png_uint_32)65535L)
2179*593dc095SDavid du Colombier {
2180*593dc095SDavid du Colombier png_warning(png_ptr, "unknown chunk too large to fit in memory");
2181*593dc095SDavid du Colombier skip = length - (png_uint_32)65535L;
2182*593dc095SDavid du Colombier length = (png_uint_32)65535L;
2183*593dc095SDavid du Colombier }
2184*593dc095SDavid du Colombier #endif
2185*593dc095SDavid du Colombier png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2186*593dc095SDavid du Colombier chunk.data = (png_bytep)png_malloc(png_ptr, length);
2187*593dc095SDavid du Colombier chunk.size = (png_size_t)length;
2188*593dc095SDavid du Colombier png_crc_read(png_ptr, (png_bytep)chunk.data, length);
2189*593dc095SDavid du Colombier #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2190*593dc095SDavid du Colombier if(png_ptr->read_user_chunk_fn != NULL)
2191*593dc095SDavid du Colombier {
2192*593dc095SDavid du Colombier /* callback to user unknown chunk handler */
2193*593dc095SDavid du Colombier if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2194*593dc095SDavid du Colombier {
2195*593dc095SDavid du Colombier if (!(png_ptr->chunk_name[0] & 0x20))
2196*593dc095SDavid du Colombier if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2197*593dc095SDavid du Colombier PNG_HANDLE_CHUNK_ALWAYS)
2198*593dc095SDavid du Colombier {
2199*593dc095SDavid du Colombier png_free(png_ptr, chunk.data);
2200*593dc095SDavid du Colombier png_chunk_error(png_ptr, "unknown critical chunk");
2201*593dc095SDavid du Colombier }
2202*593dc095SDavid du Colombier png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2203*593dc095SDavid du Colombier }
2204*593dc095SDavid du Colombier }
2205*593dc095SDavid du Colombier else
2206*593dc095SDavid du Colombier #endif
2207*593dc095SDavid du Colombier png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2208*593dc095SDavid du Colombier png_free(png_ptr, chunk.data);
2209*593dc095SDavid du Colombier }
2210*593dc095SDavid du Colombier else
2211*593dc095SDavid du Colombier #endif
2212*593dc095SDavid du Colombier skip = length;
2213*593dc095SDavid du Colombier
2214*593dc095SDavid du Colombier png_crc_finish(png_ptr, skip);
2215*593dc095SDavid du Colombier
2216*593dc095SDavid du Colombier #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2217*593dc095SDavid du Colombier if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
2218*593dc095SDavid du Colombier return;
2219*593dc095SDavid du Colombier #endif
22207dd7cddfSDavid du Colombier }
22217dd7cddfSDavid du Colombier
22227dd7cddfSDavid du Colombier /* This function is called to verify that a chunk name is valid.
22237dd7cddfSDavid du Colombier This function can't have the "critical chunk check" incorporated
22247dd7cddfSDavid du Colombier into it, since in the future we will need to be able to call user
22257dd7cddfSDavid du Colombier functions to handle unknown critical chunks after we check that
22267dd7cddfSDavid du Colombier the chunk name itself is valid. */
22277dd7cddfSDavid du Colombier
2228*593dc095SDavid du Colombier #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
22297dd7cddfSDavid du Colombier
2230*593dc095SDavid du Colombier void /* PRIVATE */
png_check_chunk_name(png_structp png_ptr,png_bytep chunk_name)22317dd7cddfSDavid du Colombier png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
22327dd7cddfSDavid du Colombier {
22337dd7cddfSDavid du Colombier png_debug(1, "in png_check_chunk_name\n");
22347dd7cddfSDavid du Colombier if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
22357dd7cddfSDavid du Colombier isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
22367dd7cddfSDavid du Colombier {
22377dd7cddfSDavid du Colombier png_chunk_error(png_ptr, "invalid chunk type");
22387dd7cddfSDavid du Colombier }
22397dd7cddfSDavid du Colombier }
22407dd7cddfSDavid du Colombier
2241*593dc095SDavid du Colombier /* Combines the row recently read in with the existing pixels in the
2242*593dc095SDavid du Colombier row. This routine takes care of alpha and transparency if requested.
22437dd7cddfSDavid du Colombier This routine also handles the two methods of progressive display
22447dd7cddfSDavid du Colombier of interlaced images, depending on the mask value.
22457dd7cddfSDavid du Colombier The mask value describes which pixels are to be combined with
22467dd7cddfSDavid du Colombier the row. The pattern always repeats every 8 pixels, so just 8
2247*593dc095SDavid du Colombier bits are needed. A one indicates the pixel is to be combined,
22487dd7cddfSDavid du Colombier a zero indicates the pixel is to be skipped. This is in addition
22497dd7cddfSDavid du Colombier to any alpha or transparency value associated with the pixel. If
22507dd7cddfSDavid du Colombier you want all pixels to be combined, pass 0xff (255) in mask. */
2251*593dc095SDavid du Colombier #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2252*593dc095SDavid du Colombier void /* PRIVATE */
png_combine_row(png_structp png_ptr,png_bytep row,int mask)2253*593dc095SDavid du Colombier png_combine_row(png_structp png_ptr, png_bytep row, int mask)
22547dd7cddfSDavid du Colombier {
22557dd7cddfSDavid du Colombier png_debug(1,"in png_combine_row\n");
22567dd7cddfSDavid du Colombier if (mask == 0xff)
22577dd7cddfSDavid du Colombier {
22587dd7cddfSDavid du Colombier png_memcpy(row, png_ptr->row_buf + 1,
2259*593dc095SDavid du Colombier PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
22607dd7cddfSDavid du Colombier }
22617dd7cddfSDavid du Colombier else
22627dd7cddfSDavid du Colombier {
22637dd7cddfSDavid du Colombier switch (png_ptr->row_info.pixel_depth)
22647dd7cddfSDavid du Colombier {
22657dd7cddfSDavid du Colombier case 1:
22667dd7cddfSDavid du Colombier {
2267*593dc095SDavid du Colombier png_bytep sp = png_ptr->row_buf + 1;
2268*593dc095SDavid du Colombier png_bytep dp = row;
22697dd7cddfSDavid du Colombier int s_inc, s_start, s_end;
2270*593dc095SDavid du Colombier int m = 0x80;
22717dd7cddfSDavid du Colombier int shift;
22727dd7cddfSDavid du Colombier png_uint_32 i;
2273*593dc095SDavid du Colombier png_uint_32 row_width = png_ptr->width;
22747dd7cddfSDavid du Colombier
22757dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
22767dd7cddfSDavid du Colombier if (png_ptr->transformations & PNG_PACKSWAP)
22777dd7cddfSDavid du Colombier {
22787dd7cddfSDavid du Colombier s_start = 0;
22797dd7cddfSDavid du Colombier s_end = 7;
22807dd7cddfSDavid du Colombier s_inc = 1;
22817dd7cddfSDavid du Colombier }
22827dd7cddfSDavid du Colombier else
22837dd7cddfSDavid du Colombier #endif
22847dd7cddfSDavid du Colombier {
22857dd7cddfSDavid du Colombier s_start = 7;
22867dd7cddfSDavid du Colombier s_end = 0;
22877dd7cddfSDavid du Colombier s_inc = -1;
22887dd7cddfSDavid du Colombier }
22897dd7cddfSDavid du Colombier
22907dd7cddfSDavid du Colombier shift = s_start;
22917dd7cddfSDavid du Colombier
2292*593dc095SDavid du Colombier for (i = 0; i < row_width; i++)
22937dd7cddfSDavid du Colombier {
22947dd7cddfSDavid du Colombier if (m & mask)
22957dd7cddfSDavid du Colombier {
22967dd7cddfSDavid du Colombier int value;
22977dd7cddfSDavid du Colombier
2298*593dc095SDavid du Colombier value = (*sp >> shift) & 0x01;
22997dd7cddfSDavid du Colombier *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
23007dd7cddfSDavid du Colombier *dp |= (png_byte)(value << shift);
23017dd7cddfSDavid du Colombier }
23027dd7cddfSDavid du Colombier
23037dd7cddfSDavid du Colombier if (shift == s_end)
23047dd7cddfSDavid du Colombier {
23057dd7cddfSDavid du Colombier shift = s_start;
23067dd7cddfSDavid du Colombier sp++;
23077dd7cddfSDavid du Colombier dp++;
23087dd7cddfSDavid du Colombier }
23097dd7cddfSDavid du Colombier else
23107dd7cddfSDavid du Colombier shift += s_inc;
23117dd7cddfSDavid du Colombier
23127dd7cddfSDavid du Colombier if (m == 1)
23137dd7cddfSDavid du Colombier m = 0x80;
23147dd7cddfSDavid du Colombier else
23157dd7cddfSDavid du Colombier m >>= 1;
23167dd7cddfSDavid du Colombier }
23177dd7cddfSDavid du Colombier break;
23187dd7cddfSDavid du Colombier }
23197dd7cddfSDavid du Colombier case 2:
23207dd7cddfSDavid du Colombier {
2321*593dc095SDavid du Colombier png_bytep sp = png_ptr->row_buf + 1;
2322*593dc095SDavid du Colombier png_bytep dp = row;
23237dd7cddfSDavid du Colombier int s_start, s_end, s_inc;
2324*593dc095SDavid du Colombier int m = 0x80;
23257dd7cddfSDavid du Colombier int shift;
23267dd7cddfSDavid du Colombier png_uint_32 i;
2327*593dc095SDavid du Colombier png_uint_32 row_width = png_ptr->width;
23287dd7cddfSDavid du Colombier int value;
23297dd7cddfSDavid du Colombier
23307dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
23317dd7cddfSDavid du Colombier if (png_ptr->transformations & PNG_PACKSWAP)
23327dd7cddfSDavid du Colombier {
23337dd7cddfSDavid du Colombier s_start = 0;
23347dd7cddfSDavid du Colombier s_end = 6;
23357dd7cddfSDavid du Colombier s_inc = 2;
23367dd7cddfSDavid du Colombier }
23377dd7cddfSDavid du Colombier else
23387dd7cddfSDavid du Colombier #endif
23397dd7cddfSDavid du Colombier {
23407dd7cddfSDavid du Colombier s_start = 6;
23417dd7cddfSDavid du Colombier s_end = 0;
23427dd7cddfSDavid du Colombier s_inc = -2;
23437dd7cddfSDavid du Colombier }
23447dd7cddfSDavid du Colombier
23457dd7cddfSDavid du Colombier shift = s_start;
23467dd7cddfSDavid du Colombier
2347*593dc095SDavid du Colombier for (i = 0; i < row_width; i++)
23487dd7cddfSDavid du Colombier {
23497dd7cddfSDavid du Colombier if (m & mask)
23507dd7cddfSDavid du Colombier {
2351*593dc095SDavid du Colombier value = (*sp >> shift) & 0x03;
23527dd7cddfSDavid du Colombier *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
23537dd7cddfSDavid du Colombier *dp |= (png_byte)(value << shift);
23547dd7cddfSDavid du Colombier }
23557dd7cddfSDavid du Colombier
23567dd7cddfSDavid du Colombier if (shift == s_end)
23577dd7cddfSDavid du Colombier {
23587dd7cddfSDavid du Colombier shift = s_start;
23597dd7cddfSDavid du Colombier sp++;
23607dd7cddfSDavid du Colombier dp++;
23617dd7cddfSDavid du Colombier }
23627dd7cddfSDavid du Colombier else
23637dd7cddfSDavid du Colombier shift += s_inc;
23647dd7cddfSDavid du Colombier if (m == 1)
23657dd7cddfSDavid du Colombier m = 0x80;
23667dd7cddfSDavid du Colombier else
23677dd7cddfSDavid du Colombier m >>= 1;
23687dd7cddfSDavid du Colombier }
23697dd7cddfSDavid du Colombier break;
23707dd7cddfSDavid du Colombier }
23717dd7cddfSDavid du Colombier case 4:
23727dd7cddfSDavid du Colombier {
2373*593dc095SDavid du Colombier png_bytep sp = png_ptr->row_buf + 1;
2374*593dc095SDavid du Colombier png_bytep dp = row;
23757dd7cddfSDavid du Colombier int s_start, s_end, s_inc;
2376*593dc095SDavid du Colombier int m = 0x80;
23777dd7cddfSDavid du Colombier int shift;
23787dd7cddfSDavid du Colombier png_uint_32 i;
2379*593dc095SDavid du Colombier png_uint_32 row_width = png_ptr->width;
23807dd7cddfSDavid du Colombier int value;
23817dd7cddfSDavid du Colombier
23827dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
23837dd7cddfSDavid du Colombier if (png_ptr->transformations & PNG_PACKSWAP)
23847dd7cddfSDavid du Colombier {
23857dd7cddfSDavid du Colombier s_start = 0;
23867dd7cddfSDavid du Colombier s_end = 4;
23877dd7cddfSDavid du Colombier s_inc = 4;
23887dd7cddfSDavid du Colombier }
23897dd7cddfSDavid du Colombier else
23907dd7cddfSDavid du Colombier #endif
23917dd7cddfSDavid du Colombier {
23927dd7cddfSDavid du Colombier s_start = 4;
23937dd7cddfSDavid du Colombier s_end = 0;
23947dd7cddfSDavid du Colombier s_inc = -4;
23957dd7cddfSDavid du Colombier }
23967dd7cddfSDavid du Colombier shift = s_start;
23977dd7cddfSDavid du Colombier
2398*593dc095SDavid du Colombier for (i = 0; i < row_width; i++)
23997dd7cddfSDavid du Colombier {
24007dd7cddfSDavid du Colombier if (m & mask)
24017dd7cddfSDavid du Colombier {
24027dd7cddfSDavid du Colombier value = (*sp >> shift) & 0xf;
24037dd7cddfSDavid du Colombier *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
24047dd7cddfSDavid du Colombier *dp |= (png_byte)(value << shift);
24057dd7cddfSDavid du Colombier }
24067dd7cddfSDavid du Colombier
24077dd7cddfSDavid du Colombier if (shift == s_end)
24087dd7cddfSDavid du Colombier {
24097dd7cddfSDavid du Colombier shift = s_start;
24107dd7cddfSDavid du Colombier sp++;
24117dd7cddfSDavid du Colombier dp++;
24127dd7cddfSDavid du Colombier }
24137dd7cddfSDavid du Colombier else
24147dd7cddfSDavid du Colombier shift += s_inc;
24157dd7cddfSDavid du Colombier if (m == 1)
24167dd7cddfSDavid du Colombier m = 0x80;
24177dd7cddfSDavid du Colombier else
24187dd7cddfSDavid du Colombier m >>= 1;
24197dd7cddfSDavid du Colombier }
24207dd7cddfSDavid du Colombier break;
24217dd7cddfSDavid du Colombier }
24227dd7cddfSDavid du Colombier default:
24237dd7cddfSDavid du Colombier {
2424*593dc095SDavid du Colombier png_bytep sp = png_ptr->row_buf + 1;
2425*593dc095SDavid du Colombier png_bytep dp = row;
2426*593dc095SDavid du Colombier png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
24277dd7cddfSDavid du Colombier png_uint_32 i;
2428*593dc095SDavid du Colombier png_uint_32 row_width = png_ptr->width;
2429*593dc095SDavid du Colombier png_byte m = 0x80;
24307dd7cddfSDavid du Colombier
24317dd7cddfSDavid du Colombier
2432*593dc095SDavid du Colombier for (i = 0; i < row_width; i++)
24337dd7cddfSDavid du Colombier {
24347dd7cddfSDavid du Colombier if (m & mask)
24357dd7cddfSDavid du Colombier {
24367dd7cddfSDavid du Colombier png_memcpy(dp, sp, pixel_bytes);
24377dd7cddfSDavid du Colombier }
24387dd7cddfSDavid du Colombier
24397dd7cddfSDavid du Colombier sp += pixel_bytes;
24407dd7cddfSDavid du Colombier dp += pixel_bytes;
24417dd7cddfSDavid du Colombier
24427dd7cddfSDavid du Colombier if (m == 1)
24437dd7cddfSDavid du Colombier m = 0x80;
24447dd7cddfSDavid du Colombier else
24457dd7cddfSDavid du Colombier m >>= 1;
24467dd7cddfSDavid du Colombier }
24477dd7cddfSDavid du Colombier break;
24487dd7cddfSDavid du Colombier }
24497dd7cddfSDavid du Colombier }
24507dd7cddfSDavid du Colombier }
24517dd7cddfSDavid du Colombier }
2452*593dc095SDavid du Colombier #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
24537dd7cddfSDavid du Colombier
2454*593dc095SDavid du Colombier #ifdef PNG_READ_INTERLACING_SUPPORTED
2455*593dc095SDavid du Colombier #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2456*593dc095SDavid du Colombier /* OLD pre-1.0.9 interface:
2457*593dc095SDavid du Colombier void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
24587dd7cddfSDavid du Colombier png_uint_32 transformations)
2459*593dc095SDavid du Colombier */
2460*593dc095SDavid du Colombier void /* PRIVATE */
png_do_read_interlace(png_structp png_ptr)2461*593dc095SDavid du Colombier png_do_read_interlace(png_structp png_ptr)
24627dd7cddfSDavid du Colombier {
2463*593dc095SDavid du Colombier png_row_infop row_info = &(png_ptr->row_info);
2464*593dc095SDavid du Colombier png_bytep row = png_ptr->row_buf + 1;
2465*593dc095SDavid du Colombier int pass = png_ptr->pass;
2466*593dc095SDavid du Colombier png_uint_32 transformations = png_ptr->transformations;
2467*593dc095SDavid du Colombier #ifdef PNG_USE_LOCAL_ARRAYS
2468*593dc095SDavid du Colombier /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2469*593dc095SDavid du Colombier /* offset to next interlace block */
2470*593dc095SDavid du Colombier const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2471*593dc095SDavid du Colombier #endif
2472*593dc095SDavid du Colombier
2473*593dc095SDavid du Colombier png_debug(1,"in png_do_read_interlace (stock C version)\n");
24747dd7cddfSDavid du Colombier if (row != NULL && row_info != NULL)
24757dd7cddfSDavid du Colombier {
24767dd7cddfSDavid du Colombier png_uint_32 final_width;
24777dd7cddfSDavid du Colombier
24787dd7cddfSDavid du Colombier final_width = row_info->width * png_pass_inc[pass];
24797dd7cddfSDavid du Colombier
24807dd7cddfSDavid du Colombier switch (row_info->pixel_depth)
24817dd7cddfSDavid du Colombier {
24827dd7cddfSDavid du Colombier case 1:
24837dd7cddfSDavid du Colombier {
2484*593dc095SDavid du Colombier png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2485*593dc095SDavid du Colombier png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
24867dd7cddfSDavid du Colombier int sshift, dshift;
24877dd7cddfSDavid du Colombier int s_start, s_end, s_inc;
2488*593dc095SDavid du Colombier int jstop = png_pass_inc[pass];
24897dd7cddfSDavid du Colombier png_byte v;
24907dd7cddfSDavid du Colombier png_uint_32 i;
24917dd7cddfSDavid du Colombier int j;
24927dd7cddfSDavid du Colombier
24937dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
24947dd7cddfSDavid du Colombier if (transformations & PNG_PACKSWAP)
24957dd7cddfSDavid du Colombier {
2496*593dc095SDavid du Colombier sshift = (int)((row_info->width + 7) & 0x07);
2497*593dc095SDavid du Colombier dshift = (int)((final_width + 7) & 0x07);
24987dd7cddfSDavid du Colombier s_start = 7;
24997dd7cddfSDavid du Colombier s_end = 0;
25007dd7cddfSDavid du Colombier s_inc = -1;
25017dd7cddfSDavid du Colombier }
25027dd7cddfSDavid du Colombier else
25037dd7cddfSDavid du Colombier #endif
25047dd7cddfSDavid du Colombier {
2505*593dc095SDavid du Colombier sshift = 7 - (int)((row_info->width + 7) & 0x07);
2506*593dc095SDavid du Colombier dshift = 7 - (int)((final_width + 7) & 0x07);
25077dd7cddfSDavid du Colombier s_start = 0;
25087dd7cddfSDavid du Colombier s_end = 7;
25097dd7cddfSDavid du Colombier s_inc = 1;
25107dd7cddfSDavid du Colombier }
25117dd7cddfSDavid du Colombier
2512*593dc095SDavid du Colombier for (i = 0; i < row_info->width; i++)
25137dd7cddfSDavid du Colombier {
2514*593dc095SDavid du Colombier v = (png_byte)((*sp >> sshift) & 0x01);
2515*593dc095SDavid du Colombier for (j = 0; j < jstop; j++)
25167dd7cddfSDavid du Colombier {
25177dd7cddfSDavid du Colombier *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
25187dd7cddfSDavid du Colombier *dp |= (png_byte)(v << dshift);
25197dd7cddfSDavid du Colombier if (dshift == s_end)
25207dd7cddfSDavid du Colombier {
25217dd7cddfSDavid du Colombier dshift = s_start;
25227dd7cddfSDavid du Colombier dp--;
25237dd7cddfSDavid du Colombier }
25247dd7cddfSDavid du Colombier else
25257dd7cddfSDavid du Colombier dshift += s_inc;
25267dd7cddfSDavid du Colombier }
25277dd7cddfSDavid du Colombier if (sshift == s_end)
25287dd7cddfSDavid du Colombier {
25297dd7cddfSDavid du Colombier sshift = s_start;
25307dd7cddfSDavid du Colombier sp--;
25317dd7cddfSDavid du Colombier }
25327dd7cddfSDavid du Colombier else
25337dd7cddfSDavid du Colombier sshift += s_inc;
25347dd7cddfSDavid du Colombier }
25357dd7cddfSDavid du Colombier break;
25367dd7cddfSDavid du Colombier }
25377dd7cddfSDavid du Colombier case 2:
25387dd7cddfSDavid du Colombier {
2539*593dc095SDavid du Colombier png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2540*593dc095SDavid du Colombier png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
25417dd7cddfSDavid du Colombier int sshift, dshift;
25427dd7cddfSDavid du Colombier int s_start, s_end, s_inc;
2543*593dc095SDavid du Colombier int jstop = png_pass_inc[pass];
25447dd7cddfSDavid du Colombier png_uint_32 i;
25457dd7cddfSDavid du Colombier
25467dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
25477dd7cddfSDavid du Colombier if (transformations & PNG_PACKSWAP)
25487dd7cddfSDavid du Colombier {
2549*593dc095SDavid du Colombier sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2550*593dc095SDavid du Colombier dshift = (int)(((final_width + 3) & 0x03) << 1);
25517dd7cddfSDavid du Colombier s_start = 6;
25527dd7cddfSDavid du Colombier s_end = 0;
25537dd7cddfSDavid du Colombier s_inc = -2;
25547dd7cddfSDavid du Colombier }
25557dd7cddfSDavid du Colombier else
25567dd7cddfSDavid du Colombier #endif
25577dd7cddfSDavid du Colombier {
2558*593dc095SDavid du Colombier sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2559*593dc095SDavid du Colombier dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
25607dd7cddfSDavid du Colombier s_start = 0;
25617dd7cddfSDavid du Colombier s_end = 6;
25627dd7cddfSDavid du Colombier s_inc = 2;
25637dd7cddfSDavid du Colombier }
25647dd7cddfSDavid du Colombier
2565*593dc095SDavid du Colombier for (i = 0; i < row_info->width; i++)
25667dd7cddfSDavid du Colombier {
25677dd7cddfSDavid du Colombier png_byte v;
25687dd7cddfSDavid du Colombier int j;
25697dd7cddfSDavid du Colombier
2570*593dc095SDavid du Colombier v = (png_byte)((*sp >> sshift) & 0x03);
2571*593dc095SDavid du Colombier for (j = 0; j < jstop; j++)
25727dd7cddfSDavid du Colombier {
25737dd7cddfSDavid du Colombier *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
25747dd7cddfSDavid du Colombier *dp |= (png_byte)(v << dshift);
25757dd7cddfSDavid du Colombier if (dshift == s_end)
25767dd7cddfSDavid du Colombier {
25777dd7cddfSDavid du Colombier dshift = s_start;
25787dd7cddfSDavid du Colombier dp--;
25797dd7cddfSDavid du Colombier }
25807dd7cddfSDavid du Colombier else
25817dd7cddfSDavid du Colombier dshift += s_inc;
25827dd7cddfSDavid du Colombier }
25837dd7cddfSDavid du Colombier if (sshift == s_end)
25847dd7cddfSDavid du Colombier {
25857dd7cddfSDavid du Colombier sshift = s_start;
25867dd7cddfSDavid du Colombier sp--;
25877dd7cddfSDavid du Colombier }
25887dd7cddfSDavid du Colombier else
25897dd7cddfSDavid du Colombier sshift += s_inc;
25907dd7cddfSDavid du Colombier }
25917dd7cddfSDavid du Colombier break;
25927dd7cddfSDavid du Colombier }
25937dd7cddfSDavid du Colombier case 4:
25947dd7cddfSDavid du Colombier {
2595*593dc095SDavid du Colombier png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2596*593dc095SDavid du Colombier png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
25977dd7cddfSDavid du Colombier int sshift, dshift;
25987dd7cddfSDavid du Colombier int s_start, s_end, s_inc;
25997dd7cddfSDavid du Colombier png_uint_32 i;
2600*593dc095SDavid du Colombier int jstop = png_pass_inc[pass];
26017dd7cddfSDavid du Colombier
26027dd7cddfSDavid du Colombier #if defined(PNG_READ_PACKSWAP_SUPPORTED)
26037dd7cddfSDavid du Colombier if (transformations & PNG_PACKSWAP)
26047dd7cddfSDavid du Colombier {
2605*593dc095SDavid du Colombier sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2606*593dc095SDavid du Colombier dshift = (int)(((final_width + 1) & 0x01) << 2);
26077dd7cddfSDavid du Colombier s_start = 4;
26087dd7cddfSDavid du Colombier s_end = 0;
26097dd7cddfSDavid du Colombier s_inc = -4;
26107dd7cddfSDavid du Colombier }
26117dd7cddfSDavid du Colombier else
26127dd7cddfSDavid du Colombier #endif
26137dd7cddfSDavid du Colombier {
2614*593dc095SDavid du Colombier sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2615*593dc095SDavid du Colombier dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
26167dd7cddfSDavid du Colombier s_start = 0;
26177dd7cddfSDavid du Colombier s_end = 4;
26187dd7cddfSDavid du Colombier s_inc = 4;
26197dd7cddfSDavid du Colombier }
26207dd7cddfSDavid du Colombier
2621*593dc095SDavid du Colombier for (i = 0; i < row_info->width; i++)
26227dd7cddfSDavid du Colombier {
2623*593dc095SDavid du Colombier png_byte v = (png_byte)((*sp >> sshift) & 0xf);
26247dd7cddfSDavid du Colombier int j;
26257dd7cddfSDavid du Colombier
2626*593dc095SDavid du Colombier for (j = 0; j < jstop; j++)
26277dd7cddfSDavid du Colombier {
26287dd7cddfSDavid du Colombier *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
26297dd7cddfSDavid du Colombier *dp |= (png_byte)(v << dshift);
26307dd7cddfSDavid du Colombier if (dshift == s_end)
26317dd7cddfSDavid du Colombier {
26327dd7cddfSDavid du Colombier dshift = s_start;
26337dd7cddfSDavid du Colombier dp--;
26347dd7cddfSDavid du Colombier }
26357dd7cddfSDavid du Colombier else
26367dd7cddfSDavid du Colombier dshift += s_inc;
26377dd7cddfSDavid du Colombier }
26387dd7cddfSDavid du Colombier if (sshift == s_end)
26397dd7cddfSDavid du Colombier {
26407dd7cddfSDavid du Colombier sshift = s_start;
26417dd7cddfSDavid du Colombier sp--;
26427dd7cddfSDavid du Colombier }
26437dd7cddfSDavid du Colombier else
26447dd7cddfSDavid du Colombier sshift += s_inc;
26457dd7cddfSDavid du Colombier }
26467dd7cddfSDavid du Colombier break;
26477dd7cddfSDavid du Colombier }
26487dd7cddfSDavid du Colombier default:
26497dd7cddfSDavid du Colombier {
2650*593dc095SDavid du Colombier png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2651*593dc095SDavid du Colombier png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2652*593dc095SDavid du Colombier png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2653*593dc095SDavid du Colombier
2654*593dc095SDavid du Colombier int jstop = png_pass_inc[pass];
26557dd7cddfSDavid du Colombier png_uint_32 i;
26567dd7cddfSDavid du Colombier
2657*593dc095SDavid du Colombier for (i = 0; i < row_info->width; i++)
26587dd7cddfSDavid du Colombier {
26597dd7cddfSDavid du Colombier png_byte v[8];
26607dd7cddfSDavid du Colombier int j;
26617dd7cddfSDavid du Colombier
26627dd7cddfSDavid du Colombier png_memcpy(v, sp, pixel_bytes);
2663*593dc095SDavid du Colombier for (j = 0; j < jstop; j++)
26647dd7cddfSDavid du Colombier {
26657dd7cddfSDavid du Colombier png_memcpy(dp, v, pixel_bytes);
26667dd7cddfSDavid du Colombier dp -= pixel_bytes;
26677dd7cddfSDavid du Colombier }
26687dd7cddfSDavid du Colombier sp -= pixel_bytes;
26697dd7cddfSDavid du Colombier }
26707dd7cddfSDavid du Colombier break;
26717dd7cddfSDavid du Colombier }
26727dd7cddfSDavid du Colombier }
26737dd7cddfSDavid du Colombier row_info->width = final_width;
2674*593dc095SDavid du Colombier row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
26757dd7cddfSDavid du Colombier }
2676*593dc095SDavid du Colombier #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2677*593dc095SDavid du Colombier if (&transformations == NULL) /* silence compiler warning */
2678*593dc095SDavid du Colombier return;
26797dd7cddfSDavid du Colombier #endif
2680*593dc095SDavid du Colombier }
2681*593dc095SDavid du Colombier #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2682*593dc095SDavid du Colombier #endif /* PNG_READ_INTERLACING_SUPPORTED */
26837dd7cddfSDavid du Colombier
2684*593dc095SDavid du Colombier #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2685*593dc095SDavid du Colombier void /* PRIVATE */
png_read_filter_row(png_structp png_ptr,png_row_infop row_info,png_bytep row,png_bytep prev_row,int filter)26867dd7cddfSDavid du Colombier png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
26877dd7cddfSDavid du Colombier png_bytep prev_row, int filter)
26887dd7cddfSDavid du Colombier {
26897dd7cddfSDavid du Colombier png_debug(1, "in png_read_filter_row\n");
2690*593dc095SDavid du Colombier png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
26917dd7cddfSDavid du Colombier switch (filter)
26927dd7cddfSDavid du Colombier {
26937dd7cddfSDavid du Colombier case PNG_FILTER_VALUE_NONE:
26947dd7cddfSDavid du Colombier break;
26957dd7cddfSDavid du Colombier case PNG_FILTER_VALUE_SUB:
26967dd7cddfSDavid du Colombier {
26977dd7cddfSDavid du Colombier png_uint_32 i;
2698*593dc095SDavid du Colombier png_uint_32 istop = row_info->rowbytes;
2699*593dc095SDavid du Colombier png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2700*593dc095SDavid du Colombier png_bytep rp = row + bpp;
2701*593dc095SDavid du Colombier png_bytep lp = row;
27027dd7cddfSDavid du Colombier
2703*593dc095SDavid du Colombier for (i = bpp; i < istop; i++)
27047dd7cddfSDavid du Colombier {
2705*593dc095SDavid du Colombier *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2706*593dc095SDavid du Colombier rp++;
27077dd7cddfSDavid du Colombier }
27087dd7cddfSDavid du Colombier break;
27097dd7cddfSDavid du Colombier }
27107dd7cddfSDavid du Colombier case PNG_FILTER_VALUE_UP:
27117dd7cddfSDavid du Colombier {
27127dd7cddfSDavid du Colombier png_uint_32 i;
2713*593dc095SDavid du Colombier png_uint_32 istop = row_info->rowbytes;
2714*593dc095SDavid du Colombier png_bytep rp = row;
2715*593dc095SDavid du Colombier png_bytep pp = prev_row;
27167dd7cddfSDavid du Colombier
2717*593dc095SDavid du Colombier for (i = 0; i < istop; i++)
27187dd7cddfSDavid du Colombier {
2719*593dc095SDavid du Colombier *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2720*593dc095SDavid du Colombier rp++;
27217dd7cddfSDavid du Colombier }
27227dd7cddfSDavid du Colombier break;
27237dd7cddfSDavid du Colombier }
27247dd7cddfSDavid du Colombier case PNG_FILTER_VALUE_AVG:
27257dd7cddfSDavid du Colombier {
27267dd7cddfSDavid du Colombier png_uint_32 i;
2727*593dc095SDavid du Colombier png_bytep rp = row;
2728*593dc095SDavid du Colombier png_bytep pp = prev_row;
2729*593dc095SDavid du Colombier png_bytep lp = row;
2730*593dc095SDavid du Colombier png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2731*593dc095SDavid du Colombier png_uint_32 istop = row_info->rowbytes - bpp;
27327dd7cddfSDavid du Colombier
2733*593dc095SDavid du Colombier for (i = 0; i < bpp; i++)
27347dd7cddfSDavid du Colombier {
27357dd7cddfSDavid du Colombier *rp = (png_byte)(((int)(*rp) +
2736*593dc095SDavid du Colombier ((int)(*pp++) / 2 )) & 0xff);
2737*593dc095SDavid du Colombier rp++;
27387dd7cddfSDavid du Colombier }
2739*593dc095SDavid du Colombier
2740*593dc095SDavid du Colombier for (i = 0; i < istop; i++)
27417dd7cddfSDavid du Colombier {
27427dd7cddfSDavid du Colombier *rp = (png_byte)(((int)(*rp) +
2743*593dc095SDavid du Colombier (int)(*pp++ + *lp++) / 2 ) & 0xff);
2744*593dc095SDavid du Colombier rp++;
27457dd7cddfSDavid du Colombier }
27467dd7cddfSDavid du Colombier break;
27477dd7cddfSDavid du Colombier }
27487dd7cddfSDavid du Colombier case PNG_FILTER_VALUE_PAETH:
27497dd7cddfSDavid du Colombier {
27507dd7cddfSDavid du Colombier png_uint_32 i;
2751*593dc095SDavid du Colombier png_bytep rp = row;
2752*593dc095SDavid du Colombier png_bytep pp = prev_row;
2753*593dc095SDavid du Colombier png_bytep lp = row;
2754*593dc095SDavid du Colombier png_bytep cp = prev_row;
2755*593dc095SDavid du Colombier png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2756*593dc095SDavid du Colombier png_uint_32 istop=row_info->rowbytes - bpp;
27577dd7cddfSDavid du Colombier
2758*593dc095SDavid du Colombier for (i = 0; i < bpp; i++)
2759*593dc095SDavid du Colombier {
2760*593dc095SDavid du Colombier *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2761*593dc095SDavid du Colombier rp++;
2762*593dc095SDavid du Colombier }
2763*593dc095SDavid du Colombier
2764*593dc095SDavid du Colombier for (i = 0; i < istop; i++) /* use leftover rp,pp */
27657dd7cddfSDavid du Colombier {
27667dd7cddfSDavid du Colombier int a, b, c, pa, pb, pc, p;
27677dd7cddfSDavid du Colombier
2768*593dc095SDavid du Colombier a = *lp++;
2769*593dc095SDavid du Colombier b = *pp++;
2770*593dc095SDavid du Colombier c = *cp++;
27717dd7cddfSDavid du Colombier
2772*593dc095SDavid du Colombier p = b - c;
2773*593dc095SDavid du Colombier pc = a - c;
2774*593dc095SDavid du Colombier
2775*593dc095SDavid du Colombier #ifdef PNG_USE_ABS
2776*593dc095SDavid du Colombier pa = abs(p);
2777*593dc095SDavid du Colombier pb = abs(pc);
2778*593dc095SDavid du Colombier pc = abs(p + pc);
2779*593dc095SDavid du Colombier #else
2780*593dc095SDavid du Colombier pa = p < 0 ? -p : p;
2781*593dc095SDavid du Colombier pb = pc < 0 ? -pc : pc;
2782*593dc095SDavid du Colombier pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2783*593dc095SDavid du Colombier #endif
2784*593dc095SDavid du Colombier
2785*593dc095SDavid du Colombier /*
27867dd7cddfSDavid du Colombier if (pa <= pb && pa <= pc)
27877dd7cddfSDavid du Colombier p = a;
27887dd7cddfSDavid du Colombier else if (pb <= pc)
27897dd7cddfSDavid du Colombier p = b;
27907dd7cddfSDavid du Colombier else
27917dd7cddfSDavid du Colombier p = c;
2792*593dc095SDavid du Colombier */
2793*593dc095SDavid du Colombier
2794*593dc095SDavid du Colombier p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
27957dd7cddfSDavid du Colombier
27967dd7cddfSDavid du Colombier *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2797*593dc095SDavid du Colombier rp++;
27987dd7cddfSDavid du Colombier }
27997dd7cddfSDavid du Colombier break;
28007dd7cddfSDavid du Colombier }
28017dd7cddfSDavid du Colombier default:
2802*593dc095SDavid du Colombier png_warning(png_ptr, "Ignoring bad adaptive filter type");
2803*593dc095SDavid du Colombier *row=0;
28047dd7cddfSDavid du Colombier break;
28057dd7cddfSDavid du Colombier }
28067dd7cddfSDavid du Colombier }
2807*593dc095SDavid du Colombier #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
28087dd7cddfSDavid du Colombier
2809*593dc095SDavid du Colombier void /* PRIVATE */
png_read_finish_row(png_structp png_ptr)28107dd7cddfSDavid du Colombier png_read_finish_row(png_structp png_ptr)
28117dd7cddfSDavid du Colombier {
2812*593dc095SDavid du Colombier #ifdef PNG_USE_LOCAL_ARRAYS
2813*593dc095SDavid du Colombier /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2814*593dc095SDavid du Colombier
2815*593dc095SDavid du Colombier /* start of interlace block */
2816*593dc095SDavid du Colombier const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2817*593dc095SDavid du Colombier
2818*593dc095SDavid du Colombier /* offset to next interlace block */
2819*593dc095SDavid du Colombier const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2820*593dc095SDavid du Colombier
2821*593dc095SDavid du Colombier /* start of interlace block in the y direction */
2822*593dc095SDavid du Colombier const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2823*593dc095SDavid du Colombier
2824*593dc095SDavid du Colombier /* offset to next interlace block in the y direction */
2825*593dc095SDavid du Colombier const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2826*593dc095SDavid du Colombier #endif
2827*593dc095SDavid du Colombier
28287dd7cddfSDavid du Colombier png_debug(1, "in png_read_finish_row\n");
28297dd7cddfSDavid du Colombier png_ptr->row_number++;
28307dd7cddfSDavid du Colombier if (png_ptr->row_number < png_ptr->num_rows)
28317dd7cddfSDavid du Colombier return;
28327dd7cddfSDavid du Colombier
28337dd7cddfSDavid du Colombier if (png_ptr->interlaced)
28347dd7cddfSDavid du Colombier {
28357dd7cddfSDavid du Colombier png_ptr->row_number = 0;
2836*593dc095SDavid du Colombier png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
28377dd7cddfSDavid du Colombier do
28387dd7cddfSDavid du Colombier {
28397dd7cddfSDavid du Colombier png_ptr->pass++;
28407dd7cddfSDavid du Colombier if (png_ptr->pass >= 7)
28417dd7cddfSDavid du Colombier break;
28427dd7cddfSDavid du Colombier png_ptr->iwidth = (png_ptr->width +
28437dd7cddfSDavid du Colombier png_pass_inc[png_ptr->pass] - 1 -
28447dd7cddfSDavid du Colombier png_pass_start[png_ptr->pass]) /
28457dd7cddfSDavid du Colombier png_pass_inc[png_ptr->pass];
2846*593dc095SDavid du Colombier
2847*593dc095SDavid du Colombier png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2848*593dc095SDavid du Colombier png_ptr->iwidth) + 1;
2849*593dc095SDavid du Colombier
28507dd7cddfSDavid du Colombier if (!(png_ptr->transformations & PNG_INTERLACE))
28517dd7cddfSDavid du Colombier {
28527dd7cddfSDavid du Colombier png_ptr->num_rows = (png_ptr->height +
28537dd7cddfSDavid du Colombier png_pass_yinc[png_ptr->pass] - 1 -
28547dd7cddfSDavid du Colombier png_pass_ystart[png_ptr->pass]) /
28557dd7cddfSDavid du Colombier png_pass_yinc[png_ptr->pass];
28567dd7cddfSDavid du Colombier if (!(png_ptr->num_rows))
28577dd7cddfSDavid du Colombier continue;
28587dd7cddfSDavid du Colombier }
2859*593dc095SDavid du Colombier else /* if (png_ptr->transformations & PNG_INTERLACE) */
28607dd7cddfSDavid du Colombier break;
28617dd7cddfSDavid du Colombier } while (png_ptr->iwidth == 0);
28627dd7cddfSDavid du Colombier
28637dd7cddfSDavid du Colombier if (png_ptr->pass < 7)
28647dd7cddfSDavid du Colombier return;
28657dd7cddfSDavid du Colombier }
28667dd7cddfSDavid du Colombier
28677dd7cddfSDavid du Colombier if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
28687dd7cddfSDavid du Colombier {
2869*593dc095SDavid du Colombier #ifdef PNG_USE_LOCAL_ARRAYS
2870*593dc095SDavid du Colombier PNG_IDAT;
2871*593dc095SDavid du Colombier #endif
28727dd7cddfSDavid du Colombier char extra;
28737dd7cddfSDavid du Colombier int ret;
28747dd7cddfSDavid du Colombier
28757dd7cddfSDavid du Colombier png_ptr->zstream.next_out = (Byte *)&extra;
28767dd7cddfSDavid du Colombier png_ptr->zstream.avail_out = (uInt)1;
2877*593dc095SDavid du Colombier for(;;)
28787dd7cddfSDavid du Colombier {
28797dd7cddfSDavid du Colombier if (!(png_ptr->zstream.avail_in))
28807dd7cddfSDavid du Colombier {
28817dd7cddfSDavid du Colombier while (!png_ptr->idat_size)
28827dd7cddfSDavid du Colombier {
28837dd7cddfSDavid du Colombier png_byte chunk_length[4];
28847dd7cddfSDavid du Colombier
28857dd7cddfSDavid du Colombier png_crc_finish(png_ptr, 0);
28867dd7cddfSDavid du Colombier
28877dd7cddfSDavid du Colombier png_read_data(png_ptr, chunk_length, 4);
2888*593dc095SDavid du Colombier png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
28897dd7cddfSDavid du Colombier png_reset_crc(png_ptr);
28907dd7cddfSDavid du Colombier png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2891*593dc095SDavid du Colombier if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
28927dd7cddfSDavid du Colombier png_error(png_ptr, "Not enough image data");
28937dd7cddfSDavid du Colombier
28947dd7cddfSDavid du Colombier }
28957dd7cddfSDavid du Colombier png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
28967dd7cddfSDavid du Colombier png_ptr->zstream.next_in = png_ptr->zbuf;
28977dd7cddfSDavid du Colombier if (png_ptr->zbuf_size > png_ptr->idat_size)
28987dd7cddfSDavid du Colombier png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
28997dd7cddfSDavid du Colombier png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
29007dd7cddfSDavid du Colombier png_ptr->idat_size -= png_ptr->zstream.avail_in;
29017dd7cddfSDavid du Colombier }
29027dd7cddfSDavid du Colombier ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
29037dd7cddfSDavid du Colombier if (ret == Z_STREAM_END)
29047dd7cddfSDavid du Colombier {
29057dd7cddfSDavid du Colombier if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
29067dd7cddfSDavid du Colombier png_ptr->idat_size)
2907*593dc095SDavid du Colombier png_warning(png_ptr, "Extra compressed data");
29087dd7cddfSDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
29097dd7cddfSDavid du Colombier png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
29107dd7cddfSDavid du Colombier break;
29117dd7cddfSDavid du Colombier }
29127dd7cddfSDavid du Colombier if (ret != Z_OK)
29137dd7cddfSDavid du Colombier png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
29147dd7cddfSDavid du Colombier "Decompression Error");
29157dd7cddfSDavid du Colombier
29167dd7cddfSDavid du Colombier if (!(png_ptr->zstream.avail_out))
2917*593dc095SDavid du Colombier {
2918*593dc095SDavid du Colombier png_warning(png_ptr, "Extra compressed data.");
2919*593dc095SDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
2920*593dc095SDavid du Colombier png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2921*593dc095SDavid du Colombier break;
2922*593dc095SDavid du Colombier }
29237dd7cddfSDavid du Colombier
2924*593dc095SDavid du Colombier }
29257dd7cddfSDavid du Colombier png_ptr->zstream.avail_out = 0;
29267dd7cddfSDavid du Colombier }
29277dd7cddfSDavid du Colombier
29287dd7cddfSDavid du Colombier if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2929*593dc095SDavid du Colombier png_warning(png_ptr, "Extra compression data");
29307dd7cddfSDavid du Colombier
29317dd7cddfSDavid du Colombier inflateReset(&png_ptr->zstream);
29327dd7cddfSDavid du Colombier
29337dd7cddfSDavid du Colombier png_ptr->mode |= PNG_AFTER_IDAT;
29347dd7cddfSDavid du Colombier }
29357dd7cddfSDavid du Colombier
2936*593dc095SDavid du Colombier void /* PRIVATE */
png_read_start_row(png_structp png_ptr)29377dd7cddfSDavid du Colombier png_read_start_row(png_structp png_ptr)
29387dd7cddfSDavid du Colombier {
2939*593dc095SDavid du Colombier #ifdef PNG_USE_LOCAL_ARRAYS
2940*593dc095SDavid du Colombier /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2941*593dc095SDavid du Colombier
2942*593dc095SDavid du Colombier /* start of interlace block */
2943*593dc095SDavid du Colombier const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2944*593dc095SDavid du Colombier
2945*593dc095SDavid du Colombier /* offset to next interlace block */
2946*593dc095SDavid du Colombier const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2947*593dc095SDavid du Colombier
2948*593dc095SDavid du Colombier /* start of interlace block in the y direction */
2949*593dc095SDavid du Colombier const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2950*593dc095SDavid du Colombier
2951*593dc095SDavid du Colombier /* offset to next interlace block in the y direction */
2952*593dc095SDavid du Colombier const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2953*593dc095SDavid du Colombier #endif
2954*593dc095SDavid du Colombier
29557dd7cddfSDavid du Colombier int max_pixel_depth;
2956*593dc095SDavid du Colombier png_uint_32 row_bytes;
29577dd7cddfSDavid du Colombier
29587dd7cddfSDavid du Colombier png_debug(1, "in png_read_start_row\n");
29597dd7cddfSDavid du Colombier png_ptr->zstream.avail_in = 0;
29607dd7cddfSDavid du Colombier png_init_read_transformations(png_ptr);
29617dd7cddfSDavid du Colombier if (png_ptr->interlaced)
29627dd7cddfSDavid du Colombier {
29637dd7cddfSDavid du Colombier if (!(png_ptr->transformations & PNG_INTERLACE))
29647dd7cddfSDavid du Colombier png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
29657dd7cddfSDavid du Colombier png_pass_ystart[0]) / png_pass_yinc[0];
29667dd7cddfSDavid du Colombier else
29677dd7cddfSDavid du Colombier png_ptr->num_rows = png_ptr->height;
29687dd7cddfSDavid du Colombier
29697dd7cddfSDavid du Colombier png_ptr->iwidth = (png_ptr->width +
29707dd7cddfSDavid du Colombier png_pass_inc[png_ptr->pass] - 1 -
29717dd7cddfSDavid du Colombier png_pass_start[png_ptr->pass]) /
29727dd7cddfSDavid du Colombier png_pass_inc[png_ptr->pass];
2973*593dc095SDavid du Colombier
2974*593dc095SDavid du Colombier row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
2975*593dc095SDavid du Colombier
2976*593dc095SDavid du Colombier png_ptr->irowbytes = (png_size_t)row_bytes;
2977*593dc095SDavid du Colombier if((png_uint_32)png_ptr->irowbytes != row_bytes)
2978*593dc095SDavid du Colombier png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
29797dd7cddfSDavid du Colombier }
29807dd7cddfSDavid du Colombier else
29817dd7cddfSDavid du Colombier {
29827dd7cddfSDavid du Colombier png_ptr->num_rows = png_ptr->height;
29837dd7cddfSDavid du Colombier png_ptr->iwidth = png_ptr->width;
29847dd7cddfSDavid du Colombier png_ptr->irowbytes = png_ptr->rowbytes + 1;
29857dd7cddfSDavid du Colombier }
29867dd7cddfSDavid du Colombier max_pixel_depth = png_ptr->pixel_depth;
29877dd7cddfSDavid du Colombier
29887dd7cddfSDavid du Colombier #if defined(PNG_READ_PACK_SUPPORTED)
29897dd7cddfSDavid du Colombier if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
29907dd7cddfSDavid du Colombier max_pixel_depth = 8;
29917dd7cddfSDavid du Colombier #endif
29927dd7cddfSDavid du Colombier
29937dd7cddfSDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
29947dd7cddfSDavid du Colombier if (png_ptr->transformations & PNG_EXPAND)
29957dd7cddfSDavid du Colombier {
29967dd7cddfSDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
29977dd7cddfSDavid du Colombier {
29987dd7cddfSDavid du Colombier if (png_ptr->num_trans)
29997dd7cddfSDavid du Colombier max_pixel_depth = 32;
30007dd7cddfSDavid du Colombier else
30017dd7cddfSDavid du Colombier max_pixel_depth = 24;
30027dd7cddfSDavid du Colombier }
30037dd7cddfSDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
30047dd7cddfSDavid du Colombier {
30057dd7cddfSDavid du Colombier if (max_pixel_depth < 8)
30067dd7cddfSDavid du Colombier max_pixel_depth = 8;
30077dd7cddfSDavid du Colombier if (png_ptr->num_trans)
30087dd7cddfSDavid du Colombier max_pixel_depth *= 2;
30097dd7cddfSDavid du Colombier }
30107dd7cddfSDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
30117dd7cddfSDavid du Colombier {
30127dd7cddfSDavid du Colombier if (png_ptr->num_trans)
30137dd7cddfSDavid du Colombier {
30147dd7cddfSDavid du Colombier max_pixel_depth *= 4;
30157dd7cddfSDavid du Colombier max_pixel_depth /= 3;
30167dd7cddfSDavid du Colombier }
30177dd7cddfSDavid du Colombier }
30187dd7cddfSDavid du Colombier }
30197dd7cddfSDavid du Colombier #endif
30207dd7cddfSDavid du Colombier
30217dd7cddfSDavid du Colombier #if defined(PNG_READ_FILLER_SUPPORTED)
30227dd7cddfSDavid du Colombier if (png_ptr->transformations & (PNG_FILLER))
30237dd7cddfSDavid du Colombier {
3024*593dc095SDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
30257dd7cddfSDavid du Colombier max_pixel_depth = 32;
3026*593dc095SDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3027*593dc095SDavid du Colombier {
3028*593dc095SDavid du Colombier if (max_pixel_depth <= 8)
3029*593dc095SDavid du Colombier max_pixel_depth = 16;
3030*593dc095SDavid du Colombier else
3031*593dc095SDavid du Colombier max_pixel_depth = 32;
3032*593dc095SDavid du Colombier }
3033*593dc095SDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3034*593dc095SDavid du Colombier {
3035*593dc095SDavid du Colombier if (max_pixel_depth <= 32)
3036*593dc095SDavid du Colombier max_pixel_depth = 32;
3037*593dc095SDavid du Colombier else
3038*593dc095SDavid du Colombier max_pixel_depth = 64;
3039*593dc095SDavid du Colombier }
30407dd7cddfSDavid du Colombier }
30417dd7cddfSDavid du Colombier #endif
30427dd7cddfSDavid du Colombier
30437dd7cddfSDavid du Colombier #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
30447dd7cddfSDavid du Colombier if (png_ptr->transformations & PNG_GRAY_TO_RGB)
30457dd7cddfSDavid du Colombier {
3046*593dc095SDavid du Colombier if (
3047*593dc095SDavid du Colombier #if defined(PNG_READ_EXPAND_SUPPORTED)
3048*593dc095SDavid du Colombier (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3049*593dc095SDavid du Colombier #endif
3050*593dc095SDavid du Colombier #if defined(PNG_READ_FILLER_SUPPORTED)
3051*593dc095SDavid du Colombier (png_ptr->transformations & (PNG_FILLER)) ||
3052*593dc095SDavid du Colombier #endif
30537dd7cddfSDavid du Colombier png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
30547dd7cddfSDavid du Colombier {
30557dd7cddfSDavid du Colombier if (max_pixel_depth <= 16)
30567dd7cddfSDavid du Colombier max_pixel_depth = 32;
3057*593dc095SDavid du Colombier else
30587dd7cddfSDavid du Colombier max_pixel_depth = 64;
30597dd7cddfSDavid du Colombier }
30607dd7cddfSDavid du Colombier else
30617dd7cddfSDavid du Colombier {
30627dd7cddfSDavid du Colombier if (max_pixel_depth <= 8)
3063*593dc095SDavid du Colombier {
3064*593dc095SDavid du Colombier if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3065*593dc095SDavid du Colombier max_pixel_depth = 32;
3066*593dc095SDavid du Colombier else
30677dd7cddfSDavid du Colombier max_pixel_depth = 24;
3068*593dc095SDavid du Colombier }
3069*593dc095SDavid du Colombier else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3070*593dc095SDavid du Colombier max_pixel_depth = 64;
3071*593dc095SDavid du Colombier else
30727dd7cddfSDavid du Colombier max_pixel_depth = 48;
30737dd7cddfSDavid du Colombier }
30747dd7cddfSDavid du Colombier }
30757dd7cddfSDavid du Colombier #endif
30767dd7cddfSDavid du Colombier
3077*593dc095SDavid du Colombier #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3078*593dc095SDavid du Colombier defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3079*593dc095SDavid du Colombier if(png_ptr->transformations & PNG_USER_TRANSFORM)
3080*593dc095SDavid du Colombier {
3081*593dc095SDavid du Colombier int user_pixel_depth=png_ptr->user_transform_depth*
3082*593dc095SDavid du Colombier png_ptr->user_transform_channels;
3083*593dc095SDavid du Colombier if(user_pixel_depth > max_pixel_depth)
3084*593dc095SDavid du Colombier max_pixel_depth=user_pixel_depth;
3085*593dc095SDavid du Colombier }
3086*593dc095SDavid du Colombier #endif
3087*593dc095SDavid du Colombier
30887dd7cddfSDavid du Colombier /* align the width on the next larger 8 pixels. Mainly used
30897dd7cddfSDavid du Colombier for interlacing */
3090*593dc095SDavid du Colombier row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
30917dd7cddfSDavid du Colombier /* calculate the maximum bytes needed, adding a byte and a pixel
3092*593dc095SDavid du Colombier for safety's sake */
3093*593dc095SDavid du Colombier row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
30947dd7cddfSDavid du Colombier 1 + ((max_pixel_depth + 7) >> 3);
30957dd7cddfSDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
3096*593dc095SDavid du Colombier if (row_bytes > (png_uint_32)65536L)
30977dd7cddfSDavid du Colombier png_error(png_ptr, "This image requires a row greater than 64KB");
30987dd7cddfSDavid du Colombier #endif
3099*593dc095SDavid du Colombier png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3100*593dc095SDavid du Colombier png_ptr->row_buf = png_ptr->big_row_buf+32;
3101*593dc095SDavid du Colombier #if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
3102*593dc095SDavid du Colombier png_ptr->row_buf_size = row_bytes;
3103*593dc095SDavid du Colombier #endif
31047dd7cddfSDavid du Colombier
31057dd7cddfSDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
31067dd7cddfSDavid du Colombier if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
31077dd7cddfSDavid du Colombier png_error(png_ptr, "This image requires a row greater than 64KB");
31087dd7cddfSDavid du Colombier #endif
3109*593dc095SDavid du Colombier if ((png_uint_32)png_ptr->rowbytes > PNG_SIZE_MAX - 1)
3110*593dc095SDavid du Colombier png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3111*593dc095SDavid du Colombier png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3112*593dc095SDavid du Colombier png_ptr->rowbytes + 1));
31137dd7cddfSDavid du Colombier
3114*593dc095SDavid du Colombier png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
31157dd7cddfSDavid du Colombier
3116*593dc095SDavid du Colombier png_debug1(3, "width = %lu,\n", png_ptr->width);
3117*593dc095SDavid du Colombier png_debug1(3, "height = %lu,\n", png_ptr->height);
3118*593dc095SDavid du Colombier png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3119*593dc095SDavid du Colombier png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3120*593dc095SDavid du Colombier png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3121*593dc095SDavid du Colombier png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
31227dd7cddfSDavid du Colombier
31237dd7cddfSDavid du Colombier png_ptr->flags |= PNG_FLAG_ROW_INIT;
31247dd7cddfSDavid du Colombier }
3125