xref: /plan9/sys/src/cmd/gs/libpng/pngrutil.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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