CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/ext/libpng17/pngpread.c
Views: 1401
1/* pngpread.c - read a png file in push mode2*3* Last changed in libpng 1.7.0 [(PENDING RELEASE)]4* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson5* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)6* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)7*8* This code is released under the libpng license.9* For conditions of distribution and use, see the disclaimer10* and license in png.h11*/1213#include "pngpriv.h"14#define PNG_SRC_FILE PNG_SRC_FILE_pngpread1516#ifdef PNG_PROGRESSIVE_READ_SUPPORTED1718/* Standard callbacks */19static void PNGCBAPI20png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)21{22png_bytep ptr;2324if (png_ptr == NULL)25return;2627ptr = buffer;28debug(length > 0);2930if (length > 0 && png_ptr->save_buffer_size > 0)31{32png_size_t save_size;3334if (length < png_ptr->save_buffer_size)35save_size = length;3637else38save_size = png_ptr->save_buffer_size;3940memcpy(ptr, png_ptr->save_buffer_ptr, save_size);41length -= save_size;42ptr += save_size;43png_ptr->buffer_size -= save_size;44png_ptr->save_buffer_size -= save_size;45png_ptr->save_buffer_ptr += save_size;46}4748if (length > 0 && png_ptr->current_buffer_size > 0)49{50png_size_t save_size;5152if (length < png_ptr->current_buffer_size)53save_size = length;5455else56save_size = png_ptr->current_buffer_size;5758memcpy(ptr, png_ptr->current_buffer_ptr, save_size);59png_ptr->buffer_size -= save_size;60png_ptr->current_buffer_size -= save_size;61png_ptr->current_buffer_ptr += save_size;62}63}6465/* Push model modes: png_chunk_op plus extras */66typedef enum67{68/* all the png_chunk_op codes, plus: */69png_read_signature = 0, /* starting value */70png_read_chunk_header,71png_read_end_IDAT,72png_read_done,73png_read_chunk, /* Not a state, use these derived from png_chunk_op: */74png_read_chunk_skip = png_read_chunk+png_chunk_skip,75png_read_chunk_unknown = png_read_chunk+png_chunk_unknown,76png_read_chunk_process_all = png_read_chunk+png_chunk_process_all,77png_read_chunk_process_part = png_read_chunk+png_chunk_process_part78} png_read_mode;7980static void81png_push_save_buffer_partial(png_structrp png_ptr, size_t amount)82{83/* Copy 'amount' bytes to the end of the save buffer from the current84* buffer.85*/86png_bytep buffer;87size_t save_size = png_ptr->save_buffer_size;8889if (save_size > PNG_SIZE_MAX - amount)90png_error(png_ptr, "save buffer overflow");9192if (png_ptr->save_buffer_max < save_size + amount)93{94/* Reallocate the save buffer. */95buffer = png_voidcast(png_bytep, png_malloc(png_ptr, save_size + amount));96memcpy(buffer, png_ptr->save_buffer_ptr, save_size);97png_free(png_ptr, png_ptr->save_buffer);98png_ptr->save_buffer_ptr = png_ptr->save_buffer = buffer;99}100101else if (png_ptr->save_buffer_max -102(png_ptr->save_buffer_ptr - png_ptr->save_buffer) < save_size + amount)103{104/* Move the existing saved data */105buffer = png_ptr->save_buffer;106memmove(buffer, png_ptr->save_buffer_ptr, save_size);107png_ptr->save_buffer_ptr = buffer;108}109110else /* Just copy the data */111buffer = png_ptr->save_buffer_ptr;112113memcpy(buffer+save_size, png_ptr->current_buffer_ptr, amount);114png_ptr->save_buffer_size = save_size + amount;115png_ptr->current_buffer_ptr += amount;116png_ptr->current_buffer_size -= amount;117png_ptr->buffer_size -= amount;118}119120static void121png_push_save_buffer(png_structrp png_ptr)122{123png_push_save_buffer_partial(png_ptr, png_ptr->current_buffer_size);124/* This terminates the process loop. */125png_ptr->buffer_size = 0;126}127128#define PNG_PUSH_SAVE_BUFFER_IF_FULL \129if (png_ptr->chunk_length + 4 > png_ptr->buffer_size) \130{ png_push_save_buffer(png_ptr); return; }131#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \132if (png_ptr->buffer_size < N) \133{ png_push_save_buffer(png_ptr); return; }134135png_size_t PNGAPI136png_process_data_pause(png_structrp png_ptr, int save)137{138if (png_ptr != NULL)139{140/* It's easiest for the caller if we do the save; then the caller doesn't141* have to supply the same data again:142*/143if (save != 0)144png_push_save_buffer(png_ptr);145else146{147/* This includes any pending saved bytes: */148png_size_t remaining = png_ptr->buffer_size;149png_ptr->buffer_size = 0; /* Terminate the process loop */150151/* So subtract the saved buffer size, unless all the data152* is actually 'saved', in which case we just return 0153*/154if (png_ptr->save_buffer_size < remaining)155return remaining - png_ptr->save_buffer_size;156}157}158159return 0;160}161162png_uint_32 PNGAPI163png_process_data_skip(png_structrp png_ptr)164{165if (png_ptr != NULL && png_ptr->process_mode == png_read_chunk_skip)166{167/* At the end of png_process_data the buffer size must be 0 (see the loop168* above) so we can detect a broken call here:169*/170if (png_ptr->buffer_size != 0)171png_app_error(png_ptr,172"png_process_data_skip called inside png_process_data");173174/* If is impossible for there to be a saved buffer at this point -175* otherwise we could not be in SKIP mode. This will also happen if176* png_process_skip is called inside png_process_data (but only very177* rarely.)178*/179else if (png_ptr->save_buffer_size != 0)180png_app_error(png_ptr, "png_process_data_skip called with saved data");181182else183{184/* Skipping png_ptr->chunk_length of data then checking the CRC, after185* that a new chunk header will be read.186*/187png_ptr->process_mode = png_read_chunk_header;188return png_ptr->chunk_length + 4;189}190}191192return 0;193}194195static void196png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,197png_size_t buffer_length)198{199png_ptr->current_buffer_size = buffer_length;200png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;201png_ptr->current_buffer_ptr = buffer;202}203204/* Read any remaining signature bytes from the stream and compare them with205* the correct PNG signature. It is possible that this routine is called206* with bytes already read from the signature, either because they have been207* checked by the calling application, or because of multiple calls to this208* routine.209*/210static void211png_push_read_signature(png_structrp png_ptr, png_inforp info_ptr)212{213unsigned int num_checked = png_ptr->sig_bytes;214unsigned int num_to_check = 8 - num_checked;215216if (png_ptr->buffer_size < num_to_check)217num_to_check = (int)/*SAFE*/png_ptr->buffer_size;218219png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),220num_to_check);221png_ptr->sig_bytes = png_check_byte(png_ptr,222png_ptr->sig_bytes + num_to_check);223224if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))225{226if (num_checked < 4 &&227png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))228png_error(png_ptr, "Not a PNG file");229230else231png_error(png_ptr, "PNG file corrupted by ASCII conversion");232}233234else if (png_ptr->sig_bytes >= 8)235png_ptr->process_mode = png_read_chunk_header;236}237238static void239png_push_crc_finish(png_structrp png_ptr)240/* CRC the remainder of the chunk data; png_struct::chunk_length must be the241* amount of data left to read excluding the CRC.242*/243{244if (png_ptr->chunk_length != 0 && png_ptr->save_buffer_size != 0)245{246png_size_t save_size = png_ptr->save_buffer_size;247png_uint_32 skip_length = png_ptr->chunk_length;248249/* We want the smaller of 'skip_length' and 'save_buffer_size', but250* they are of different types and we don't know which variable has the251* fewest bits. Carefully select the smaller and cast it to the type of252* the larger - this cannot overflow. Do not cast in the following test253* - it will break on either 16 or 64 bit platforms.254*/255if (skip_length < save_size)256save_size = (png_size_t)/*SAFE*/skip_length;257258else259skip_length = (png_uint_32)/*SAFE*/save_size;260261png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);262263png_ptr->chunk_length -= skip_length;264png_ptr->buffer_size -= save_size;265png_ptr->save_buffer_size -= save_size;266png_ptr->save_buffer_ptr += save_size;267}268269if (png_ptr->chunk_length != 0 && png_ptr->current_buffer_size != 0)270{271png_size_t save_size = png_ptr->current_buffer_size;272png_uint_32 skip_length = png_ptr->chunk_length;273274/* We want the smaller of 'skip_length' and 'current_buffer_size', here,275* the same problem exists as above and the same solution.276*/277if (skip_length < save_size)278save_size = (png_size_t)/*SAFE*/skip_length;279280else281skip_length = (png_uint_32)/*SAFE*/save_size;282283png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);284285png_ptr->chunk_length -= skip_length;286png_ptr->buffer_size -= save_size;287png_ptr->current_buffer_size -= save_size;288png_ptr->current_buffer_ptr += save_size;289}290291if (png_ptr->chunk_length == 0)292{293PNG_PUSH_SAVE_BUFFER_IF_LT(4)294png_crc_finish(png_ptr, 0);295png_ptr->process_mode = png_read_chunk_header;296}297}298299static void300png_push_read_unknown(png_structrp png_ptr, png_inforp info_ptr)301{302/* Handle an unknown chunk. All the data is available but it may not303* all be in the same buffer. png_handle_unknown needs the chunk data in304* just one buffer.305*/306png_bytep buffer;307png_uint_32 chunk_length = png_ptr->chunk_length;308309if (png_ptr->save_buffer_size > 0)310{311png_size_t save_size = png_ptr->save_buffer_size;312313if (save_size < chunk_length)314{315/* Copy the current_buffer_ptr data into the save buffer. */316png_push_save_buffer_partial(png_ptr, chunk_length - save_size);317save_size = chunk_length;318}319320buffer = png_ptr->save_buffer_ptr;321png_ptr->save_buffer_ptr = buffer+chunk_length;322png_ptr->save_buffer_size = save_size-chunk_length;323png_ptr->buffer_size -= chunk_length;324affirm(png_ptr->buffer_size >= 4);325}326327else328{329affirm(png_ptr->current_buffer_size >= chunk_length+4);330buffer = png_ptr->current_buffer_ptr;331png_ptr->current_buffer_ptr = buffer+chunk_length;332png_ptr->current_buffer_size -= chunk_length;333png_ptr->buffer_size -= chunk_length;334}335336/* Now check the CRC, before attempting the unknown handling. */337png_calculate_crc(png_ptr, buffer, chunk_length);338png_crc_finish(png_ptr, 0);339# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED340png_handle_unknown(png_ptr, info_ptr, buffer);341# else /* !READ_UNKNOWN_CHUNKS */342PNG_UNUSED(info_ptr)343# endif /* !READ_UNKNOWN_CHUNKS */344png_ptr->process_mode = png_read_chunk_header;345}346347static void348png_push_have_row(png_structrp png_ptr, png_bytep row)349{350if (png_ptr->row_fn != NULL)351{352png_uint_32 row_number = png_ptr->row_number;353png_byte pass = png_ptr->pass;354355if (png_ptr->interlaced)356{357/* If the row de-interlace is not being done by PNG this wacky API358* delivers the row number in the pass to the caller. We know that359* if we get here the row exists, so the number is just one less than360* the height of an interlaced image with just the rows up to this361* one:362*/363# ifdef PNG_READ_INTERLACING_SUPPORTED364if (!png_ptr->do_interlace)365# endif /* READ_INTERLACING */366{367affirm(PNG_ROW_IN_INTERLACE_PASS(row_number, pass) && row != NULL);368row_number = PNG_PASS_ROWS(row_number+1, pass);369affirm(row_number > 0);370--row_number;371}372}373374(*(png_ptr->row_fn))(png_ptr, row, row_number, pass);375}376}377378static void379png_push_read_sync_zstream(png_structp png_ptr, png_bytep *bufferp,380size_t *buffer_lengthp)381/* Synchronize the png_struct progressive read buffer382* {*bufferp,*buffer_lengthp} with png_struct::zstream.next_in, on the383* assumption that the zstream had previously been set up with *bufferp.384*/385{386png_bytep original_start = *bufferp;387png_alloc_size_t bytes_consumed = png_ptr->zstream.next_in - original_start;388389affirm(buffer_lengthp != NULL);390391/* Calculate the CRC for the consumed data: */392png_calculate_crc(png_ptr, original_start, bytes_consumed);393394/* Update the buffer pointers and the various lengths: */395*bufferp = original_start + bytes_consumed; /* == png_ptr->zstream.next_in */396397affirm(bytes_consumed <= *buffer_lengthp);398*buffer_lengthp -= (size_t)/*SAFE*/bytes_consumed;399400affirm(bytes_consumed <= png_ptr->chunk_length);401png_ptr->chunk_length -= (png_uint_32)/*SAFE*/bytes_consumed;402403affirm(bytes_consumed <= png_ptr->buffer_size);404png_ptr->buffer_size -= (size_t)/*SAFE*/bytes_consumed;405}406407static void408png_push_read_process_IDAT(png_structp png_ptr, png_bytep *bufferp,409size_t *buffer_lengthp)410/* If the the *buffer_lengthp parameter is NULL there is no more input,411* png_struct::mode & PNG_AFTER_IDAT must be set at this point.412*/413{414png_alloc_size_t buffer_length;415416if (buffer_lengthp != NULL)417buffer_length = *buffer_lengthp;418419else /* end of IDAT */420{421/* SECURITY: if this affirm fails the code would go into an infinite loop;422* see the handling of avail_in == 0 in png_inflate_IDAT.423*/424affirm(png_ptr->mode & PNG_AFTER_IDAT);425buffer_length = 0;426}427428/* This routine attempts to process all the data it has been given before429* returning, calling the row callback as required to handle the430* uncompressed results.431*432* If a pause happens during processing (png_ptr->buffer_size is set to 0)433* or the end of the chunk is encountered the routine may return without434* handling all the input data.435*/436if (buffer_length > png_ptr->chunk_length)437{438buffer_length = png_ptr->chunk_length;439440/* This works because the last part of a 'skip' is to read and check the441* CRC, then the process mode is set to png_read_chunk_header.442*/443if (buffer_length == 0)444png_ptr->process_mode = png_read_chunk_skip;445}446447/* It is possble for buffer_length to be zero at this point if the stream448* caontains a zero length IDAT. This is handled below.449*/450png_ptr->zstream.next_in = *bufferp;451452while (buffer_length > 0 || buffer_lengthp == NULL)453{454if (buffer_length >= ZLIB_IO_MAX)455{456png_ptr->zstream.avail_in = ZLIB_IO_MAX;457buffer_length -= ZLIB_IO_MAX;458}459460else461{462png_ptr->zstream.avail_in = (uInt)/*SAFE*/buffer_length;463buffer_length = 0;464}465466/* The last row may already have been processed.467*468* row_number is the *current* row number in the range 0..height-1. It is469* updated only by the call to png_read_process_IDAT that follows the call470* which returns something other than png_row_incomplete.471*472* At the end of the image that call must *NOT* be made; png_process_IDAT473* must not be called after the last row. png_struct::zstream_eod is set474* below to allow this condition to be detected.475*476* Note that png_read_process_IDAT handles errors in the LZ compressed477* data (i.e. the cases where png_struct::zstream_error is set) by filling478* the rows in with 0, which is a safe value, so keep calling it until we479* reach the end of the image.480*/481if (!png_ptr->zstream_eod)482{483png_bytep row_buffer = NULL;484png_row_op row_op =485png_read_process_IDAT(png_ptr, NULL, NULL, 1/*save row*/);486487if (row_op != png_row_incomplete)488{489/* Have a complete row, so check for end-of-image; do this here490* because interlaced images can end on earlier rows or passes but491* we keep calling png_read_process_IDAT until it updates row_number492* to the last row of the actual image:493*/494if (png_ptr->row_number+1 >= png_ptr->height &&495(!png_ptr->interlaced || png_ptr->pass == 6))496png_ptr->zstream_eod = 1; /* end of image */497}498499switch (row_op)500{501case png_row_incomplete:502/* more IDAT data needed for row */503debug(png_ptr->zstream.avail_in == 0);504505/* png_inflate_IDAT is supposed to handle this and recognize a506* call with 0 avail_in as end of stream:507*/508affirm(buffer_lengthp != NULL);509continue;510511case png_row_process:512/* If a row was obtained after the end of the IDAT this was done513* by fabricating data, ensure this is reported, else there is a514* security issue; normally libpng does a png_error in this515* case, even if the error is ignored png_struct::zstream_error516* should be set so somehow the error wasn't noticed!517*/518affirm(buffer_lengthp != NULL || png_ptr->zstream_error);519520/* png_struct::transformed_row contains a complete, transformed,521* row; this is processed in both 'sparkle' and 'block' mode.522*/523# ifdef PNG_TRANSFORM_MECH_SUPPORTED524row_buffer = png_ptr->transformed_row;525if (row_buffer == NULL)526# endif /* TRANSFORM_MECH */527row_buffer = png_ptr->row_buffer;528break;529530case png_row_repeat:531/* row not in this pass, but the existing row in532* png_struct::transformed_row may be used, this is only required533* if the 'block' or 'rectangle' mode of display is done and534* libpng is handling the de-interlace; when the app does it it535* only see the real rows.536*/537# ifdef PNG_READ_INTERLACING_SUPPORTED538if (png_ptr->do_interlace)539{540# ifdef PNG_TRANSFORM_MECH_SUPPORTED541row_buffer = png_ptr->transformed_row;542if (row_buffer == NULL)543# endif /* TRANSFORM_MECH */544row_buffer = png_ptr->row_buffer;545break;546}547# endif /* READ_INTERLACING */548continue;549550case png_row_skip:551/* row not in pass and no appropriate data; skip this row,552* nothing more need be done, except the read_row_fn. The use553* of 'NULL' to mean this row doesn't contribute to the output554* is historical and not documented;555*/556# ifdef PNG_READ_INTERLACING_SUPPORTED557if (png_ptr->do_interlace)558break;559# endif /* READ_INTERLACING */560continue;561562default:563impossible("not reached");564}565566/* Here if there is a row to process. */567568/* Now adjust the buffer pointers before calling png_push_have_row569* because the callback might call png_process_data_pause and that570* calls png_push_save_row. (Yes, this is insane; it was forced on571* libpng by writers of an external app that ignored the instructions572* not to fiddle with the insides of png_struct in version 1.4. It573* will probably be fixed here before 1.7.0 is released by removing574* the need for the save buffer entirely.)575*/576if (buffer_lengthp != NULL)577png_push_read_sync_zstream(png_ptr, bufferp, buffer_lengthp);578579/* Process one row: */580png_push_have_row(png_ptr, row_buffer);581582/* The buffer pointer and size may have changed at this point,583* so everything needs to be reloaded if we can continue reading.584*/585if (buffer_lengthp != NULL) /* not at end of IDATs */586{587if (png_ptr->chunk_length == 0)588png_ptr->process_mode = png_read_chunk_skip;589590/* If the buffer_size has been set to zero more input is required,591* this may be a 'pause', and if the specific input buffer being592* processed has been exhaused then more input is also required.593* Otherwise we can keep going, however the input buffer may have594* been changed by the app callback, so do a complete reload:595*/596else if (png_ptr->buffer_size > 0 && *buffer_lengthp > 0)597png_push_read_process_IDAT(png_ptr, bufferp, buffer_lengthp);598599return;600}601602/* If we can't continue reading because there is no more IDAT data this603* may still be a pause.604*/605if (png_ptr->buffer_size == 0)606return;607608/* Else continue, with zero data: */609continue;610}611612affirm(png_ptr->zstream_eod);613614if (png_ptr->zowner == 0 || png_read_finish_IDAT(png_ptr))615{616/* The zlib stream has ended, there may still be input data in617* png_ptr->zstream.next_in, restore this.618*/619debug(png_ptr->zowner == 0 && png_ptr->zstream_ended);620621if (buffer_lengthp != NULL)622{623png_push_read_sync_zstream(png_ptr, bufferp, buffer_lengthp);624625/* If the chunk_length is greater than 0 then there is extra data,626* report this once. Notice that for IDAT after the end of the627* stream we keep coming to this point and doing the skip.628*/629if (png_ptr->chunk_length > 0)630{631if (!png_ptr->zstream_error)632{633png_chunk_benign_error(png_ptr,634"too much IDAT data (progressive read)");635png_ptr->zstream_error = 1;636}637}638639/* In any case CRC the chunk, skipping any unneeded data: */640png_ptr->process_mode = png_read_chunk_skip;641}642return;643}644645/* else more input is required */646/* NOTE: this test only fires on a small (less than 5 byte) IDAT chunk647* which just contains the LZ EOF and the Adler32 CRC.648*/649affirm(png_ptr->zowner == png_IDAT && !png_ptr->zstream_ended);650}651652/* At this point all the input has been consumed, however the CRC has not653* been done and the three length fields in png_struct, *buffer_lengthp,654* buffer_size and chunk_length, all need updating.655*/656png_push_read_sync_zstream(png_ptr, bufferp, buffer_lengthp);657}658659static void660png_push_read_IDAT(png_structrp png_ptr)661{662if (png_ptr->save_buffer_size > 0)663{664png_push_read_process_IDAT(png_ptr, &png_ptr->save_buffer_ptr,665&png_ptr->save_buffer_size);666667/* This is a slight optimization; normally when the process mode changes668* there will still be something in the buffer:669*/670if (png_ptr->save_buffer_size > 0)671return;672673/* Check for a change in process mode or an application pause before674* checking the current input buffer. This is only rarely reached.675*/676if (png_ptr->process_mode != png_read_chunk_process_part ||677png_ptr->buffer_size == 0)678return;679}680681if (png_ptr->current_buffer_size > 0)682png_push_read_process_IDAT(png_ptr, &png_ptr->current_buffer_ptr,683&png_ptr->current_buffer_size);684}685686static void687png_push_finish_IDAT(png_structrp png_ptr)688/* Called once when the first chunk after IDAT is seen. */689{690/* All of the IDAT data has been processed, however the stream may have691* been truncated and the image rows may not all have been processed.692* Clean up here (this doesn't read anything.)693*694* 1.7.0: this attempts some measure of compatibility with the sequential695* API, if the IDAT is truncated and the resultant error reporting doesn't696* abort the read the image is filled in using zeros of pixel data. This697* actually happens inside png_inflate_IDAT (pngrutil.c) when called with698* z_stream::avail_in == 0.699*/700while (png_ptr->zowner == png_IDAT)701{702png_byte b = 0, *pb = &b;703704png_push_read_process_IDAT(png_ptr, &pb, NULL/*end of IDAT*/);705706if (png_ptr->zowner == 0)707break;708709if (png_ptr->buffer_size == 0) /* pause */710return;711}712713png_ptr->process_mode = png_check_bits(png_ptr, png_ptr->process_mode >> 4,7144);715}716717static void718png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)719{720if (png_ptr->info_fn != NULL)721(*(png_ptr->info_fn))(png_ptr, info_ptr);722}723724static void725png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)726{727if (png_ptr->end_fn != NULL)728(*(png_ptr->end_fn))(png_ptr, info_ptr);729}730731static void732png_push_read_chunk_header(png_structrp png_ptr, png_infop info_ptr)733{734/* Called to read a new chunk header and work out how to handle the remainder735* of the data.736*/737unsigned int mode; /* mode prior to the header */738png_byte chunk_header[8];739740PNG_PUSH_SAVE_BUFFER_IF_LT(8)741png_push_fill_buffer(png_ptr, chunk_header, 8);742png_ptr->chunk_length = png_get_uint_31(png_ptr, chunk_header);743png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_header+4);744png_reset_crc(png_ptr, chunk_header+4);745png_check_chunk_name(png_ptr, png_ptr->chunk_name);746png_check_chunk_length(png_ptr, png_ptr->chunk_length);747mode = png_ptr->mode;748png_ptr->process_mode = png_check_bits(png_ptr,749png_read_chunk+png_find_chunk_op(png_ptr), 4);750751/* Is this the first IDAT chunk? */752if ((mode ^ png_ptr->mode) & PNG_HAVE_IDAT)753png_push_have_info(png_ptr, info_ptr);754755/* Is it the chunk after the last IDAT chunk? */756else if (((mode ^ png_ptr->mode) & PNG_AFTER_IDAT) != 0)757png_ptr->process_mode = png_check_bits(png_ptr,758(png_ptr->process_mode << 4) + png_read_end_IDAT, 8);759}760761/* What we do with the incoming data depends on what we were previously762* doing before we ran out of data...763*/764static void765png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)766{767if (png_ptr == NULL)768return;769770switch (png_ptr->process_mode & 0xf)771{772case png_read_signature:773png_push_read_signature(png_ptr, info_ptr);774return;775776case png_read_chunk_header:777png_push_read_chunk_header(png_ptr, info_ptr);778return;779780case png_read_chunk_skip:781png_push_crc_finish(png_ptr);782return;783784case png_read_chunk_unknown:785PNG_PUSH_SAVE_BUFFER_IF_FULL786png_push_read_unknown(png_ptr, info_ptr);787return;788789case png_read_chunk_process_all:790PNG_PUSH_SAVE_BUFFER_IF_FULL791png_handle_chunk(png_ptr, info_ptr);792793if (png_ptr->mode & PNG_HAVE_IEND)794{795png_ptr->process_mode = png_read_done;796png_push_have_end(png_ptr, info_ptr);797png_ptr->buffer_size = 0;798}799800else801png_ptr->process_mode = png_read_chunk_header;802return;803804case png_read_chunk_process_part:805debug(png_ptr->chunk_name == png_IDAT &&806(png_ptr->mode & PNG_HAVE_IDAT) &&807!(png_ptr->mode & PNG_AFTER_IDAT));808809if (png_ptr->zowner == 0 && !png_ptr->zstream_ended) /* first time */810png_read_start_IDAT(png_ptr);811812png_push_read_IDAT(png_ptr);813return;814815case png_read_end_IDAT:816png_push_finish_IDAT(png_ptr);817return;818819case png_read_done:820png_app_error(png_ptr, "read beyond end of stream");821png_ptr->buffer_size = 0;822return;823824default:825impossible("invalid process mode");826}827}828829void PNGAPI830png_process_data(png_structrp png_ptr, png_inforp info_ptr,831png_bytep buffer, png_size_t buffer_size)832{833if (png_ptr == NULL || info_ptr == NULL)834return;835836png_push_restore_buffer(png_ptr, buffer, buffer_size);837838while (png_ptr->buffer_size)839png_process_some_data(png_ptr, info_ptr);840}841842void PNGAPI843png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,844png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,845png_progressive_end_ptr end_fn)846{847if (png_ptr == NULL)848return;849850png_ptr->info_fn = info_fn;851png_ptr->row_fn = row_fn;852png_ptr->end_fn = end_fn;853854png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);855}856857png_voidp PNGAPI858png_get_progressive_ptr(png_const_structrp png_ptr)859{860if (png_ptr == NULL)861return (NULL);862863return png_ptr->io_ptr;864}865#endif /* PROGRESSIVE_READ */866867868