1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/codec/SkJpegUtility.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/codec/SkCodecPriv.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci/* 13cb93a386Sopenharmony_ci * Call longjmp to continue execution on an error 14cb93a386Sopenharmony_ci */ 15cb93a386Sopenharmony_civoid skjpeg_err_exit(j_common_ptr dinfo) { 16cb93a386Sopenharmony_ci // Simply return to Skia client code 17cb93a386Sopenharmony_ci // JpegDecoderMgr will take care of freeing memory 18cb93a386Sopenharmony_ci skjpeg_error_mgr* error = (skjpeg_error_mgr*) dinfo->err; 19cb93a386Sopenharmony_ci (*error->output_message) (dinfo); 20cb93a386Sopenharmony_ci if (error->fJmpBufStack.empty()) { 21cb93a386Sopenharmony_ci SK_ABORT("JPEG error with no jmp_buf set."); 22cb93a386Sopenharmony_ci } 23cb93a386Sopenharmony_ci#if defined(_JBLEN) && (defined(_JMP_BUF_DEFINED) || defined(_JBTYPE)) 24cb93a386Sopenharmony_ci longjmp((_JBTYPE*)*error->fJmpBufStack.back(), 1); 25cb93a386Sopenharmony_ci#else 26cb93a386Sopenharmony_ci longjmp(*error->fJmpBufStack.back(), 1); 27cb93a386Sopenharmony_ci#endif 28cb93a386Sopenharmony_ci} 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci// Functions for buffered sources // 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci/* 33cb93a386Sopenharmony_ci * Initialize the buffered source manager 34cb93a386Sopenharmony_ci */ 35cb93a386Sopenharmony_cistatic void sk_init_buffered_source(j_decompress_ptr dinfo) { 36cb93a386Sopenharmony_ci skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; 37cb93a386Sopenharmony_ci src->next_input_byte = (const JOCTET*) src->fBuffer; 38cb93a386Sopenharmony_ci src->bytes_in_buffer = 0; 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci/* 42cb93a386Sopenharmony_ci * Fill the input buffer from the stream 43cb93a386Sopenharmony_ci */ 44cb93a386Sopenharmony_cistatic boolean sk_fill_buffered_input_buffer(j_decompress_ptr dinfo) { 45cb93a386Sopenharmony_ci skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; 46cb93a386Sopenharmony_ci size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci // libjpeg is still happy with a less than full read, as long as the result is non-zero 49cb93a386Sopenharmony_ci if (bytes == 0) { 50cb93a386Sopenharmony_ci // Let libjpeg know that the buffer needs to be refilled 51cb93a386Sopenharmony_ci src->next_input_byte = nullptr; 52cb93a386Sopenharmony_ci src->bytes_in_buffer = 0; 53cb93a386Sopenharmony_ci return false; 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci src->next_input_byte = (const JOCTET*) src->fBuffer; 57cb93a386Sopenharmony_ci src->bytes_in_buffer = bytes; 58cb93a386Sopenharmony_ci return true; 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci/* 62cb93a386Sopenharmony_ci * Skip a certain number of bytes in the stream 63cb93a386Sopenharmony_ci */ 64cb93a386Sopenharmony_cistatic void sk_skip_buffered_input_data(j_decompress_ptr dinfo, long numBytes) { 65cb93a386Sopenharmony_ci skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src; 66cb93a386Sopenharmony_ci size_t bytes = (size_t) numBytes; 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci if (bytes > src->bytes_in_buffer) { 69cb93a386Sopenharmony_ci size_t bytesToSkip = bytes - src->bytes_in_buffer; 70cb93a386Sopenharmony_ci if (bytesToSkip != src->fStream->skip(bytesToSkip)) { 71cb93a386Sopenharmony_ci SkCodecPrintf("Failure to skip.\n"); 72cb93a386Sopenharmony_ci dinfo->err->error_exit((j_common_ptr) dinfo); 73cb93a386Sopenharmony_ci return; 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci src->next_input_byte = (const JOCTET*) src->fBuffer; 77cb93a386Sopenharmony_ci src->bytes_in_buffer = 0; 78cb93a386Sopenharmony_ci } else { 79cb93a386Sopenharmony_ci src->next_input_byte += numBytes; 80cb93a386Sopenharmony_ci src->bytes_in_buffer -= numBytes; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci/* 85cb93a386Sopenharmony_ci * We do not need to do anything to terminate our stream 86cb93a386Sopenharmony_ci */ 87cb93a386Sopenharmony_cistatic void sk_term_source(j_decompress_ptr dinfo) 88cb93a386Sopenharmony_ci{ 89cb93a386Sopenharmony_ci // The current implementation of SkJpegCodec does not call 90cb93a386Sopenharmony_ci // jpeg_finish_decompress(), so this function is never called. 91cb93a386Sopenharmony_ci // If we want to modify this function to do something, we also 92cb93a386Sopenharmony_ci // need to modify SkJpegCodec to call jpeg_finish_decompress(). 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci// Functions for memory backed sources // 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci/* 98cb93a386Sopenharmony_ci * Initialize the mem backed source manager 99cb93a386Sopenharmony_ci */ 100cb93a386Sopenharmony_cistatic void sk_init_mem_source(j_decompress_ptr dinfo) { 101cb93a386Sopenharmony_ci /* no work necessary here, all things are done in constructor */ 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_cistatic void sk_skip_mem_input_data (j_decompress_ptr cinfo, long num_bytes) { 105cb93a386Sopenharmony_ci jpeg_source_mgr* src = cinfo->src; 106cb93a386Sopenharmony_ci size_t bytes = static_cast<size_t>(num_bytes); 107cb93a386Sopenharmony_ci if(bytes > src->bytes_in_buffer) { 108cb93a386Sopenharmony_ci src->next_input_byte = nullptr; 109cb93a386Sopenharmony_ci src->bytes_in_buffer = 0; 110cb93a386Sopenharmony_ci } else { 111cb93a386Sopenharmony_ci src->next_input_byte += bytes; 112cb93a386Sopenharmony_ci src->bytes_in_buffer -= bytes; 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_cistatic boolean sk_fill_mem_input_buffer (j_decompress_ptr cinfo) { 117cb93a386Sopenharmony_ci /* The whole JPEG data is expected to reside in the supplied memory, 118cb93a386Sopenharmony_ci * buffer, so any request for more data beyond the given buffer size 119cb93a386Sopenharmony_ci * is treated as an error. 120cb93a386Sopenharmony_ci */ 121cb93a386Sopenharmony_ci return false; 122cb93a386Sopenharmony_ci} 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci/* 125cb93a386Sopenharmony_ci * Constructor for the source manager that we provide to libjpeg 126cb93a386Sopenharmony_ci * We provide skia implementations of all of the stream processing functions required by libjpeg 127cb93a386Sopenharmony_ci */ 128cb93a386Sopenharmony_ciskjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream) 129cb93a386Sopenharmony_ci : fStream(stream) 130cb93a386Sopenharmony_ci{ 131cb93a386Sopenharmony_ci if (stream->hasLength() && stream->getMemoryBase()) { 132cb93a386Sopenharmony_ci init_source = sk_init_mem_source; 133cb93a386Sopenharmony_ci fill_input_buffer = sk_fill_mem_input_buffer; 134cb93a386Sopenharmony_ci skip_input_data = sk_skip_mem_input_data; 135cb93a386Sopenharmony_ci resync_to_restart = jpeg_resync_to_restart; 136cb93a386Sopenharmony_ci term_source = sk_term_source; 137cb93a386Sopenharmony_ci bytes_in_buffer = static_cast<size_t>(stream->getLength()); 138cb93a386Sopenharmony_ci next_input_byte = static_cast<const JOCTET*>(stream->getMemoryBase()); 139cb93a386Sopenharmony_ci } else { 140cb93a386Sopenharmony_ci init_source = sk_init_buffered_source; 141cb93a386Sopenharmony_ci fill_input_buffer = sk_fill_buffered_input_buffer; 142cb93a386Sopenharmony_ci skip_input_data = sk_skip_buffered_input_data; 143cb93a386Sopenharmony_ci resync_to_restart = jpeg_resync_to_restart; 144cb93a386Sopenharmony_ci term_source = sk_term_source; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci} 147