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