diff options
author | Sireesh Tripurari <sireesh.tripurari@linaro.org> | 2014-05-09 15:39:12 +0530 |
---|---|---|
committer | Sireesh Tripurari <sireesh.tripurari@linaro.org> | 2014-05-09 12:02:04 +0000 |
commit | b0277d0706e596e9a1dd889903f8ceb2680bcadb (patch) | |
tree | e0d91a166486805affa71e8cb1b92fa073b06776 | |
parent | b478e66e7c2621eef5f465e4629ce642db00716b (diff) | |
download | android_external_libpng-b0277d0706e596e9a1dd889903f8ceb2680bcadb.tar.gz android_external_libpng-b0277d0706e596e9a1dd889903f8ceb2680bcadb.tar.bz2 android_external_libpng-b0277d0706e596e9a1dd889903f8ceb2680bcadb.zip |
libpng 1.6.10 - Merge seekable png patch
Change-Id: I3aa6d8775b884f719375c5aaa458a5c27c120b38
-rw-r--r-- | png.h | 18 | ||||
-rw-r--r-- | pngpriv.h | 9 | ||||
-rw-r--r-- | pngread.c | 167 | ||||
-rw-r--r-- | pngrio.c | 25 | ||||
-rw-r--r-- | pngrutil.c | 57 | ||||
-rw-r--r-- | pngstruct.h | 53 |
6 files changed, 328 insertions, 1 deletions
@@ -901,6 +901,10 @@ typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, int)); +#ifdef PNG_INDEX_SUPPORTED +typedef PNG_CALLBACK(void, *png_seek_ptr, (png_structp, png_uint_32)); +#endif + #ifdef PNG_PROGRESSIVE_READ_SUPPORTED typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); @@ -1887,6 +1891,20 @@ PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, png_inforp info_ptr, int freer, png_uint_32 mask)); +#ifdef PNG_INDEX_SUPPORTED +/* Build image index for partial image decoding. */ +PNG_EXPORT(300, void, png_build_index, (png_structp png_ptr)); +PNG_EXPORT(301, void, png_configure_decoder, + (png_structp png_ptr, int *row_offset, int pass)); +/* Set the data seek function with a user supplied one. + * REQUIRED by partial image decode. + */ +PNG_EXPORT(302, void, png_set_seek_fn, (png_structp png_ptr, + png_seek_ptr seek_data_fn)); +/* Update the decoder status to the given pass */ +PNG_EXPORT(303, void, png_set_interlaced_pass, (png_structp png_ptr, int pass)); +#endif + /* Assignments for png_data_freer */ #define PNG_DESTROY_WILL_FREE_DATA 1 #define PNG_SET_WILL_FREE_DATA 1 @@ -1928,6 +1928,15 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); #endif +#ifdef PNG_INDEX_SUPPORTED +PNG_INTERNAL_FUNCTION(void, png_seek_data, (png_structp png_ptr, + png_uint_32 length), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_opt_crc_finish,(png_structrp png_ptr, + png_uint_32 skip), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_set_interlaced_pass,(png_structrp png_ptr, + int pass), PNG_EMPTY); +#endif + /* Maintainer: Put new private prototypes here ^ */ #include "pngdebug.h" @@ -73,6 +73,10 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, * required. */ png_set_read_fn(png_ptr, NULL, NULL); + +#ifdef PNG_INDEX_SUPPORTED + png_ptr->index = NULL; +#endif } return png_ptr; @@ -262,6 +266,11 @@ png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) if (png_ptr != NULL) { +#ifdef PNG_INDEX_SUPPORTED + if (png_ptr->index) { + png_read_start_row(png_ptr); + } +#endif if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) { png_read_start_row(png_ptr); @@ -272,11 +281,12 @@ png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) PNG_UNUSED(info_ptr) # endif } - +#ifndef PNG_INDEX_SUPPORTED /* New in 1.6.0 this avoids the bug of doing the initializations twice */ else png_app_error(png_ptr, "png_read_update_info/png_start_read_image: duplicate call"); +#endif } } @@ -671,6 +681,142 @@ png_read_rows(png_structrp png_ptr, png_bytepp row, } #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#ifdef PNG_INDEX_SUPPORTED +#define IDAT_HEADER_SIZE 8 + +/* Set the png read position to a new position based on idat_position and + * offset. + */ +void +png_set_read_offset(png_structp png_ptr, + png_uint_32 idat_position, png_uint_32 bytes_left) +{ + png_seek_data(png_ptr, idat_position); + png_ptr->idat_size = png_read_chunk_header(png_ptr); + + // We need to add back IDAT_HEADER_SIZE because in zlib's perspective, + // IDAT_HEADER in PNG is already stripped out. + png_seek_data(png_ptr, idat_position + IDAT_HEADER_SIZE + png_ptr->idat_size - bytes_left); + png_ptr->idat_size = bytes_left; +} + +/* Configure png decoder to decode the pass starting from *row. + * The requested row may be adjusted to align with an indexing row. + * The actual row for the decoder to start its decoding will be returned in + * *row. + */ +void PNGAPI +png_configure_decoder(png_structp png_ptr, int *row, int pass) +{ + png_indexp index = png_ptr->index; + int n = *row / index->step[pass]; + png_line_indexp line_index = index->pass_line_index[pass][n]; + + // Adjust row to an indexing row. + *row = n * index->step[pass]; + png_ptr->row_number = *row; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + png_set_interlaced_pass(png_ptr, pass); +#endif + + long row_byte_length = + PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; + + inflateEnd(&png_ptr->zstream); + inflateCopy(&png_ptr->zstream, line_index->z_state); + + // Set the png read position to line_index. + png_set_read_offset(png_ptr, line_index->stream_idat_position, + line_index->bytes_left_in_idat); + memcpy(png_ptr->prev_row, line_index->prev_row, row_byte_length); + png_ptr->zstream.avail_in = 0; +} + +/* Build the line index and store the index in png_ptr->index. + */ +void PNGAPI +png_build_index(png_structp png_ptr) +{ + // number of rows in a 8x8 block for each interlaced pass. + int number_rows_in_pass[7] = {1, 1, 1, 2, 2, 4, 4}; + + int ret; + png_uint_32 i, j; + png_bytep rp; + int p, pass_number = 1; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass_number = png_set_interlace_handling(png_ptr); +#endif + + if (png_ptr == NULL) + return; + + png_read_start_row(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!png_ptr->interlaced) +#endif + { + number_rows_in_pass[0] = 8; + } + + rp = png_malloc(png_ptr, png_ptr->rowbytes); + + png_indexp index = png_malloc(png_ptr, sizeof(png_index)); + png_ptr->index = index; + + index->stream_idat_position = png_ptr->total_data_read - IDAT_HEADER_SIZE; + + // Set the default size of index in each pass to 0, + // so that we can free index correctly in png_destroy_read_struct. + for (p = 0; p < 7; p++) + index->size[p] = 0; + + for (p = 0; p < pass_number; p++) + { + // We adjust the index step in each pass to make sure each pass + // has roughly the same size of index. + // This way, we won't consume to much memory in recording index. + index->step[p] = INDEX_SAMPLE_SIZE * (8 / number_rows_in_pass[p]); + index->size[p] = + (png_ptr->height + index->step[p] - 1) / index->step[p]; + index->pass_line_index[p] = + png_malloc(png_ptr, index->size[p] * sizeof(png_line_indexp)); + + // Get the row_byte_length seen by the filter. This value may be + // different from the row_byte_length of a bitmap in the case of + // color palette mode. + int row_byte_length = + PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; + + // Now, we record index for each indexing row. + for (i = 0; i < index->size[p]; i++) + { + png_line_indexp line_index = png_malloc(png_ptr, sizeof(png_line_index)); + index->pass_line_index[p][i] = line_index; + + line_index->z_state = png_malloc(png_ptr, sizeof(z_stream)); + inflateCopy(line_index->z_state, &png_ptr->zstream); + line_index->prev_row = png_malloc(png_ptr, row_byte_length); + memcpy(line_index->prev_row, png_ptr->prev_row, row_byte_length); + line_index->stream_idat_position = index->stream_idat_position; + line_index->bytes_left_in_idat = png_ptr->idat_size + png_ptr->zstream.avail_in; + + // Skip the "step" number of rows to the next indexing row. + for (j = 0; j < index->step[p] && + i * index->step[p] + j < png_ptr->height; j++) + { + png_read_row(png_ptr, rp, NULL); + } + } + } + png_free(png_ptr, rp); +} +#endif + #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the entire image. If the image has an alpha channel or a tRNS * chunk, and you have called png_handle_alpha()[*], you will need to @@ -954,6 +1100,25 @@ png_read_destroy(png_structrp png_ptr) png_free(png_ptr, png_ptr->chunk_list); #endif +#ifdef PNG_INDEX_SUPPORTED + if (png_ptr->index) { + unsigned int i, p; + png_indexp index = png_ptr->index; + for (p = 0; p < 7; p++) { + for (i = 0; i < index->size[p]; i++) { + inflateEnd(index->pass_line_index[p][i]->z_state); + png_free(png_ptr, index->pass_line_index[p][i]->z_state); + png_free(png_ptr, index->pass_line_index[p][i]->prev_row); + png_free(png_ptr, index->pass_line_index[p][i]); + } + if (index->size[p] != 0) { + png_free(png_ptr, index->pass_line_index[p]); + } + } + png_free(png_ptr, index); + } +#endif + /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error * callbacks are still set at this point. They are required to complete the * destruction of the png_struct itself. @@ -38,7 +38,21 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) else png_error(png_ptr, "Call to NULL read function"); +#ifdef PNG_INDEX_SUPPORTED + png_ptr->total_data_read += length; +#endif +} + +#ifdef PNG_INDEX_SUPPORTED +void /* PRIVATE */ +png_seek_data(png_structp png_ptr, png_uint_32 offset) +{ + if (png_ptr->seek_data_fn != NULL) + (*(png_ptr->seek_data_fn))(png_ptr, offset); + else + png_error(png_ptr, "Call to NULL seek function"); } +#endif #ifdef PNG_STDIO_SUPPORTED /* This is the function that does the actual reading of data. If you are @@ -117,4 +131,15 @@ png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, png_ptr->output_flush_fn = NULL; #endif } + +#ifdef PNG_INDEX_SUPPORTED +void PNGAPI +png_set_seek_fn(png_structp png_ptr, png_seek_ptr seek_data_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->seek_data_fn = seek_data_fn; +} +#endif + #endif /* PNG_READ_SUPPORTED */ @@ -235,6 +235,33 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip) return (0); } +#ifdef PNG_INDEX_SUPPORTED +int /* PRIVATE */ +png_opt_crc_finish(png_structrp png_ptr, png_uint_32 skip) +{ + while (skip > 0) + { + png_uint_32 len; + png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; + + len = (sizeof tmpbuf); + if (len > skip) + len = skip; + skip -= len; + + png_crc_read(png_ptr, tmpbuf, len); + } + + if (png_crc_error(png_ptr)) + { + png_chunk_warning(png_ptr, "CRC error"); + return (1); + } + + return (0); +} +#endif + /* Compare the CRC stored in the PNG file with that calculated by libpng from * the data it has read thus far. */ @@ -3957,6 +3984,12 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, while (png_ptr->idat_size == 0) { +#ifdef PNG_INDEX_SUPPORTED + if (png_ptr->index) { + png_opt_crc_finish(png_ptr, 0); + png_ptr->index->stream_idat_position = png_ptr->total_data_read; + } else +#endif png_crc_finish(png_ptr, 0); png_ptr->idat_size = png_read_chunk_header(png_ptr); @@ -4036,6 +4069,9 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, } if (ret != Z_OK) +#ifdef PNG_INDEX_SUPPORTED + if (png_ptr->index && png_ptr->row_number != png_ptr->height - 1) +#endif { png_zstream_error(png_ptr, ret); @@ -4111,6 +4147,27 @@ png_read_finish_IDAT(png_structrp png_ptr) } } +#ifdef PNG_INDEX_SUPPORTED +void /* PRIVATE */ +png_set_interlaced_pass(png_structp png_ptr, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + png_ptr->pass = pass; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; +} +#endif + void /* PRIVATE */ png_read_finish_row(png_structrp png_ptr) { diff --git a/pngstruct.h b/pngstruct.h index d58c028..e40e17d 100644 --- a/pngstruct.h +++ b/pngstruct.h @@ -141,6 +141,50 @@ typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; #define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) #endif /* COLORSPACE || GAMMA */ +#ifdef PNG_INDEX_SUPPORTED +/* png_line_index_struct records an index point, where we impose an index point + * to be located at the beginning of a line for simplifying the implementation. + */ +typedef struct png_line_index_struct +{ + // state of the lz decoder + z_streamp z_state; + + // the IDAT header position of the chunk, which the index point is in + png_uint_32 stream_idat_position; + + // we intend to record the offset of the index point in the chunk, + // but we record the number of remaining bytes in the chunk after the + // index point. That's because PNG processes a chunk this way. + png_uint_32 bytes_left_in_idat; + + // decompressed data of the previous row + png_bytep prev_row; +} png_line_index; +typedef png_line_index FAR * png_line_indexp; + +typedef struct png_index_struct +{ + // A temporary variable used when we build the index. The variable records + // the IDAT header position of the last chunk read in so far. + png_uint_32 stream_idat_position; + + // line index information about each passes + + // the number of index points in each pass + png_uint_32 size[7]; + + // the line span of two index points of each pass + png_uint_32 step[7]; + + // the index points of each pass + png_line_indexp *pass_line_index[7]; +} png_index; +typedef png_index FAR * png_indexp; + +#define INDEX_SAMPLE_SIZE 254 +#endif + struct png_struct_def { #ifdef PNG_SETJMP_SUPPORTED @@ -156,6 +200,9 @@ struct png_struct_def png_voidp error_ptr; /* user supplied struct for error functions */ png_rw_ptr write_data_fn; /* function for writing output data */ png_rw_ptr read_data_fn; /* function for reading input data */ +#ifdef PNG_INDEX_SUPPORTED + png_seek_ptr seek_data_fn; /* function for seeking input data */ +#endif png_voidp io_ptr; /* ptr to application struct for I/O functions */ #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED @@ -485,5 +532,11 @@ struct png_struct_def png_colorspace colorspace; #endif #endif + +#ifdef PNG_INDEX_SUPPORTED + png_indexp index; + png_uint_32 total_data_read; +#endif + }; #endif /* PNGSTRUCT_H */ |