This repository has been archived on 2023-11-11. You can view files and clone it, but cannot push or open issues or pull requests.
libpng/pngpread.c

1103 lines
30 KiB
C
Raw Normal View History

1995-12-19 03:22:19 -06:00
/* pngpread.c - read a png file in push mode
1997-05-16 02:46:07 -05:00
libpng 1.0 beta 6 - version 0.96
1995-12-19 03:22:19 -06:00
For conditions of distribution and use, see copyright notice in png.h
1996-01-26 01:38:47 -06:00
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
1997-05-16 02:46:07 -05:00
Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
1995-12-19 03:22:19 -06:00
*/
#define PNG_INTERNAL
#include "png.h"
1996-01-16 01:51:56 -06:00
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
1995-12-19 03:22:19 -06:00
void
1997-01-17 01:34:35 -06:00
png_process_data(png_structp png_ptr, png_infop info_ptr,
1997-05-16 02:46:07 -05:00
png_bytep buffer, png_size_t buffer_size)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
png_push_restore_buffer(png_ptr, buffer, buffer_size);
1995-12-19 03:22:19 -06:00
1996-01-26 01:38:47 -06:00
while (png_ptr->buffer_size)
{
1997-01-17 01:34:35 -06:00
png_process_some_data(png_ptr, info_ptr);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
}
1997-01-17 01:34:35 -06:00
/* What we do with the incoming data depends on what we were previously
* doing before we ran out of data...
*/
1995-12-19 03:22:19 -06:00
void
1997-01-17 01:34:35 -06:00
png_process_some_data(png_structp png_ptr, png_infop info_ptr)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
switch (png_ptr->process_mode)
{
case PNG_READ_SIG_MODE:
{
1997-01-17 01:34:35 -06:00
png_push_read_sig(png_ptr, info_ptr);
1996-01-26 01:38:47 -06:00
break;
}
case PNG_READ_CHUNK_MODE:
{
1997-01-17 01:34:35 -06:00
png_push_read_chunk(png_ptr, info_ptr);
1996-01-26 01:38:47 -06:00
break;
}
case PNG_READ_IDAT_MODE:
{
1996-06-05 15:50:50 -05:00
png_push_read_IDAT(png_ptr);
1996-01-26 01:38:47 -06:00
break;
}
1995-12-19 03:22:19 -06:00
#if defined(PNG_READ_tEXt_SUPPORTED)
1996-01-26 01:38:47 -06:00
case PNG_READ_tEXt_MODE:
{
1997-01-17 01:34:35 -06:00
png_push_read_tEXt(png_ptr, info_ptr);
1996-01-26 01:38:47 -06:00
break;
}
1995-12-19 03:22:19 -06:00
#endif
1996-01-26 01:38:47 -06:00
#if defined(PNG_READ_zTXt_SUPPORTED)
case PNG_READ_zTXt_MODE:
{
1997-01-17 01:34:35 -06:00
png_push_read_zTXt(png_ptr, info_ptr);
1996-01-26 01:38:47 -06:00
break;
}
#endif
case PNG_SKIP_MODE:
{
1997-05-16 02:46:07 -05:00
png_push_crc_finish(png_ptr);
1996-01-26 01:38:47 -06:00
break;
}
default:
{
png_ptr->buffer_size = 0;
break;
}
}
1995-12-19 03:22:19 -06:00
}
1997-01-17 01:34:35 -06:00
/* Read any remaining signature bytes from the stream and compare them with
* the correct PNG signature. It is possible that this routine is called
* with bytes already read from the signature, whether because they have been
* checked by the calling application, or from multiple calls to this routine.
*/
1995-12-19 03:22:19 -06:00
void
1997-01-17 01:34:35 -06:00
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
1995-12-19 03:22:19 -06:00
{
1997-05-16 02:46:07 -05:00
png_size_t num_checked = png_ptr->sig_bytes,
num_to_check = 8 - num_checked;
1996-01-26 01:38:47 -06:00
1997-01-17 01:34:35 -06:00
if (png_ptr->buffer_size < num_to_check)
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
num_to_check = png_ptr->buffer_size;
1996-01-26 01:38:47 -06:00
}
1997-01-17 01:34:35 -06:00
png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
1997-05-16 02:46:07 -05:00
num_to_check);
1997-01-17 01:34:35 -06:00
png_ptr->sig_bytes += num_to_check;
1996-01-26 01:38:47 -06:00
1997-01-17 01:34:35 -06:00
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
if (num_checked < 4 &&
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
png_error(png_ptr, "Not a PNG file");
else
png_error(png_ptr, "PNG file corrupted by ASCII conversion");
1996-01-26 01:38:47 -06:00
}
else
{
1997-01-17 01:34:35 -06:00
if (png_ptr->sig_bytes >= 8)
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
}
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
}
void
1997-01-17 01:34:35 -06:00
png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
1995-12-19 03:22:19 -06:00
{
1997-01-17 01:34:35 -06:00
/* First we make sure we have enough data for the 4 byte chunk name
and the 4 byte chunk length before proceeding with decoding the
chunk data. To fully decode each of these chunks, we also make
sure we have enough data in the buffer for the 4 byte CRC at the
end of every chunk (except IDAT, which is handled separately). */
1996-06-05 15:50:50 -05:00
if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
png_byte chunk_length[4];
1996-01-26 01:38:47 -06:00
if (png_ptr->buffer_size < 8)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_32(chunk_length);
1996-01-26 01:38:47 -06:00
png_reset_crc(png_ptr);
1997-05-16 02:46:07 -05:00
png_crc_read(png_ptr, png_ptr->chunk_name, 4);
1997-01-17 01:34:35 -06:00
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
1996-01-26 01:38:47 -06:00
}
1997-01-17 01:34:35 -06:00
if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
png_push_save_buffer(png_ptr);
return;
1996-01-26 01:38:47 -06:00
}
1997-01-17 01:34:35 -06:00
png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
/* If we reach an IDAT chunk, this means we have read all of the
header chunks, and we can start reading the image (or if this
is called after the image has been read - we have an error). */
if (png_ptr->mode & PNG_HAVE_IDAT)
{
if (png_ptr->push_length == 0)
return;
if (png_ptr->mode & PNG_AFTER_IDAT)
png_error(png_ptr, "Too many IDAT's found");
}
1996-01-26 01:38:47 -06:00
png_ptr->idat_size = png_ptr->push_length;
1997-01-17 01:34:35 -06:00
png_ptr->mode |= PNG_HAVE_IDAT;
1996-01-26 01:38:47 -06:00
png_ptr->process_mode = PNG_READ_IDAT_MODE;
1997-01-17 01:34:35 -06:00
png_push_have_info(png_ptr, info_ptr);
png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
png_ptr->zstream.next_out = png_ptr->row_buf;
1996-01-26 01:38:47 -06:00
return;
}
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
png_ptr->process_mode = PNG_READ_DONE_MODE;
png_push_have_end(png_ptr, info_ptr);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#if defined(PNG_READ_gAMA_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
1997-05-16 02:46:07 -05:00
#if defined(PNG_READ_pCAL_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
1995-12-19 03:22:19 -06:00
#if defined(PNG_READ_tIME_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
1997-01-17 01:34:35 -06:00
else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
#endif
1996-01-26 01:38:47 -06:00
else
{
1997-01-17 01:34:35 -06:00
png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
1997-01-17 01:34:35 -06:00
png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
1995-12-19 03:22:19 -06:00
}
void
1997-05-16 02:46:07 -05:00
png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
png_ptr->process_mode = PNG_SKIP_MODE;
1997-05-16 02:46:07 -05:00
png_ptr->skip_length = skip;
1995-12-19 03:22:19 -06:00
}
void
1997-05-16 02:46:07 -05:00
png_push_crc_finish(png_structp png_ptr)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
if (png_ptr->skip_length && png_ptr->save_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_size_t save_size;
1996-01-26 01:38:47 -06:00
1997-05-16 02:46:07 -05:00
if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
save_size = (png_size_t)png_ptr->skip_length;
1996-01-26 01:38:47 -06:00
else
save_size = png_ptr->save_buffer_size;
png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
png_ptr->skip_length -= save_size;
png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size;
1997-05-16 02:46:07 -05:00
png_ptr->save_buffer_ptr += save_size;
1996-01-26 01:38:47 -06:00
}
if (png_ptr->skip_length && png_ptr->current_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_size_t save_size;
1996-01-26 01:38:47 -06:00
1997-05-16 02:46:07 -05:00
if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
save_size = (png_size_t)png_ptr->skip_length;
1996-01-26 01:38:47 -06:00
else
save_size = png_ptr->current_buffer_size;
png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
png_ptr->skip_length -= save_size;
png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size;
1997-05-16 02:46:07 -05:00
png_ptr->current_buffer_ptr += save_size;
1996-01-26 01:38:47 -06:00
}
if (!png_ptr->skip_length)
{
if (png_ptr->buffer_size < 4)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_crc_finish(png_ptr, 0);
1997-05-16 02:46:07 -05:00
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
}
void
1997-05-16 02:46:07 -05:00
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
png_bytep ptr;
ptr = buffer;
if (png_ptr->save_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_size_t save_size;
1996-01-26 01:38:47 -06:00
if (length < png_ptr->save_buffer_size)
save_size = length;
else
save_size = png_ptr->save_buffer_size;
1997-05-16 02:46:07 -05:00
png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
1996-01-26 01:38:47 -06:00
length -= save_size;
1997-05-16 02:46:07 -05:00
ptr += save_size;
1996-01-26 01:38:47 -06:00
png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size;
1997-05-16 02:46:07 -05:00
png_ptr->save_buffer_ptr += save_size;
1996-01-26 01:38:47 -06:00
}
if (length && png_ptr->current_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_size_t save_size;
1996-01-26 01:38:47 -06:00
if (length < png_ptr->current_buffer_size)
save_size = length;
else
save_size = png_ptr->current_buffer_size;
1997-05-16 02:46:07 -05:00
png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
1996-01-26 01:38:47 -06:00
png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size;
1997-05-16 02:46:07 -05:00
png_ptr->current_buffer_ptr += save_size;
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
}
void
png_push_save_buffer(png_structp png_ptr)
{
1996-01-26 01:38:47 -06:00
if (png_ptr->save_buffer_size)
{
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
{
1997-05-16 02:46:07 -05:00
png_size_t i;
1996-01-26 01:38:47 -06:00
png_bytep sp;
png_bytep dp;
for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
i < png_ptr->save_buffer_size;
i++, sp++, dp++)
{
*dp = *sp;
}
}
}
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
png_ptr->save_buffer_max)
{
1997-05-16 02:46:07 -05:00
png_size_t new_max;
1996-01-26 01:38:47 -06:00
png_bytep old_buffer;
1997-05-16 02:46:07 -05:00
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
1996-01-26 01:38:47 -06:00
old_buffer = png_ptr->save_buffer;
1997-05-16 02:46:07 -05:00
png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, new_max);
png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
1997-01-17 01:34:35 -06:00
png_free(png_ptr, old_buffer);
1997-05-16 02:46:07 -05:00
png_ptr->save_buffer_max = new_max;
1996-01-26 01:38:47 -06:00
}
if (png_ptr->current_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
1996-01-26 01:38:47 -06:00
png_ptr->save_buffer_size += png_ptr->current_buffer_size;
png_ptr->current_buffer_size = 0;
}
png_ptr->save_buffer_ptr = png_ptr->save_buffer;
png_ptr->buffer_size = 0;
1995-12-19 03:22:19 -06:00
}
void
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
1997-05-16 02:46:07 -05:00
png_size_t buffer_length)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
png_ptr->current_buffer = buffer;
png_ptr->current_buffer_size = buffer_length;
png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
png_ptr->current_buffer_ptr = png_ptr->current_buffer;
1995-12-19 03:22:19 -06:00
}
void
1996-06-05 15:50:50 -05:00
png_push_read_IDAT(png_structp png_ptr)
1995-12-19 03:22:19 -06:00
{
1996-06-05 15:50:50 -05:00
if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
png_byte chunk_length[4];
1996-01-26 01:38:47 -06:00
if (png_ptr->buffer_size < 8)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_32(chunk_length);
1996-01-26 01:38:47 -06:00
png_reset_crc(png_ptr);
1997-05-16 02:46:07 -05:00
png_crc_read(png_ptr, png_ptr->chunk_name, 4);
1997-01-17 01:34:35 -06:00
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
1996-01-26 01:38:47 -06:00
{
1997-05-16 02:46:07 -05:00
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
1996-06-05 15:50:50 -05:00
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
1996-01-26 01:38:47 -06:00
png_error(png_ptr, "Not enough compressed data");
return;
}
png_ptr->idat_size = png_ptr->push_length;
}
if (png_ptr->idat_size && png_ptr->save_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_size_t save_size;
1996-01-26 01:38:47 -06:00
1997-05-16 02:46:07 -05:00
if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
1996-01-26 01:38:47 -06:00
save_size = png_ptr->idat_size;
else
save_size = png_ptr->save_buffer_size;
png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
png_ptr->idat_size -= save_size;
png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size;
1997-05-16 02:46:07 -05:00
png_ptr->save_buffer_ptr += save_size;
1996-01-26 01:38:47 -06:00
}
if (png_ptr->idat_size && png_ptr->current_buffer_size)
{
1997-05-16 02:46:07 -05:00
png_size_t save_size;
1996-01-26 01:38:47 -06:00
1997-05-16 02:46:07 -05:00
if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
1996-01-26 01:38:47 -06:00
save_size = png_ptr->idat_size;
else
save_size = png_ptr->current_buffer_size;
png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
png_ptr->idat_size -= save_size;
png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size;
1997-05-16 02:46:07 -05:00
png_ptr->current_buffer_ptr += save_size;
1996-01-26 01:38:47 -06:00
}
if (!png_ptr->idat_size)
{
if (png_ptr->buffer_size < 4)
{
png_push_save_buffer(png_ptr);
return;
}
1997-01-17 01:34:35 -06:00
png_crc_finish(png_ptr, 0);
1996-06-05 15:50:50 -05:00
png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
1996-01-26 01:38:47 -06:00
}
1995-12-19 03:22:19 -06:00
}
void
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
1997-05-16 02:46:07 -05:00
png_size_t buffer_length)
1995-12-19 03:22:19 -06:00
{
1996-01-26 01:38:47 -06:00
int ret;
1996-06-05 15:50:50 -05:00
if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
1996-01-26 01:38:47 -06:00
png_error(png_ptr, "Extra compression data");
1997-01-17 01:34:35 -06:00
png_ptr->zstream.next_in = buffer;
png_ptr->zstream.avail_in = (uInt)buffer_length;
1997-05-16 02:46:07 -05:00
while(1)
1996-01-26 01:38:47 -06:00
{
1997-01-17 01:34:35 -06:00
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
1996-01-26 01:38:47 -06:00
if (ret == Z_STREAM_END)
{
1997-01-17 01:34:35 -06:00
if (png_ptr->zstream.avail_in)
1996-01-26 01:38:47 -06:00
png_error(png_ptr, "Extra compressed data");
1997-05-16 02:46:07 -05:00
if (!(png_ptr->zstream.avail_out))
1996-01-26 01:38:47 -06:00
{
png_push_process_row(png_ptr);
}
1997-05-16 02:46:07 -05:00
png_ptr->mode |= PNG_AFTER_IDAT;
1996-06-05 15:50:50 -05:00
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
1996-01-26 01:38:47 -06:00
break;
}
1997-05-16 02:46:07 -05:00
else if (ret == Z_BUF_ERROR)
break;
else if (ret != Z_OK)
1996-06-05 15:50:50 -05:00
png_error(png_ptr, "Decompression Error");
1997-01-17 01:34:35 -06:00
if (!(png_ptr->zstream.avail_out))
1996-01-26 01:38:47 -06:00
{
png_push_process_row(png_ptr);
1997-01-17 01:34:35 -06:00
png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
png_ptr->zstream.next_out = png_ptr->row_buf;
1996-01-26 01:38:47 -06:00
}
1997-05-16 02:46:07 -05:00
else
break;
}
1995-12-19 03:22:19 -06:00
}
void
png_push_process_row(png_structp png_ptr)
{
1996-01-26 01:38:47 -06:00
png_ptr->row_info.color_type = png_ptr->color_type;
1995-12-19 03:22:19 -06:00
png_ptr->row_info.width = png_ptr->iwidth;
png_ptr->row_info.channels = png_ptr->channels;
png_ptr->row_info.bit_depth = png_ptr->bit_depth;
png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
(png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
1996-06-05 15:50:50 -05:00
png_read_filter_row(png_ptr, &(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0]));
1995-12-19 03:22:19 -06:00
1997-05-16 02:46:07 -05:00
png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
1995-12-19 03:22:19 -06:00
if (png_ptr->transformations)
png_do_read_transformations(png_ptr);
#if defined(PNG_READ_INTERLACING_SUPPORTED)
1996-01-26 01:38:47 -06:00
/* blow up interlaced rows to full size */
1997-05-16 02:46:07 -05:00
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
1996-01-26 01:38:47 -06:00
{
if (png_ptr->pass < 6)
png_do_read_interlace(&(png_ptr->row_info),
1997-05-16 02:46:07 -05:00
png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
1996-01-26 01:38:47 -06:00
switch (png_ptr->pass)
{
case 0:
{
int i;
for (i = 0; i < 8 && png_ptr->pass == 0; i++)
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
break;
}
case 1:
{
int i;
for (i = 0; i < 8 && png_ptr->pass == 1; i++)
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
if (png_ptr->pass == 2)
{
for (i = 0; i < 4 && png_ptr->pass == 2; i++)
{
png_push_have_row(png_ptr, NULL);
png_read_push_finish_row(png_ptr);
}
}
break;
}
case 2:
{
int i;
for (i = 0; i < 4 && png_ptr->pass == 2; i++)
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
for (i = 0; i < 4 && png_ptr->pass == 2; i++)
{
png_push_have_row(png_ptr, NULL);
png_read_push_finish_row(png_ptr);
}
break;
}
case 3:
{
int i;
for (i = 0; i < 4 && png_ptr->pass == 3; i++)
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
if (png_ptr->pass == 4)
{
for (i = 0; i < 2 && png_ptr->pass == 4; i++)
{
png_push_have_row(png_ptr, NULL);
png_read_push_finish_row(png_ptr);
}
}
break;
}
case 4:
{
int i;
for (i = 0; i < 2 && png_ptr->pass == 4; i++)
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
for (i = 0; i < 2 && png_ptr->pass == 4; i++)
{
png_push_have_row(png_ptr, NULL);
png_read_push_finish_row(png_ptr);
}
break;
}
case 5:
{
int i;
for (i = 0; i < 2 && png_ptr->pass == 5; i++)
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
if (png_ptr->pass == 6)
{
png_push_have_row(png_ptr, NULL);
png_read_push_finish_row(png_ptr);
}
break;
}
case 6:
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
if (png_ptr->pass != 6)
break;
png_push_have_row(png_ptr, NULL);
png_read_push_finish_row(png_ptr);
}
}
}
else
1995-12-19 03:22:19 -06:00
#endif
1996-01-26 01:38:47 -06:00
{
png_push_have_row(png_ptr, png_ptr->row_buf + 1);
png_read_push_finish_row(png_ptr);
}
1995-12-19 03:22:19 -06:00
}
void