Home | History | Annotate | Download | only in images
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "SkJpegUtility.h"
     18 
     19 /////////////////////////////////////////////////////////////////////
     20 static void sk_init_source(j_decompress_ptr cinfo) {
     21     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
     22     src->next_input_byte = (const JOCTET*)src->fBuffer;
     23     src->bytes_in_buffer = 0;
     24     src->current_offset = 0;
     25     src->fStream->rewind();
     26 }
     27 
     28 static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
     29     skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
     30 
     31     if (byte_offset > src->current_offset) {
     32         (void)src->fStream->skip(byte_offset - src->current_offset);
     33     } else {
     34         src->fStream->rewind();
     35         (void)src->fStream->skip(byte_offset);
     36     }
     37 
     38     src->current_offset = byte_offset;
     39     src->next_input_byte = (const JOCTET*)src->fBuffer;
     40     src->bytes_in_buffer = 0;
     41     return TRUE;
     42 }
     43 
     44 static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
     45     skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
     46     if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
     47         return FALSE;
     48     }
     49     size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
     50     // note that JPEG is happy with less than the full read,
     51     // as long as the result is non-zero
     52     if (bytes == 0) {
     53         return FALSE;
     54     }
     55 
     56     src->current_offset += bytes;
     57     src->next_input_byte = (const JOCTET*)src->fBuffer;
     58     src->bytes_in_buffer = bytes;
     59     return TRUE;
     60 }
     61 
     62 static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
     63     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
     64 
     65     if (num_bytes > (long)src->bytes_in_buffer) {
     66         long bytesToSkip = num_bytes - src->bytes_in_buffer;
     67         while (bytesToSkip > 0) {
     68             long bytes = (long)src->fStream->skip(bytesToSkip);
     69             if (bytes <= 0 || bytes > bytesToSkip) {
     70 //              SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes);
     71                 cinfo->err->error_exit((j_common_ptr)cinfo);
     72                 return;
     73             }
     74             src->current_offset += bytes;
     75             bytesToSkip -= bytes;
     76         }
     77         src->next_input_byte = (const JOCTET*)src->fBuffer;
     78         src->bytes_in_buffer = 0;
     79     } else {
     80         src->next_input_byte += num_bytes;
     81         src->bytes_in_buffer -= num_bytes;
     82     }
     83 }
     84 
     85 static boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) {
     86     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
     87 
     88     // what is the desired param for???
     89 
     90     if (!src->fStream->rewind()) {
     91         SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
     92         cinfo->err->error_exit((j_common_ptr)cinfo);
     93         return FALSE;
     94     }
     95     src->next_input_byte = (const JOCTET*)src->fBuffer;
     96     src->bytes_in_buffer = 0;
     97     return TRUE;
     98 }
     99 
    100 static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
    101 
    102 
    103 static void skmem_init_source(j_decompress_ptr cinfo) {
    104     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
    105     src->next_input_byte = (const JOCTET*)src->fMemoryBase;
    106     src->start_input_byte = (const JOCTET*)src->fMemoryBase;
    107     src->bytes_in_buffer = src->fMemoryBaseSize;
    108     src->current_offset = src->fMemoryBaseSize;
    109 }
    110 
    111 static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
    112     SkDebugf("xxxxxxxxxxxxxx skmem_fill_input_buffer called\n");
    113     return FALSE;
    114 }
    115 
    116 static void skmem_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
    117     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
    118 //    SkDebugf("xxxxxxxxxxxxxx skmem_skip_input_data called %d\n", num_bytes);
    119     src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes);
    120     src->bytes_in_buffer -= num_bytes;
    121 }
    122 
    123 static boolean skmem_resync_to_restart(j_decompress_ptr cinfo, int desired) {
    124     SkDebugf("xxxxxxxxxxxxxx skmem_resync_to_restart called\n");
    125     return TRUE;
    126 }
    127 
    128 static void skmem_term_source(j_decompress_ptr /*cinfo*/) {}
    129 
    130 
    131 ///////////////////////////////////////////////////////////////////////////////
    132 
    133 skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
    134                                      bool ownStream) : fStream(stream) {
    135     fDecoder = decoder;
    136     const void* baseAddr = stream->getMemoryBase();
    137     size_t bufferSize = 4096;
    138     size_t len;
    139     fMemoryBase = NULL;
    140     fUnrefStream = ownStream;
    141     fMemoryBaseSize = 0;
    142 
    143     init_source = sk_init_source;
    144     fill_input_buffer = sk_fill_input_buffer;
    145     skip_input_data = sk_skip_input_data;
    146     resync_to_restart = sk_resync_to_restart;
    147     term_source = sk_term_source;
    148     seek_input_data = sk_seek_input_data;
    149 //    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
    150 }
    151 
    152 skjpeg_source_mgr::~skjpeg_source_mgr() {
    153     if (fMemoryBase) {
    154         sk_free(fMemoryBase);
    155     }
    156     if (fUnrefStream) {
    157         fStream->unref();
    158     }
    159 }
    160 
    161 ///////////////////////////////////////////////////////////////////////////////
    162 
    163 static void sk_init_destination(j_compress_ptr cinfo) {
    164     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    165 
    166     dest->next_output_byte = dest->fBuffer;
    167     dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
    168 }
    169 
    170 static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
    171     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    172 
    173 //  if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer))
    174     if (!dest->fStream->write(dest->fBuffer,
    175             skjpeg_destination_mgr::kBufferSize)) {
    176         ERREXIT(cinfo, JERR_FILE_WRITE);
    177         return false;
    178     }
    179 
    180     dest->next_output_byte = dest->fBuffer;
    181     dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
    182     return TRUE;
    183 }
    184 
    185 static void sk_term_destination (j_compress_ptr cinfo) {
    186     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    187 
    188     size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer;
    189     if (size > 0) {
    190         if (!dest->fStream->write(dest->fBuffer, size)) {
    191             ERREXIT(cinfo, JERR_FILE_WRITE);
    192             return;
    193         }
    194     }
    195     dest->fStream->flush();
    196 }
    197 
    198 skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream)
    199         : fStream(stream) {
    200     this->init_destination = sk_init_destination;
    201     this->empty_output_buffer = sk_empty_output_buffer;
    202     this->term_destination = sk_term_destination;
    203 }
    204 
    205 void skjpeg_error_exit(j_common_ptr cinfo) {
    206     skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
    207 
    208     (*error->output_message) (cinfo);
    209 
    210     /* Let the memory manager delete any temp files before we die */
    211     jpeg_destroy(cinfo);
    212 
    213     longjmp(error->fJmpBuf, -1);
    214 }
    215