diff --git a/src/codec/SkJpegUtility.cpp b/src/codec/SkJpegUtility.cpp index 2cf36bacf1..c9c8d3b11c 100644 --- a/src/codec/SkJpegUtility.cpp +++ b/src/codec/SkJpegUtility.cpp @@ -10,9 +10,22 @@ #include "SkCodecPriv.h" /* - * Initialize the source manager + * Call longjmp to continue execution on an error */ -static void sk_init_source(j_decompress_ptr dinfo) { +void skjpeg_err_exit(j_common_ptr dinfo) { + // Simply return to Skia client code + // JpegDecoderMgr will take care of freeing memory + skjpeg_error_mgr* error = (skjpeg_error_mgr*) dinfo->err; + (*error->output_message) (dinfo); + longjmp(error->fJmpBuf, 1); +} + +// Functions for buffered sources // + +/* + * Initialize the buffered source manager + */ +static void sk_init_buffered_source(j_decompress_ptr dinfo) { skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; src->next_input_byte = (const JOCTET*) src->fBuffer; src->bytes_in_buffer = 0; @@ -21,7 +34,7 @@ static void sk_init_source(j_decompress_ptr dinfo) { /* * Fill the input buffer from the stream */ -static boolean sk_fill_input_buffer(j_decompress_ptr dinfo) { +static boolean sk_fill_buffered_input_buffer(j_decompress_ptr dinfo) { skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); @@ -38,7 +51,7 @@ static boolean sk_fill_input_buffer(j_decompress_ptr dinfo) { /* * Skip a certain number of bytes in the stream */ -static void sk_skip_input_data(j_decompress_ptr dinfo, long numBytes) { +static void sk_skip_buffered_input_data(j_decompress_ptr dinfo, long numBytes) { skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; size_t bytes = (size_t) numBytes; @@ -69,6 +82,35 @@ static void sk_term_source(j_decompress_ptr dinfo) // need to modify SkJpegCodec to call jpeg_finish_decompress(). } +// Functions for memory backed sources // + +/* + * Initialize the mem backed source manager + */ +static void sk_init_mem_source(j_decompress_ptr dinfo) { + /* no work necessary here, all things are done in constructor */ +} + +static void sk_skip_mem_input_data (j_decompress_ptr cinfo, long num_bytes) { + jpeg_source_mgr* src = cinfo->src; + size_t bytes = static_cast(num_bytes); + if(bytes > src->bytes_in_buffer) { + src->next_input_byte = nullptr; + src->bytes_in_buffer = 0; + } else { + src->next_input_byte += bytes; + src->bytes_in_buffer -= bytes; + } +} + +static boolean sk_fill_mem_input_buffer (j_decompress_ptr cinfo) { + /* The whole JPEG data is expected to reside in the supplied memory, + * buffer, so any request for more data beyond the given buffer size + * is treated as an error. + */ + return false; +} + /* * Constructor for the source manager that we provide to libjpeg * We provide skia implementations of all of the stream processing functions required by libjpeg @@ -76,20 +118,19 @@ static void sk_term_source(j_decompress_ptr dinfo) skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream) : fStream(stream) { - init_source = sk_init_source; - fill_input_buffer = sk_fill_input_buffer; - skip_input_data = sk_skip_input_data; - resync_to_restart = jpeg_resync_to_restart; - term_source = sk_term_source; -} - -/* - * Call longjmp to continue execution on an error - */ -void skjpeg_err_exit(j_common_ptr dinfo) { - // Simply return to Skia client code - // JpegDecoderMgr will take care of freeing memory - skjpeg_error_mgr* error = (skjpeg_error_mgr*) dinfo->err; - (*error->output_message) (dinfo); - longjmp(error->fJmpBuf, 1); + if (stream->hasLength() && stream->getMemoryBase()) { + init_source = sk_init_mem_source; + fill_input_buffer = sk_fill_mem_input_buffer; + skip_input_data = sk_skip_mem_input_data; + resync_to_restart = jpeg_resync_to_restart; + term_source = sk_term_source; + bytes_in_buffer = static_cast(stream->getLength()); + next_input_byte = static_cast(stream->getMemoryBase()); + } else { + init_source = sk_init_buffered_source; + fill_input_buffer = sk_fill_buffered_input_buffer; + skip_input_data = sk_skip_buffered_input_data; + resync_to_restart = jpeg_resync_to_restart; + term_source = sk_term_source; + } }