16f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 The Android Open Source Project 36f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 66f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com */ 76f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 96f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com#include "SkJpegUtility.h" 106f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 116f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com///////////////////////////////////////////////////////////////////// 126f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic void sk_init_source(j_decompress_ptr cinfo) { 136f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 146f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 156f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->bytes_in_buffer = 0; 16d79277f67824392876b82cf5635cc11f819e64dfscroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 17113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com src->current_offset = 0; 18113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com#endif 194d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com if (!src->fStream->rewind()) { 204d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); 214d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com cinfo->err->error_exit((j_common_ptr)cinfo); 224d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com } 2357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com} 2457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com 25d79277f67824392876b82cf5635cc11f819e64dfscroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 26113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.comstatic boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) { 27113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 28d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com size_t bo = (size_t) byte_offset; 29113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com 30d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com if (bo > src->current_offset) { 31d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com (void)src->fStream->skip(bo - src->current_offset); 32113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com } else { 334d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com if (!src->fStream->rewind()) { 344d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); 354d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com cinfo->err->error_exit((j_common_ptr)cinfo); 364d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com return false; 374d213ab944d96ad60a243ac1ad21c793c1acc80ascroggo@google.com } 38d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com (void)src->fStream->skip(bo); 39113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com } 40113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com 41d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com src->current_offset = bo; 42113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com src->next_input_byte = (const JOCTET*)src->fBuffer; 43113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com src->bytes_in_buffer = 0; 44113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com return true; 45113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com} 46113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com#endif 47113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com 486f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic boolean sk_fill_input_buffer(j_decompress_ptr cinfo) { 496f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 506f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) { 516f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com return FALSE; 526f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 536f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); 546f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com // note that JPEG is happy with less than the full read, 556f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com // as long as the result is non-zero 566f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com if (bytes == 0) { 576f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com return FALSE; 586f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 596f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 60d79277f67824392876b82cf5635cc11f819e64dfscroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 61113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com src->current_offset += bytes; 62113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com#endif 636f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 646f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->bytes_in_buffer = bytes; 656f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com return TRUE; 666f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 676f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 686f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { 696f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; 706f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 713f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com if (num_bytes > (long)src->bytes_in_buffer) { 728b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com size_t bytesToSkip = num_bytes - src->bytes_in_buffer; 73b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com while (bytesToSkip > 0) { 748b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com size_t bytes = src->fStream->skip(bytesToSkip); 75b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com if (bytes <= 0 || bytes > bytesToSkip) { 76b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes); 77b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com cinfo->err->error_exit((j_common_ptr)cinfo); 78b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com return; 79b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com } 80d79277f67824392876b82cf5635cc11f819e64dfscroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 81113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com src->current_offset += bytes; 82113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com#endif 83b8fd84b803b2a2f4d304e0763b83a90f582b449areed@android.com bytesToSkip -= bytes; 846f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 856f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->next_input_byte = (const JOCTET*)src->fBuffer; 866f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->bytes_in_buffer = 0; 876f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } else { 886f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->next_input_byte += num_bytes; 896f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com src->bytes_in_buffer -= num_bytes; 906f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 916f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 926f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 936f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic void sk_term_source(j_decompress_ptr /*cinfo*/) {} 946f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 956f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 966f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com/////////////////////////////////////////////////////////////////////////////// 976f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 98d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.comskjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder) 99d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com : fStream(SkRef(stream)) 100d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com , fDecoder(decoder) { 10157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com 10257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com init_source = sk_init_source; 10357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com fill_input_buffer = sk_fill_input_buffer; 10457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com skip_input_data = sk_skip_input_data; 105a93489986789bdf109064884bb940ced71110349scroggo@google.com resync_to_restart = jpeg_resync_to_restart; 10657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com term_source = sk_term_source; 107d79277f67824392876b82cf5635cc11f819e64dfscroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 108113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com seek_input_data = sk_seek_input_data; 109113994051b41366a7b25851d05cd56e89866a33bdjsollen@google.com#endif 1106f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize); 1116f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 1126f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 11357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.comskjpeg_source_mgr::~skjpeg_source_mgr() { 114d4c3565aac5c83ff0008453abed4c6d6009bb394scroggo@google.com SkSafeUnref(fStream); 11557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com} 11657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com 1176f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com/////////////////////////////////////////////////////////////////////////////// 1186f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1196f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic void sk_init_destination(j_compress_ptr cinfo) { 1206f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; 1216f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1226f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com dest->next_output_byte = dest->fBuffer; 1236f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; 1246f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 1256f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1266f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic boolean sk_empty_output_buffer(j_compress_ptr cinfo) { 1276f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; 1286f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1296f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com// if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer)) 1306f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com if (!dest->fStream->write(dest->fBuffer, 1316f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_destination_mgr::kBufferSize)) { 1326f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com ERREXIT(cinfo, JERR_FILE_WRITE); 1336f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com return false; 1346f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 1356f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1366f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com dest->next_output_byte = dest->fBuffer; 1376f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; 1386f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com return TRUE; 1396f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 1406f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1416f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comstatic void sk_term_destination (j_compress_ptr cinfo) { 1426f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; 1436f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1446f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer; 1456f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com if (size > 0) { 1466f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com if (!dest->fStream->write(dest->fBuffer, size)) { 1476f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com ERREXIT(cinfo, JERR_FILE_WRITE); 1486f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com return; 1496f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 1506f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com } 1516f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com dest->fStream->flush(); 1526f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 1536f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1546f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comskjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream) 1556f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com : fStream(stream) { 1566f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com this->init_destination = sk_init_destination; 1576f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com this->empty_output_buffer = sk_empty_output_buffer; 1586f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com this->term_destination = sk_term_destination; 1596f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 1606f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1616f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.comvoid skjpeg_error_exit(j_common_ptr cinfo) { 1626f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err; 1636f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1646f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com (*error->output_message) (cinfo); 1656f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1666f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com /* Let the memory manager delete any temp files before we die */ 1676f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com jpeg_destroy(cinfo); 1686f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com 1696f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com longjmp(error->fJmpBuf, -1); 1706f59815b3dbd19efb8a29d0115deea9c88da8ae1reed@android.com} 171