blob: 2bbd427d1542edc1633d77eab1072fed8bade319 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
2/* pngrutil.c - utilities to read a png file
3
Guy Schalnat6d764711995-12-19 03:22:19 -06004 libpng 1.0 beta 2 - version 0.85
Guy Schalnat0d580581995-07-20 02:43:20 -05005 For conditions of distribution and use, see copyright notice in png.h
6 Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
Guy Schalnat6d764711995-12-19 03:22:19 -06007 December 19, 1995
Guy Schalnat0d580581995-07-20 02:43:20 -05008 */
9
10#define PNG_INTERNAL
11#include "png.h"
12
13/* grab an uint 32 from a buffer */
14png_uint_32
Guy Schalnat6d764711995-12-19 03:22:19 -060015png_get_uint_32(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050016{
17 png_uint_32 i;
18
19 i = ((png_uint_32)(*buf) << 24) +
20 ((png_uint_32)(*(buf + 1)) << 16) +
21 ((png_uint_32)(*(buf + 2)) << 8) +
22 (png_uint_32)(*(buf + 3));
23
24 return i;
25}
26
27/* grab an uint 16 from a buffer */
28png_uint_16
Guy Schalnat6d764711995-12-19 03:22:19 -060029png_get_uint_16(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050030{
31 png_uint_16 i;
32
Guy Schalnat6d764711995-12-19 03:22:19 -060033 i = ((png_uint_16)(*buf) << 8) +
Guy Schalnat0d580581995-07-20 02:43:20 -050034 (png_uint_16)(*(buf + 1));
35
36 return i;
37}
38
39/* read data, and run it through the crc */
40void
Guy Schalnat6d764711995-12-19 03:22:19 -060041png_crc_read(png_structp png_ptr, png_bytep buf, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -050042{
Guy Schalnat6d764711995-12-19 03:22:19 -060043 png_read_data(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -050044 png_calculate_crc(png_ptr, buf, length);
45}
46
47/* skip data, but calcuate the crc anyway */
48void
Guy Schalnat6d764711995-12-19 03:22:19 -060049png_crc_skip(png_structp png_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -050050{
51 png_uint_32 i;
52
53 for (i = length; i > png_ptr->zbuf_size; i -= png_ptr->zbuf_size)
54 {
Guy Schalnat6d764711995-12-19 03:22:19 -060055 png_read_data(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -050056 png_calculate_crc(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
57 }
58 if (i)
59 {
Guy Schalnat6d764711995-12-19 03:22:19 -060060 png_read_data(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -050061 png_calculate_crc(png_ptr, png_ptr->zbuf, i);
62 }
63}
64
65/* read and check the IDHR chunk */
66void
Guy Schalnat6d764711995-12-19 03:22:19 -060067png_handle_IHDR(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -050068{
69 png_byte buf[13];
70 png_uint_32 width, height;
71 int bit_depth, color_type, compression_type, filter_type;
72 int interlace_type;
73
74 /* check the length */
75 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -060076 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -050077
78 png_crc_read(png_ptr, buf, 13);
79
80 width = png_get_uint_32(buf);
81 height = png_get_uint_32(buf + 4);
82 bit_depth = buf[8];
83 color_type = buf[9];
84 compression_type = buf[10];
85 filter_type = buf[11];
86 interlace_type = buf[12];
87
88 /* check for width and height valid values */
89 if (width == 0 || height == 0)
Guy Schalnat6d764711995-12-19 03:22:19 -060090 png_error(png_ptr, "Invalid Width or Height Found");
Guy Schalnat0d580581995-07-20 02:43:20 -050091
92 /* check other values */
93 if (bit_depth != 1 && bit_depth != 2 &&
94 bit_depth != 4 && bit_depth != 8 &&
95 bit_depth != 16)
Guy Schalnat6d764711995-12-19 03:22:19 -060096 png_error(png_ptr, "Invalid Bit Depth Found");
Guy Schalnat0d580581995-07-20 02:43:20 -050097
98 if (color_type < 0 || color_type == 1 ||
99 color_type == 5 || color_type > 6)
Guy Schalnat6d764711995-12-19 03:22:19 -0600100 png_error(png_ptr, "Invalid Color Type Found");
Guy Schalnat0d580581995-07-20 02:43:20 -0500101
Guy Schalnat6d764711995-12-19 03:22:19 -0600102 if (color_type == PNG_COLOR_TYPE_PALETTE &&
Guy Schalnat0d580581995-07-20 02:43:20 -0500103 bit_depth == 16)
Guy Schalnat6d764711995-12-19 03:22:19 -0600104 png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
Guy Schalnat0d580581995-07-20 02:43:20 -0500105
106 if ((color_type == PNG_COLOR_TYPE_RGB ||
107 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
108 color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
109 bit_depth < 8)
Guy Schalnat6d764711995-12-19 03:22:19 -0600110 png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
Guy Schalnat0d580581995-07-20 02:43:20 -0500111
112 if (interlace_type > 1)
Guy Schalnat6d764711995-12-19 03:22:19 -0600113 png_error(png_ptr, "Found Invalid Interlace Value");
Guy Schalnat0d580581995-07-20 02:43:20 -0500114
115 if (compression_type > 0)
Guy Schalnat6d764711995-12-19 03:22:19 -0600116 png_error(png_ptr, "Found Invalid Compression Value");
Guy Schalnat0d580581995-07-20 02:43:20 -0500117
118 if (filter_type > 0)
Guy Schalnat6d764711995-12-19 03:22:19 -0600119 png_error(png_ptr, "Found Invalid Filter Value");
Guy Schalnat0d580581995-07-20 02:43:20 -0500120
121 /* set internal variables */
122 png_ptr->width = width;
123 png_ptr->height = height;
124 png_ptr->bit_depth = bit_depth;
125 png_ptr->interlaced = interlace_type;
126 png_ptr->color_type = color_type;
127
128 /* find number of channels */
129 switch (png_ptr->color_type)
130 {
131 case 0:
132 case 3:
133 png_ptr->channels = 1;
134 break;
135 case 2:
136 png_ptr->channels = 3;
137 break;
138 case 4:
139 png_ptr->channels = 2;
140 break;
141 case 6:
142 png_ptr->channels = 4;
143 break;
144 }
145 /* set up other useful info */
146 png_ptr->pixel_depth = png_ptr->bit_depth *
147 png_ptr->channels;
148 png_ptr->rowbytes = ((png_ptr->width *
149 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
150 /* call the IHDR callback (which should just set up info) */
151 png_read_IHDR(png_ptr, info, width, height, bit_depth,
152 color_type, compression_type, filter_type, interlace_type);
153}
154
155/* read and check the palette */
156void
Guy Schalnat6d764711995-12-19 03:22:19 -0600157png_handle_PLTE(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500158{
159 int num, i;
Guy Schalnat6d764711995-12-19 03:22:19 -0600160 png_colorp palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500161
162 if (length % 3)
Guy Schalnat6d764711995-12-19 03:22:19 -0600163 png_error(png_ptr, "Invalid Palette Chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500164
165 num = (int)length / 3;
Guy Schalnat6d764711995-12-19 03:22:19 -0600166 palette = (png_colorp)png_malloc(png_ptr, num * sizeof (png_color));
Guy Schalnat0d580581995-07-20 02:43:20 -0500167 for (i = 0; i < num; i++)
168 {
169 png_byte buf[3];
170
171 png_crc_read(png_ptr, buf, 3);
172 /* don't depend upon png_color being any order */
173 palette[i].red = buf[0];
174 palette[i].green = buf[1];
175 palette[i].blue = buf[2];
176 }
177 png_ptr->palette = palette;
178 png_ptr->num_palette = num;
179 png_read_PLTE(png_ptr, info, palette, num);
180}
181
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500182#if defined(PNG_READ_gAMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500183void
Guy Schalnat6d764711995-12-19 03:22:19 -0600184png_handle_gAMA(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500185{
186 png_uint_32 igamma;
187 float gamma;
188 png_byte buf[4];
189
190 if (length != 4)
191 {
192 png_crc_skip(png_ptr, length);
193 return;
194 }
195
196 png_crc_read(png_ptr, buf, 4);
197 igamma = png_get_uint_32(buf);
198 /* check for zero gamma */
199 if (!igamma)
Guy Schalnat6d764711995-12-19 03:22:19 -0600200 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500201
202 gamma = (float)igamma / (float)100000.0;
203 png_read_gAMA(png_ptr, info, gamma);
204 png_ptr->gamma = gamma;
205}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500206#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500207
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500208#if defined(PNG_READ_sBIT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500209void
Guy Schalnat6d764711995-12-19 03:22:19 -0600210png_handle_sBIT(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500211{
212 int slen;
213 png_byte buf[4];
214
215 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
216 slen = 3;
217 else
Guy Schalnat6d764711995-12-19 03:22:19 -0600218 slen = png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500219
220 if (length != (png_uint_32)slen)
221 {
222 png_crc_skip(png_ptr, length);
223 return;
224 }
225
226 png_crc_read(png_ptr, buf, length);
227 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
228 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600229 png_ptr->sig_bit.red = buf[0];
230 png_ptr->sig_bit.green = buf[1];
231 png_ptr->sig_bit.blue = buf[2];
232 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500233 }
234 else
235 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600236 png_ptr->sig_bit.gray = buf[0];
237 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500238 }
239 png_read_sBIT(png_ptr, info, &(png_ptr->sig_bit));
240}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500241#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500242
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500243#if defined(PNG_READ_cHRM_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500244void
Guy Schalnat6d764711995-12-19 03:22:19 -0600245png_handle_cHRM(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500246{
247 png_byte buf[4];
248 png_uint_32 v;
249 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
250
251 if (length != 32)
252 {
253 png_crc_skip(png_ptr, length);
Guy Schalnat6d764711995-12-19 03:22:19 -0600254 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500255 }
256
257 png_crc_read(png_ptr, buf, 4);
258 v = png_get_uint_32(buf);
259 white_x = (float)v / (float)100000.0;
260
261 png_crc_read(png_ptr, buf, 4);
262 v = png_get_uint_32(buf);
263 white_y = (float)v / (float)100000.0;
264
265 png_crc_read(png_ptr, buf, 4);
266 v = png_get_uint_32(buf);
267 red_x = (float)v / (float)100000.0;
268
269 png_crc_read(png_ptr, buf, 4);
270 v = png_get_uint_32(buf);
271 red_y = (float)v / (float)100000.0;
272
273 png_crc_read(png_ptr, buf, 4);
274 v = png_get_uint_32(buf);
275 green_x = (float)v / (float)100000.0;
276
277 png_crc_read(png_ptr, buf, 4);
278 v = png_get_uint_32(buf);
279 green_y = (float)v / (float)100000.0;
280
281 png_crc_read(png_ptr, buf, 4);
282 v = png_get_uint_32(buf);
283 blue_x = (float)v / (float)100000.0;
284
285 png_crc_read(png_ptr, buf, 4);
286 v = png_get_uint_32(buf);
287 blue_y = (float)v / (float)100000.0;
288
289 png_read_cHRM(png_ptr, info,
Guy Schalnat6d764711995-12-19 03:22:19 -0600290 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Guy Schalnat0d580581995-07-20 02:43:20 -0500291}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500292#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500293
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500294#if defined(PNG_READ_tRNS_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500295void
Guy Schalnat6d764711995-12-19 03:22:19 -0600296png_handle_tRNS(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500297{
298 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
299 {
300 if (length > png_ptr->num_palette)
301 {
302 png_crc_skip(png_ptr, length);
303 return;
304 }
305
Guy Schalnat6d764711995-12-19 03:22:19 -0600306 png_ptr->trans = (png_bytep)png_malloc(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500307 png_crc_read(png_ptr, png_ptr->trans, length);
Guy Schalnat6d764711995-12-19 03:22:19 -0600308 png_ptr->num_trans = (int)length;
Guy Schalnat0d580581995-07-20 02:43:20 -0500309 }
310 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
311 {
312 png_byte buf[6];
313
314 if (length != 6)
315 {
316 png_crc_skip(png_ptr, length);
317 return;
318 }
319
320 png_crc_read(png_ptr, buf, length);
321 png_ptr->num_trans = 3;
322 png_ptr->trans_values.red = png_get_uint_16(buf);
323 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
324 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
325 }
326 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
327 {
328 png_byte buf[6];
329
330 if (length != 2)
331 {
332 png_crc_skip(png_ptr, length);
333 return;
334 }
335
336 png_crc_read(png_ptr, buf, 2);
337 png_ptr->num_trans = 1;
338 png_ptr->trans_values.gray = png_get_uint_16(buf);
339 }
340 else
Guy Schalnat6d764711995-12-19 03:22:19 -0600341 png_error(png_ptr, "Invalid tRNS chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500342
343 png_read_tRNS(png_ptr, info, png_ptr->trans, png_ptr->num_trans,
344 &(png_ptr->trans_values));
345}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500346#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500347
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500348#if defined(PNG_READ_bKGD_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500349void
Guy Schalnat6d764711995-12-19 03:22:19 -0600350png_handle_bKGD(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500351{
352 int truelen;
353 png_byte buf[6];
354
355 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
356 truelen = 1;
357 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
358 truelen = 6;
359 else
360 truelen = 2;
361
362 if (length != (png_uint_32)truelen)
363 {
364 png_crc_skip(png_ptr, length);
365 return;
366 }
367
368 png_crc_read(png_ptr, buf, length);
369 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
370 png_ptr->background.index = buf[0];
371 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
372 png_ptr->background.gray = png_get_uint_16(buf);
373 else
374 {
375 png_ptr->background.red = png_get_uint_16(buf);
376 png_ptr->background.green = png_get_uint_16(buf + 2);
377 png_ptr->background.blue = png_get_uint_16(buf + 4);
378 }
379
380 png_read_bKGD(png_ptr, info, &(png_ptr->background));
381}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500382#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500383
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500384#if defined(PNG_READ_hIST_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500385void
Guy Schalnat6d764711995-12-19 03:22:19 -0600386png_handle_hIST(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500387{
388 int num, i;
389
390 if (length != 2 * png_ptr->num_palette)
391 {
392 png_crc_skip(png_ptr, length);
393 return;
394 }
395
396 num = (int)length / 2;
Guy Schalnat6d764711995-12-19 03:22:19 -0600397 png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
398 num * sizeof (png_uint_16));
Guy Schalnat0d580581995-07-20 02:43:20 -0500399 for (i = 0; i < num; i++)
400 {
401 png_byte buf[2];
402
403 png_crc_read(png_ptr, buf, 2);
404 png_ptr->hist[i] = png_get_uint_16(buf);
405 }
406 png_read_hIST(png_ptr, info, png_ptr->hist);
407}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500408#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500409
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500410#if defined(PNG_READ_pHYs_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500411void
Guy Schalnat6d764711995-12-19 03:22:19 -0600412png_handle_pHYs(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500413{
414 png_byte buf[9];
415 png_uint_32 res_x, res_y;
416 int unit_type;
417
418 if (length != 9)
419 {
420 png_crc_skip(png_ptr, length);
421 return;
Guy Schalnat6d764711995-12-19 03:22:19 -0600422 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500423
424 png_crc_read(png_ptr, buf, 9);
425
426 res_x = png_get_uint_32(buf);
427 res_y = png_get_uint_32(buf + 4);
428 unit_type = buf[8];
429 png_read_pHYs(png_ptr, info, res_x, res_y, unit_type);
430}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500431#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500432
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500433#if defined(PNG_READ_oFFs_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500434void
Guy Schalnat6d764711995-12-19 03:22:19 -0600435png_handle_oFFs(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500436{
437 png_byte buf[9];
438 png_uint_32 offset_x, offset_y;
439 int unit_type;
440
441 if (length != 9)
442 {
443 png_crc_skip(png_ptr, length);
444 return;
445 }
446
447 png_crc_read(png_ptr, buf, 9);
448
449 offset_x = png_get_uint_32(buf);
450 offset_y = png_get_uint_32(buf + 4);
451 unit_type = buf[8];
452 png_read_oFFs(png_ptr, info, offset_x, offset_y, unit_type);
453}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500454#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500455
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500456#if defined(PNG_READ_tIME_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500457void
Guy Schalnat6d764711995-12-19 03:22:19 -0600458png_handle_tIME(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500459{
460 png_byte buf[7];
461 png_time mod_time;
462
463 if (length != 7)
464 {
465 png_crc_skip(png_ptr, length);
466 return;
467 }
468
469 png_crc_read(png_ptr, buf, 7);
470
471 mod_time.second = buf[6];
472 mod_time.minute = buf[5];
473 mod_time.hour = buf[4];
474 mod_time.day = buf[3];
475 mod_time.month = buf[2];
Guy Schalnat6d764711995-12-19 03:22:19 -0600476 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500477
478 png_read_tIME(png_ptr, info, &mod_time);
479}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500480#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500481
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500482#if defined(PNG_READ_tEXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500483/* note: this does not correctly handle chunks that are > 64K */
484void
Guy Schalnat6d764711995-12-19 03:22:19 -0600485png_handle_tEXt(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500486{
Guy Schalnat6d764711995-12-19 03:22:19 -0600487 png_charp key;
488 png_charp text;
Guy Schalnat0d580581995-07-20 02:43:20 -0500489
490 text = NULL;
491
Guy Schalnat6d764711995-12-19 03:22:19 -0600492 key = (png_charp )png_large_malloc(png_ptr, length + 1);
493 png_crc_read(png_ptr, (png_bytep )key, length);
494 key[(png_size_t)length] = '\0';
Guy Schalnat0d580581995-07-20 02:43:20 -0500495
496 for (text = key; *text; text++)
497 /* empty loop */ ;
498
499 if (text != key + (png_size_t)length)
500 text++;
501
502 png_read_tEXt(png_ptr, info, key, text, length - (text - key));
503}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500504#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500505
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500506#if defined(PNG_READ_zTXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500507/* note: this does not correctly handle chunks that are > 64K compressed */
508void
Guy Schalnat6d764711995-12-19 03:22:19 -0600509png_handle_zTXt(png_structp png_ptr, png_infop info, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500510{
Guy Schalnat6d764711995-12-19 03:22:19 -0600511 png_charp key;
512 png_charp text;
513 int ret;
Guy Schalnat0d580581995-07-20 02:43:20 -0500514 png_uint_32 text_size, key_size;
515
516 text = NULL;
517
518 key = png_large_malloc(png_ptr, length + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -0600519 png_crc_read(png_ptr, (png_bytep )key, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500520 key[(png_size_t)length] = '\0';
521
522 for (text = key; *text; text++)
523 /* empty loop */ ;
524
525 /* zTXt can't have zero text */
526 if (text == key + (png_size_t)length)
527 {
528 png_large_free(png_ptr, key);
529 return;
530 }
531
532 text++;
533
534 if (*text) /* check compression byte */
535 {
536 png_large_free(png_ptr, key);
537 return;
538 }
539
540 text++;
541
Guy Schalnat6d764711995-12-19 03:22:19 -0600542 png_ptr->zstream->next_in = (png_bytep )text;
Guy Schalnat0d580581995-07-20 02:43:20 -0500543 png_ptr->zstream->avail_in = (uInt)(length - (text - key));
544 png_ptr->zstream->next_out = png_ptr->zbuf;
545 png_ptr->zstream->avail_out = (png_size_t)png_ptr->zbuf_size;
546
547 key_size = text - key;
548 text_size = 0;
549 text = NULL;
550
551 while (png_ptr->zstream->avail_in)
552 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600553 ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -0500554 if (ret != Z_OK && ret != Z_STREAM_END)
555 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600556 inflateReset(png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -0500557 png_ptr->zstream->avail_in = 0;
558 png_large_free(png_ptr, key);
559 png_large_free(png_ptr, text);
560 return;
561 }
562 if (!png_ptr->zstream->avail_out || ret == Z_STREAM_END)
563 {
564 if (!text)
565 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600566 text = (png_charp)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -0500567 png_ptr->zbuf_size - png_ptr->zstream->avail_out +
568 key_size + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500569 png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf,
Guy Schalnat0d580581995-07-20 02:43:20 -0500570 (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500571 png_memcpy(text, key, (png_size_t)key_size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500572 text_size = key_size + (png_size_t)png_ptr->zbuf_size -
573 png_ptr->zstream->avail_out;
574 *(text + (png_size_t)text_size) = '\0';
575 }
576 else
577 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600578 png_charp tmp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500579
580 tmp = text;
581 text = png_large_malloc(png_ptr, text_size +
582 png_ptr->zbuf_size - png_ptr->zstream->avail_out + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500583 png_memcpy(text, tmp, (png_size_t)text_size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500584 png_large_free(png_ptr, tmp);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500585 png_memcpy(text + (png_size_t)text_size, png_ptr->zbuf,
Guy Schalnat0d580581995-07-20 02:43:20 -0500586 (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
587 text_size += png_ptr->zbuf_size - png_ptr->zstream->avail_out;
588 *(text + (png_size_t)text_size) = '\0';
589 }
590 if (ret != Z_STREAM_END)
591 {
592 png_ptr->zstream->next_out = png_ptr->zbuf;
593 png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
594 }
595 }
596 else
597 {
598 break;
599 }
600
601 if (ret == Z_STREAM_END)
602 break;
603 }
604
Guy Schalnat6d764711995-12-19 03:22:19 -0600605 inflateReset(png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -0500606 png_ptr->zstream->avail_in = 0;
607
608 if (ret != Z_STREAM_END)
609 {
610 png_large_free(png_ptr, key);
611 png_large_free(png_ptr, text);
612 return;
613 }
614
615 png_large_free(png_ptr, key);
616 key = text;
617 text += (png_size_t)key_size;
618 text_size -= key_size;
619
620 png_read_zTXt(png_ptr, info, key, text, text_size, 0);
621}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500622#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500623
624/* Combines the row recently read in with the previous row.
625 This routine takes care of alpha and transparency if requested.
626 This routine also handles the two methods of progressive display
627 of interlaced images, depending on the mask value.
628 The mask value describes which pixels are to be combined with
629 the row. The pattern always repeats every 8 pixels, so just 8
630 bits are needed. A one indicates the pixels is to be combined,
631 a zero indicates the pixel is to be skipped. This is in addition
632 to any alpha or transparency value associated with the pixel. If
633 you want all pixels to be combined, pass 0xff (255) in mask.
634*/
635void
Guy Schalnat6d764711995-12-19 03:22:19 -0600636png_combine_row(png_structp png_ptr, png_bytep row,
Guy Schalnat0d580581995-07-20 02:43:20 -0500637 int mask)
638{
639 if (mask == 0xff)
640 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500641 png_memcpy(row, png_ptr->row_buf + 1,
Guy Schalnat0d580581995-07-20 02:43:20 -0500642 (png_size_t)((png_ptr->width *
643 png_ptr->row_info.pixel_depth + 7) >> 3));
644 }
645 else
646 {
647 switch (png_ptr->row_info.pixel_depth)
648 {
649 case 1:
650 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600651 png_bytep sp;
652 png_bytep dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500653 int m;
654 int shift;
655 png_uint_32 i;
656 int value;
657
658 sp = png_ptr->row_buf + 1;
659 dp = row;
660 shift = 7;
661 m = 0x80;
662 for (i = 0; i < png_ptr->width; i++)
663 {
664 if (m & mask)
665 {
666 value = (*sp >> shift) & 0x1;
667 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
668 *dp |= (value << shift);
669 }
670
671 if (shift == 0)
672 {
673 shift = 7;
674 sp++;
675 dp++;
676 }
677 else
678 shift--;
679
680 if (m == 1)
681 m = 0x80;
682 else
683 m >>= 1;
684 }
685 break;
686 }
687 case 2:
688 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600689 png_bytep sp;
690 png_bytep dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500691 int m;
692 int shift;
693 png_uint_32 i;
694 int value;
695
696 sp = png_ptr->row_buf + 1;
697 dp = row;
698 shift = 6;
699 m = 0x80;
700 for (i = 0; i < png_ptr->width; i++)
701 {
702 if (m & mask)
703 {
704 value = (*sp >> shift) & 0x3;
705 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
706 *dp |= (value << shift);
707 }
708
709 if (shift == 0)
710 {
711 shift = 6;
712 sp++;
713 dp++;
714 }
715 else
716 shift -= 2;
717 if (m == 1)
718 m = 0x80;
719 else
720 m >>= 1;
721 }
722 break;
723 }
724 case 4:
725 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600726 png_bytep sp;
727 png_bytep dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500728 int m;
729 int shift;
730 png_uint_32 i;
731 int value;
732
733 sp = png_ptr->row_buf + 1;
734 dp = row;
735 shift = 4;
736 m = 0x80;
737 for (i = 0; i < png_ptr->width; i++)
738 {
739 if (m & mask)
740 {
741 value = (*sp >> shift) & 0xf;
742 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
743 *dp |= (value << shift);
744 }
745
746 if (shift == 0)
747 {
748 shift = 4;
749 sp++;
750 dp++;
751 }
752 else
753 shift -= 4;
754 if (m == 1)
755 m = 0x80;
756 else
757 m >>= 1;
758 }
759 break;
760 }
761 default:
762 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600763 png_bytep sp;
764 png_bytep dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500765 png_uint_32 i;
766 int pixel_bytes, m;
767
768 pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
769
770 sp = png_ptr->row_buf + 1;
771 dp = row;
772 m = 0x80;
773 for (i = 0; i < png_ptr->width; i++)
774 {
775 if (m & mask)
776 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500777 png_memcpy(dp, sp, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -0500778 }
779
780 sp += pixel_bytes;
781 dp += pixel_bytes;
782
783 if (m == 1)
784 m = 0x80;
785 else
786 m >>= 1;
787 }
788 break;
789 }
790 }
791 }
792}
793
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500794#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500795void
Guy Schalnat6d764711995-12-19 03:22:19 -0600796png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass)
Guy Schalnat0d580581995-07-20 02:43:20 -0500797{
798 if (row && row_info)
799 {
800 png_uint_32 final_width;
801
802 final_width = row_info->width * png_pass_inc[pass];
803
804 switch (row_info->pixel_depth)
805 {
806 case 1:
807 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600808 png_bytep sp, dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500809 int sshift, dshift;
810 png_byte v;
811 png_uint_32 i;
812 int j;
813
814 sp = row + (png_size_t)((row_info->width - 1) >> 3);
815 sshift = 7 - (int)((row_info->width + 7) & 7);
816 dp = row + (png_size_t)((final_width - 1) >> 3);
817 dshift = 7 - (int)((final_width + 7) & 7);
818 for (i = row_info->width; i; i--)
819 {
820 v = (*sp >> sshift) & 0x1;
821 for (j = 0; j < png_pass_inc[pass]; j++)
822 {
823 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
824 *dp |= (png_byte)(v << dshift);
825 if (dshift == 7)
826 {
827 dshift = 0;
828 dp--;
829 }
830 else
831 dshift++;
832 }
833 if (sshift == 7)
834 {
835 sshift = 0;
836 sp--;
837 }
838 else
839 sshift++;
840 }
841 break;
842 }
843 case 2:
844 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600845 png_bytep sp, dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500846 int sshift, dshift;
847 png_byte v;
848 png_uint_32 i, j;
849
850 sp = row + (png_size_t)((row_info->width - 1) >> 2);
851 sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
852 dp = row + (png_size_t)((final_width - 1) >> 2);
853 dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
854 for (i = row_info->width; i; i--)
855 {
856 v = (*sp >> sshift) & 0x3;
857 for (j = 0; j < png_pass_inc[pass]; j++)
858 {
859 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
860 *dp |= (v << dshift);
861 if (dshift == 6)
862 {
863 dshift = 0;
864 dp--;
865 }
866 else
867 dshift += 2;
868 }
869 if (sshift == 6)
870 {
871 sshift = 0;
872 sp--;
873 }
874 else
875 sshift += 2;
876 }
877 break;
878 }
879 case 4:
880 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600881 png_bytep sp, dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500882 int sshift, dshift;
883 png_byte v;
884 png_uint_32 i;
885 int j;
886
887 sp = row + (png_size_t)((row_info->width - 1) >> 1);
888 sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
889 dp = row + (png_size_t)((final_width - 1) >> 1);
890 dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
891 for (i = row_info->width; i; i--)
892 {
893 v = (*sp >> sshift) & 0xf;
894 for (j = 0; j < png_pass_inc[pass]; j++)
895 {
896 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
897 *dp |= (v << dshift);
898 if (dshift == 4)
899 {
900 dshift = 0;
901 dp--;
902 }
903 else
904 dshift = 4;
905 }
906 if (sshift == 4)
907 {
908 sshift = 0;
909 sp--;
910 }
911 else
912 sshift = 4;
913 }
914 break;
915 }
916 default:
917 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600918 png_bytep sp, dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500919 png_byte v[8];
920 png_uint_32 i;
921 int j;
922 int pixel_bytes;
923
924 pixel_bytes = (row_info->pixel_depth >> 3);
925
926 sp = row + (png_size_t)((row_info->width - 1) * pixel_bytes);
927 dp = row + (png_size_t)((final_width - 1) * pixel_bytes);
928 for (i = row_info->width; i; i--)
929 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500930 png_memcpy(v, sp, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -0500931 for (j = 0; j < png_pass_inc[pass]; j++)
932 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500933 png_memcpy(dp, v, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -0500934 dp -= pixel_bytes;
935 }
936 sp -= pixel_bytes;
937 }
938 break;
939 }
940 }
941 row_info->width = final_width;
942 row_info->rowbytes = ((final_width *
943 (png_uint_32)row_info->pixel_depth + 7) >> 3);
944 }
945}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500946#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500947
948void
Guy Schalnat6d764711995-12-19 03:22:19 -0600949png_read_filter_row(png_row_infop row_info, png_bytep row,
950 png_bytep prev_row, int filter)
Guy Schalnat0d580581995-07-20 02:43:20 -0500951{
952 switch (filter)
953 {
954 case 0:
955 break;
956 case 1:
957 {
958 png_uint_32 i;
959 int bpp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600960 png_bytep rp;
961 png_bytep lp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500962
963 bpp = (row_info->pixel_depth + 7) / 8;
964 for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
965 i < row_info->rowbytes; i++, rp++, lp++)
966 {
967 *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
968 }
969 break;
970 }
971 case 2:
972 {
973 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -0600974 png_bytep rp;
975 png_bytep pp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500976
977 for (i = 0, rp = row, pp = prev_row;
978 i < row_info->rowbytes; i++, rp++, pp++)
979 {
980 *rp = (png_byte)(((int)(*rp) + (int)(*pp)) & 0xff);
981 }
982 break;
983 }
984 case 3:
985 {
986 png_uint_32 i;
987 int bpp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600988 png_bytep rp;
989 png_bytep pp;
990 png_bytep lp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500991
992 bpp = (row_info->pixel_depth + 7) / 8;
993 for (i = 0, rp = row, pp = prev_row;
994 i < (png_uint_32)bpp; i++, rp++, pp++)
995 {
996 *rp = (png_byte)(((int)(*rp) +
997 ((int)(*pp) / 2)) & 0xff);
998 }
999 for (lp = row; i < row_info->rowbytes; i++, rp++, lp++, pp++)
1000 {
1001 *rp = (png_byte)(((int)(*rp) +
1002 (int)(*pp + *lp) / 2) & 0xff);
1003 }
1004 break;
1005 }
1006 case 4:
1007 {
1008 int bpp;
1009 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -06001010 png_bytep rp;
1011 png_bytep pp;
1012 png_bytep lp;
1013 png_bytep cp;
Guy Schalnat0d580581995-07-20 02:43:20 -05001014
1015 bpp = (row_info->pixel_depth + 7) / 8;
1016 for (i = 0, rp = row, pp = prev_row,
1017 lp = row - bpp, cp = prev_row - bpp;
1018 i < row_info->rowbytes; i++, rp++, pp++, lp++, cp++)
1019 {
1020 int a, b, c, pa, pb, pc, p;
1021
1022 b = *pp;
1023 if (i >= (png_uint_32)bpp)
1024 {
1025 c = *cp;
1026 a = *lp;
1027 }
1028 else
1029 {
1030 a = c = 0;
1031 }
1032 p = a + b - c;
1033 pa = abs(p - a);
1034 pb = abs(p - b);
1035 pc = abs(p - c);
1036
1037 if (pa <= pb && pa <= pc)
1038 p = a;
1039 else if (pb <= pc)
1040 p = b;
1041 else
1042 p = c;
1043
1044 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
1045 }
1046 break;
1047 }
1048 default:
1049 break;
1050 }
1051}
1052
1053void
Guy Schalnat6d764711995-12-19 03:22:19 -06001054png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001055{
1056 png_ptr->row_number++;
1057 if (png_ptr->row_number < png_ptr->num_rows)
1058 return;
1059
1060 if (png_ptr->interlaced)
1061 {
1062 png_ptr->row_number = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001063 png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05001064 do
1065 {
1066 png_ptr->pass++;
1067 if (png_ptr->pass >= 7)
1068 break;
1069 png_ptr->iwidth = (png_ptr->width +
1070 png_pass_inc[png_ptr->pass] - 1 -
1071 png_pass_start[png_ptr->pass]) /
1072 png_pass_inc[png_ptr->pass];
1073 png_ptr->irowbytes = ((png_ptr->iwidth *
1074 png_ptr->pixel_depth + 7) >> 3) + 1;
1075 if (!(png_ptr->transformations & PNG_INTERLACE))
1076 {
1077 png_ptr->num_rows = (png_ptr->height +
1078 png_pass_yinc[png_ptr->pass] - 1 -
1079 png_pass_ystart[png_ptr->pass]) /
1080 png_pass_yinc[png_ptr->pass];
1081 if (!(png_ptr->num_rows))
1082 continue;
1083 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001084 if (png_ptr->transformations & PNG_INTERLACE)
1085 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05001086 } while (png_ptr->iwidth == 0);
1087
1088 if (png_ptr->pass < 7)
1089 return;
1090 }
1091
1092 if (!png_ptr->zlib_finished)
1093 {
1094 char extra;
1095 int ret;
1096
1097 png_ptr->zstream->next_out = (Byte *)&extra;
1098 png_ptr->zstream->avail_out = (uInt)1;
1099 do
1100 {
1101 if (!(png_ptr->zstream->avail_in))
1102 {
1103 while (!png_ptr->idat_size)
1104 {
1105 png_byte buf[4];
1106 png_uint_32 crc;
1107
Guy Schalnat6d764711995-12-19 03:22:19 -06001108 png_read_data(png_ptr, buf, 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001109 crc = png_get_uint_32(buf);
1110 if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
1111 (png_ptr->crc & 0xffffffffL))
Guy Schalnat6d764711995-12-19 03:22:19 -06001112 png_error(png_ptr, "Bad CRC value");
Guy Schalnat0d580581995-07-20 02:43:20 -05001113
Guy Schalnat6d764711995-12-19 03:22:19 -06001114 png_read_data(png_ptr, buf, 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001115 png_ptr->idat_size = png_get_uint_32(buf);
1116 png_reset_crc(png_ptr);
1117
1118 png_crc_read(png_ptr, buf, 4);
Guy Schalnat6d764711995-12-19 03:22:19 -06001119 if (png_memcmp(buf, png_IDAT, 4))
1120 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05001121
1122 }
1123 png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
1124 png_ptr->zstream->next_in = png_ptr->zbuf;
1125 if (png_ptr->zbuf_size > png_ptr->idat_size)
1126 png_ptr->zstream->avail_in = (uInt)png_ptr->idat_size;
1127 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in);
1128 png_ptr->idat_size -= png_ptr->zstream->avail_in;
1129 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001130 ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -05001131 if (ret == Z_STREAM_END)
1132 {
1133 if (!(png_ptr->zstream->avail_out) || png_ptr->zstream->avail_in ||
1134 png_ptr->idat_size)
Guy Schalnat6d764711995-12-19 03:22:19 -06001135 png_error(png_ptr, "Extra compressed data");
Guy Schalnat0d580581995-07-20 02:43:20 -05001136 png_ptr->mode = PNG_AT_LAST_IDAT;
1137 break;
1138 }
1139 if (ret != Z_OK)
Guy Schalnat6d764711995-12-19 03:22:19 -06001140 png_error(png_ptr, "Compression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05001141
1142 if (!(png_ptr->zstream->avail_out))
Guy Schalnat6d764711995-12-19 03:22:19 -06001143 png_error(png_ptr, "Extra compressed data");
Guy Schalnat0d580581995-07-20 02:43:20 -05001144
1145 } while (1);
1146 png_ptr->zstream->avail_out = 0;
1147 }
1148
1149 if (png_ptr->idat_size || png_ptr->zstream->avail_in)
Guy Schalnat6d764711995-12-19 03:22:19 -06001150 png_error(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05001151
1152 inflateReset(png_ptr->zstream);
1153
1154 png_ptr->mode = PNG_AT_LAST_IDAT;
1155}
1156
1157void
Guy Schalnat6d764711995-12-19 03:22:19 -06001158png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001159{
1160 int max_pixel_depth;
1161 png_uint_32 rowbytes;
1162
1163 png_ptr->zstream->avail_in = 0;
1164 png_init_read_transformations(png_ptr);
1165 if (png_ptr->interlaced)
1166 {
1167 if (!(png_ptr->transformations & PNG_INTERLACE))
1168 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
1169 png_pass_ystart[0]) / png_pass_yinc[0];
1170 else
1171 png_ptr->num_rows = png_ptr->height;
1172
1173 png_ptr->iwidth = (png_ptr->width +
1174 png_pass_inc[png_ptr->pass] - 1 -
1175 png_pass_start[png_ptr->pass]) /
1176 png_pass_inc[png_ptr->pass];
1177 png_ptr->irowbytes = ((png_ptr->iwidth *
1178 png_ptr->pixel_depth + 7) >> 3) + 1;
1179 }
1180 else
1181 {
1182 png_ptr->num_rows = png_ptr->height;
1183 png_ptr->iwidth = png_ptr->width;
1184 png_ptr->irowbytes = png_ptr->rowbytes + 1;
1185 }
1186
1187 max_pixel_depth = png_ptr->pixel_depth;
1188
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001189#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001190 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
1191 {
1192 max_pixel_depth = 8;
1193 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001194#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001195
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001196#if defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001197 if (png_ptr->transformations & (PNG_EXPAND | PNG_PACK))
1198 {
1199 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1200 {
1201 if (png_ptr->num_trans)
1202 max_pixel_depth = 32;
1203 else
1204 max_pixel_depth = 24;
1205 }
1206 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1207 {
1208 if (max_pixel_depth < 8)
1209 max_pixel_depth = 8;
1210 if (png_ptr->num_trans)
1211 max_pixel_depth *= 2;
1212 }
1213 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1214 {
1215 if (png_ptr->num_trans)
1216 {
1217 max_pixel_depth *= 4;
1218 max_pixel_depth /= 3;
1219 }
1220 }
1221 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001222#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001223
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001224#if defined(PNG_READ_FILLER_SUPPORTED)
1225 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05001226 {
1227 if (max_pixel_depth < 32)
1228 max_pixel_depth = 32;
1229 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001230#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001231
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001232#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001233 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1234 {
1235 if ((png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
1236 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1237 {
1238 if (max_pixel_depth <= 16)
1239 max_pixel_depth = 32;
1240 else if (max_pixel_depth <= 32)
1241 max_pixel_depth = 64;
1242 }
1243 else
1244 {
1245 if (max_pixel_depth <= 8)
1246 max_pixel_depth = 24;
1247 else if (max_pixel_depth <= 16)
1248 max_pixel_depth = 48;
1249 }
1250 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001251#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001252
1253 /* align the width on the next larger 8 pixels. Mainly used
1254 for interlacing */
1255 rowbytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
1256 /* calculate the maximum bytes needed, adding a byte and a pixel
1257 for safety sake */
1258 rowbytes = ((rowbytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
1259 1 + ((max_pixel_depth + 7) >> 3);
1260#ifdef PNG_MAX_MALLOC_64K
1261 if (rowbytes > 65536L)
Guy Schalnat6d764711995-12-19 03:22:19 -06001262 png_error(png_ptr, "This image requires a row greater then 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05001263#endif
Guy Schalnat6d764711995-12-19 03:22:19 -06001264 png_ptr->row_buf = (png_bytep )png_large_malloc(png_ptr, rowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05001265
1266#ifdef PNG_MAX_MALLOC_64K
1267 if (png_ptr->rowbytes + 1 > 65536L)
Guy Schalnat6d764711995-12-19 03:22:19 -06001268 png_error(png_ptr, "This image requires a row greater then 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05001269#endif
1270 png_ptr->prev_row = png_large_malloc(png_ptr,
1271 png_ptr->rowbytes + 1);
1272
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001273 png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05001274
1275 png_ptr->row_init = 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05001276}
1277