1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCodecPriv.h" 9 #include "SkJpegUtility_codec.h" 10 11 /* 12 * Initialize the source manager 13 */ sk_init_source(j_decompress_ptr dinfo)14static void sk_init_source(j_decompress_ptr dinfo) { 15 skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; 16 src->next_input_byte = (const JOCTET*) src->fBuffer; 17 src->bytes_in_buffer = 0; 18 } 19 20 /* 21 * Fill the input buffer from the stream 22 */ sk_fill_input_buffer(j_decompress_ptr dinfo)23static boolean sk_fill_input_buffer(j_decompress_ptr dinfo) { 24 skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; 25 size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); 26 27 // libjpeg is still happy with a less than full read, as long as the result is non-zero 28 if (bytes == 0) { 29 return false; 30 } 31 32 src->next_input_byte = (const JOCTET*) src->fBuffer; 33 src->bytes_in_buffer = bytes; 34 return true; 35 } 36 37 /* 38 * Skip a certain number of bytes in the stream 39 */ sk_skip_input_data(j_decompress_ptr dinfo,long numBytes)40static void sk_skip_input_data(j_decompress_ptr dinfo, long numBytes) { 41 skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; 42 size_t bytes = (size_t) numBytes; 43 44 if (bytes > src->bytes_in_buffer) { 45 size_t bytesToSkip = bytes - src->bytes_in_buffer; 46 if (bytesToSkip != src->fStream->skip(bytesToSkip)) { 47 SkCodecPrintf("Failure to skip.\n"); 48 dinfo->err->error_exit((j_common_ptr) dinfo); 49 return; 50 } 51 52 src->next_input_byte = (const JOCTET*) src->fBuffer; 53 src->bytes_in_buffer = 0; 54 } else { 55 src->next_input_byte += numBytes; 56 src->bytes_in_buffer -= numBytes; 57 } 58 } 59 60 /* 61 * We do not need to do anything to terminate our stream 62 */ sk_term_source(j_decompress_ptr dinfo)63static void sk_term_source(j_decompress_ptr dinfo) 64 { 65 // The current implementation of SkJpegCodec does not call 66 // jpeg_finish_decompress(), so this function is never called. 67 // If we want to modify this function to do something, we also 68 // need to modify SkJpegCodec to call jpeg_finish_decompress(). 69 } 70 71 /* 72 * Constructor for the source manager that we provide to libjpeg 73 * We provide skia implementations of all of the stream processing functions required by libjpeg 74 */ skjpeg_source_mgr(SkStream * stream)75skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream) 76 : fStream(stream) 77 { 78 init_source = sk_init_source; 79 fill_input_buffer = sk_fill_input_buffer; 80 skip_input_data = sk_skip_input_data; 81 resync_to_restart = jpeg_resync_to_restart; 82 term_source = sk_term_source; 83 } 84 85 /* 86 * Call longjmp to continue execution on an error 87 */ skjpeg_err_exit(j_common_ptr dinfo)88void skjpeg_err_exit(j_common_ptr dinfo) { 89 // Simply return to Skia client code 90 // JpegDecoderMgr will take care of freeing memory 91 skjpeg_error_mgr* error = (skjpeg_error_mgr*) dinfo->err; 92 (*error->output_message) (dinfo); 93 longjmp(error->fJmpBuf, 1); 94 } 95