Home | History | Annotate | Download | only in images
      1 /*
      2  * Copyright 2010 The Android Open Source Project
      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 
      9 #include "SkJpegUtility.h"
     10 
     11 /////////////////////////////////////////////////////////////////////
     12 static void sk_init_source(j_decompress_ptr cinfo) {
     13     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
     14     src->next_input_byte = (const JOCTET*)src->fBuffer;
     15     src->bytes_in_buffer = 0;
     16 #ifdef SK_BUILD_FOR_ANDROID
     17     src->current_offset = 0;
     18 #endif
     19     if (!src->fStream->rewind()) {
     20         SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
     21         cinfo->err->error_exit((j_common_ptr)cinfo);
     22     }
     23 }
     24 
     25 #ifdef SK_BUILD_FOR_ANDROID
     26 static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
     27     skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
     28     size_t bo = (size_t) byte_offset;
     29 
     30     if (bo > src->current_offset) {
     31         (void)src->fStream->skip(bo - src->current_offset);
     32     } else {
     33         if (!src->fStream->rewind()) {
     34             SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
     35             cinfo->err->error_exit((j_common_ptr)cinfo);
     36             return false;
     37         }
     38         (void)src->fStream->skip(bo);
     39     }
     40 
     41     src->current_offset = bo;
     42     src->next_input_byte = (const JOCTET*)src->fBuffer;
     43     src->bytes_in_buffer = 0;
     44     return true;
     45 }
     46 #endif
     47 
     48 static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
     49     skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
     50     if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
     51         return FALSE;
     52     }
     53     size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
     54     // note that JPEG is happy with less than the full read,
     55     // as long as the result is non-zero
     56     if (bytes == 0) {
     57         return FALSE;
     58     }
     59 
     60 #ifdef SK_BUILD_FOR_ANDROID
     61     src->current_offset += bytes;
     62 #endif
     63     src->next_input_byte = (const JOCTET*)src->fBuffer;
     64     src->bytes_in_buffer = bytes;
     65     return TRUE;
     66 }
     67 
     68 static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
     69     skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
     70 
     71     if (num_bytes > (long)src->bytes_in_buffer) {
     72         size_t bytesToSkip = num_bytes - src->bytes_in_buffer;
     73         while (bytesToSkip > 0) {
     74             size_t bytes = src->fStream->skip(bytesToSkip);
     75             if (bytes <= 0 || bytes > bytesToSkip) {
     76 //              SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes);
     77                 cinfo->err->error_exit((j_common_ptr)cinfo);
     78                 return;
     79             }
     80 #ifdef SK_BUILD_FOR_ANDROID
     81             src->current_offset += bytes;
     82 #endif
     83             bytesToSkip -= bytes;
     84         }
     85         src->next_input_byte = (const JOCTET*)src->fBuffer;
     86         src->bytes_in_buffer = 0;
     87     } else {
     88         src->next_input_byte += num_bytes;
     89         src->bytes_in_buffer -= num_bytes;
     90     }
     91 }
     92 
     93 static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
     94 
     95 
     96 ///////////////////////////////////////////////////////////////////////////////
     97 
     98 skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder)
     99     : fStream(SkRef(stream))
    100     , fDecoder(decoder) {
    101 
    102     init_source = sk_init_source;
    103     fill_input_buffer = sk_fill_input_buffer;
    104     skip_input_data = sk_skip_input_data;
    105     resync_to_restart = jpeg_resync_to_restart;
    106     term_source = sk_term_source;
    107 #ifdef SK_BUILD_FOR_ANDROID
    108     seek_input_data = sk_seek_input_data;
    109 #endif
    110 //    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
    111 }
    112 
    113 skjpeg_source_mgr::~skjpeg_source_mgr() {
    114     SkSafeUnref(fStream);
    115 }
    116 
    117 ///////////////////////////////////////////////////////////////////////////////
    118 
    119 static void sk_init_destination(j_compress_ptr cinfo) {
    120     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    121 
    122     dest->next_output_byte = dest->fBuffer;
    123     dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
    124 }
    125 
    126 static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
    127     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    128 
    129 //  if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer))
    130     if (!dest->fStream->write(dest->fBuffer,
    131             skjpeg_destination_mgr::kBufferSize)) {
    132         ERREXIT(cinfo, JERR_FILE_WRITE);
    133         return false;
    134     }
    135 
    136     dest->next_output_byte = dest->fBuffer;
    137     dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
    138     return TRUE;
    139 }
    140 
    141 static void sk_term_destination (j_compress_ptr cinfo) {
    142     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    143 
    144     size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer;
    145     if (size > 0) {
    146         if (!dest->fStream->write(dest->fBuffer, size)) {
    147             ERREXIT(cinfo, JERR_FILE_WRITE);
    148             return;
    149         }
    150     }
    151     dest->fStream->flush();
    152 }
    153 
    154 skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream)
    155         : fStream(stream) {
    156     this->init_destination = sk_init_destination;
    157     this->empty_output_buffer = sk_empty_output_buffer;
    158     this->term_destination = sk_term_destination;
    159 }
    160 
    161 void skjpeg_error_exit(j_common_ptr cinfo) {
    162     skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
    163 
    164     (*error->output_message) (cinfo);
    165 
    166     /* Let the memory manager delete any temp files before we die */
    167     jpeg_destroy(cinfo);
    168 
    169     longjmp(error->fJmpBuf, -1);
    170 }
    171