• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
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 #include "SkCodecPriv.h"
9 #include "SkJpegUtility_codec.h"
10 
11 /*
12  * Initialize the source manager
13  */
sk_init_source(j_decompress_ptr dinfo)14 static void sk_init_source(j_decompress_ptr dinfo) {
15     skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src;
16     src->next_input_byte = (const JOCTET*) src->fBuffer;
17     src->bytes_in_buffer = 0;
18 }
19 
20 /*
21  * Fill the input buffer from the stream
22  */
sk_fill_input_buffer(j_decompress_ptr dinfo)23 static boolean sk_fill_input_buffer(j_decompress_ptr dinfo) {
24     skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src;
25     size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize);
26 
27     // libjpeg is still happy with a less than full read, as long as the result is non-zero
28     if (bytes == 0) {
29         return false;
30     }
31 
32     src->next_input_byte = (const JOCTET*) src->fBuffer;
33     src->bytes_in_buffer = bytes;
34     return true;
35 }
36 
37 /*
38  * Skip a certain number of bytes in the stream
39  */
sk_skip_input_data(j_decompress_ptr dinfo,long numBytes)40 static void sk_skip_input_data(j_decompress_ptr dinfo, long numBytes) {
41     skjpeg_source_mgr* src = (skjpeg_source_mgr*) dinfo->src;
42     size_t bytes = (size_t) numBytes;
43 
44     if (bytes > src->bytes_in_buffer) {
45         size_t bytesToSkip = bytes - src->bytes_in_buffer;
46         if (bytesToSkip != src->fStream->skip(bytesToSkip)) {
47             SkCodecPrintf("Failure to skip.\n");
48             dinfo->err->error_exit((j_common_ptr) dinfo);
49             return;
50         }
51 
52         src->next_input_byte = (const JOCTET*) src->fBuffer;
53         src->bytes_in_buffer = 0;
54     } else {
55         src->next_input_byte += numBytes;
56         src->bytes_in_buffer -= numBytes;
57     }
58 }
59 
60 /*
61  * We do not need to do anything to terminate our stream
62  */
sk_term_source(j_decompress_ptr dinfo)63 static void sk_term_source(j_decompress_ptr dinfo)
64 {
65     // The current implementation of SkJpegCodec does not call
66     // jpeg_finish_decompress(), so this function is never called.
67     // If we want to modify this function to do something, we also
68     // need to modify SkJpegCodec to call jpeg_finish_decompress().
69 }
70 
71 /*
72  * Constructor for the source manager that we provide to libjpeg
73  * We provide skia implementations of all of the stream processing functions required by libjpeg
74  */
skjpeg_source_mgr(SkStream * stream)75 skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream)
76     : fStream(stream)
77 {
78     init_source = sk_init_source;
79     fill_input_buffer = sk_fill_input_buffer;
80     skip_input_data = sk_skip_input_data;
81     resync_to_restart = jpeg_resync_to_restart;
82     term_source = sk_term_source;
83 }
84 
85 /*
86  * Call longjmp to continue execution on an error
87  */
skjpeg_err_exit(j_common_ptr dinfo)88 void skjpeg_err_exit(j_common_ptr dinfo) {
89     // Simply return to Skia client code
90     // JpegDecoderMgr will take care of freeing memory
91     skjpeg_error_mgr* error = (skjpeg_error_mgr*) dinfo->err;
92     (*error->output_message) (dinfo);
93     longjmp(error->fJmpBuf, 1);
94 }
95