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_JPEG_INDEX_SUPPORTED
     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_JPEG_INDEX_SUPPORTED
     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 != nullptr && 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_JPEG_INDEX_SUPPORTED
     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_JPEG_INDEX_SUPPORTED
     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(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_JPEG_INDEX_SUPPORTED
    108     seek_input_data = sk_seek_input_data;
    109 #endif
    110 //    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
    111 }
    112 
    113 ///////////////////////////////////////////////////////////////////////////////
    114 
    115 static void sk_init_destination(j_compress_ptr cinfo) {
    116     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    117 
    118     dest->next_output_byte = dest->fBuffer;
    119     dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
    120 }
    121 
    122 static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
    123     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    124 
    125 //  if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer))
    126     if (!dest->fStream->write(dest->fBuffer,
    127             skjpeg_destination_mgr::kBufferSize)) {
    128         ERREXIT(cinfo, JERR_FILE_WRITE);
    129         return false;
    130     }
    131 
    132     dest->next_output_byte = dest->fBuffer;
    133     dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize;
    134     return TRUE;
    135 }
    136 
    137 static void sk_term_destination (j_compress_ptr cinfo) {
    138     skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest;
    139 
    140     size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer;
    141     if (size > 0) {
    142         if (!dest->fStream->write(dest->fBuffer, size)) {
    143             ERREXIT(cinfo, JERR_FILE_WRITE);
    144             return;
    145         }
    146     }
    147     dest->fStream->flush();
    148 }
    149 
    150 skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream)
    151         : fStream(stream) {
    152     this->init_destination = sk_init_destination;
    153     this->empty_output_buffer = sk_empty_output_buffer;
    154     this->term_destination = sk_term_destination;
    155 }
    156 
    157 void skjpeg_error_exit(j_common_ptr cinfo) {
    158     skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err;
    159 
    160     (*error->output_message) (cinfo);
    161 
    162     /* Let the memory manager delete any temp files before we die */
    163     jpeg_destroy(cinfo);
    164 
    165     longjmp(error->fJmpBuf, -1);
    166 }
    167