109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com/* 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2010 The Android Open Source Project 309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com * 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com */ 709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com#include "SkJpegUtility.h" 1009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 1109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com///////////////////////////////////////////////////////////////////// 1209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic void sk_init_source(j_decompress_ptr cinfo) { 1309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 1409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 1509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->bytes_in_buffer = 0; 164161fe6b4cd8ec008a8c5635bb631d5602668b81scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 177df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com src->current_offset = 0; 187df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com#endif 19fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com src->fStream->rewind(); 20fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com} 21fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com 224161fe6b4cd8ec008a8c5635bb631d5602668b81scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 237df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.comstatic boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) { 247df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 254ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com size_t bo = (size_t) byte_offset; 267df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com 274ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com if (bo > src->current_offset) { 284ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com (void)src->fStream->skip(bo - src->current_offset); 297df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com } else { 307df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com src->fStream->rewind(); 314ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com (void)src->fStream->skip(bo); 327df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com } 337df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com 344ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com src->current_offset = bo; 357df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com src->next_input_byte = (const JOCTET*)src->fBuffer; 367df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com src->bytes_in_buffer = 0; 377df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com return true; 387df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com} 397df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com#endif 407df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com 4109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic boolean sk_fill_input_buffer(j_decompress_ptr cinfo) { 4209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 4309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) { 4409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return FALSE; 4509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 4609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); 4709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com // note that JPEG is happy with less than the full read, 4809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com // as long as the result is non-zero 4909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com if (bytes == 0) { 5009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return FALSE; 5109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 5209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 534161fe6b4cd8ec008a8c5635bb631d5602668b81scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 547df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com src->current_offset += bytes; 557df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com#endif 5609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 5709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->bytes_in_buffer = bytes; 5809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return TRUE; 5909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 6009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 6109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { 6209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 6309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 64dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com if (num_bytes > (long)src->bytes_in_buffer) { 659c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com long bytesToSkip = num_bytes - src->bytes_in_buffer; 669c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com while (bytesToSkip > 0) { 679c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com long bytes = (long)src->fStream->skip(bytesToSkip); 689c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com if (bytes <= 0 || bytes > bytesToSkip) { 699c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes); 709c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com cinfo->err->error_exit((j_common_ptr)cinfo); 719c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com return; 729c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com } 734161fe6b4cd8ec008a8c5635bb631d5602668b81scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 747df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com src->current_offset += bytes; 757df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com#endif 769c02ab1cf9e1e61b0f4ba217bf58634511cc5839reed@android.com bytesToSkip -= bytes; 7709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 7809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 7909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->bytes_in_buffer = 0; 8009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } else { 8109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->next_input_byte += num_bytes; 8209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->bytes_in_buffer -= num_bytes; 8309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 8409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 8509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 8609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) { 8709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 8809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 8909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com // what is the desired param for??? 9009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 9109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com if (!src->fStream->rewind()) { 9209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); 9309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com cinfo->err->error_exit((j_common_ptr)cinfo); 9409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return FALSE; 9509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 9609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 9709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com src->bytes_in_buffer = 0; 9809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return TRUE; 9909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 10009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 10109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic void sk_term_source(j_decompress_ptr /*cinfo*/) {} 10209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 10309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 10409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com/////////////////////////////////////////////////////////////////////////////// 10509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 1064ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.comskjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder) 1074ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com : fStream(SkRef(stream)) 1084ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com , fDecoder(decoder) { 109fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com 110fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com init_source = sk_init_source; 111fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com fill_input_buffer = sk_fill_input_buffer; 112fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com skip_input_data = sk_skip_input_data; 113fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com resync_to_restart = sk_resync_to_restart; 114fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com term_source = sk_term_source; 1154161fe6b4cd8ec008a8c5635bb631d5602668b81scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 1167df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com seek_input_data = sk_seek_input_data; 1177df632ab780d57e8bc7ac8f47beba1296c97345fdjsollen@google.com#endif 11809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize); 11909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 12009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 121fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.comskjpeg_source_mgr::~skjpeg_source_mgr() { 1224ecddbdf09fa5a08eb8ad57288f53dc040ede8b3scroggo@google.com SkSafeUnref(fStream); 123fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com} 124fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com 12509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com/////////////////////////////////////////////////////////////////////////////// 12609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 12709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic void sk_init_destination(j_compress_ptr cinfo) { 12809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; 12909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 13009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com dest->next_output_byte = dest->fBuffer; 13109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; 13209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 13309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 13409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic boolean sk_empty_output_buffer(j_compress_ptr cinfo) { 13509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; 13609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 13709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com// if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer)) 13809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com if (!dest->fStream->write(dest->fBuffer, 13909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_destination_mgr::kBufferSize)) { 14009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com ERREXIT(cinfo, JERR_FILE_WRITE); 14109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return false; 14209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 14309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 14409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com dest->next_output_byte = dest->fBuffer; 14509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; 14609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return TRUE; 14709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 14809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 14909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comstatic void sk_term_destination (j_compress_ptr cinfo) { 15009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; 15109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 15209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer; 15309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com if (size > 0) { 15409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com if (!dest->fStream->write(dest->fBuffer, size)) { 15509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com ERREXIT(cinfo, JERR_FILE_WRITE); 15609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com return; 15709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 15809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com } 15909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com dest->fStream->flush(); 16009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 16109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 16209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comskjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream) 16309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com : fStream(stream) { 16409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com this->init_destination = sk_init_destination; 16509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com this->empty_output_buffer = sk_empty_output_buffer; 16609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com this->term_destination = sk_term_destination; 16709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 16809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 16909ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.comvoid skjpeg_error_exit(j_common_ptr cinfo) { 17009ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err; 17109ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 17209ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com (*error->output_message) (cinfo); 17309ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 17409ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com /* Let the memory manager delete any temp files before we die */ 17509ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com jpeg_destroy(cinfo); 17609ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com 17709ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com longjmp(error->fJmpBuf, -1); 17809ed9d799dd9e5390de27d77563a336c6b0fcc19reed@android.com} 179