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 #include "src/codec/SkJpegDecoderMgr.h"
8
9 #include "include/core/SkTypes.h"
10 #include "src/codec/SkCodecPriv.h"
11 #include "src/codec/SkJpegSourceMgr.h"
12 #include "src/codec/SkJpegUtility.h"
13
14 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
15 #include "include/android/SkAndroidFrameworkUtils.h"
16 #endif
17
18 #include <cstddef>
19 #include <utility>
20
21 class SkStream;
22
23 /*
24 * Print information, warning, and error messages
25 */
print_message(const j_common_ptr info,const char caller[])26 static void print_message(const j_common_ptr info, const char caller[]) {
27 char buffer[JMSG_LENGTH_MAX];
28 info->err->format_message(info, buffer);
29 SkCodecPrintf("libjpeg error %d <%s> from %s\n", info->err->msg_code, buffer, caller);
30 }
31
32 /*
33 * Reporting function for error and warning messages.
34 */
output_message(j_common_ptr info)35 static void output_message(j_common_ptr info) {
36 print_message(info, "output_message");
37 }
38
progress_monitor(j_common_ptr info)39 static void progress_monitor(j_common_ptr info) {
40 int scan = ((j_decompress_ptr)info)->input_scan_number;
41 // Progressive images with a very large number of scans can cause the
42 // decoder to hang. Here we use the progress monitor to abort on
43 // a very large number of scans. 100 is arbitrary, but much larger
44 // than the number of scans we might expect in a normal image.
45 if (scan >= 100) {
46 skjpeg_err_exit(info);
47 }
48 }
49
50 ////////////////////////////////////////////////////////////////////////////////////////////////////
51 // JpegDecoderMgr
52
returnFalse(const char caller[])53 bool JpegDecoderMgr::returnFalse(const char caller[]) {
54 print_message((j_common_ptr) &fDInfo, caller);
55 return false;
56 }
57
returnFailure(const char caller[],SkCodec::Result result)58 SkCodec::Result JpegDecoderMgr::returnFailure(const char caller[], SkCodec::Result result) {
59 print_message((j_common_ptr) &fDInfo, caller);
60 return result;
61 }
62
getEncodedColor(SkEncodedInfo::Color * outColor)63 bool JpegDecoderMgr::getEncodedColor(SkEncodedInfo::Color* outColor) {
64 switch (fDInfo.jpeg_color_space) {
65 case JCS_GRAYSCALE:
66 *outColor = SkEncodedInfo::kGray_Color;
67 return true;
68 case JCS_YCbCr:
69 *outColor = SkEncodedInfo::kYUV_Color;
70 return true;
71 case JCS_RGB:
72 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
73 SkAndroidFrameworkUtils::SafetyNetLog("118372692");
74 #endif
75 *outColor = SkEncodedInfo::kRGB_Color;
76 return true;
77 case JCS_YCCK:
78 *outColor = SkEncodedInfo::kYCCK_Color;
79 return true;
80 case JCS_CMYK:
81 *outColor = SkEncodedInfo::kInvertedCMYK_Color;
82 return true;
83 default:
84 return false;
85 }
86 }
87
getSourceMgr()88 SkJpegSourceMgr* JpegDecoderMgr::getSourceMgr() {
89 return fSrcMgr.fSourceMgr.get();
90 }
91
JpegDecoderMgr(SkStream * stream)92 JpegDecoderMgr::JpegDecoderMgr(SkStream* stream)
93 : fSrcMgr(SkJpegSourceMgr::Make(stream)), fInit(false) {
94 // Error manager must be set before any calls to libjeg in order to handle failures
95 fDInfo.err = jpeg_std_error(&fErrorMgr);
96 fErrorMgr.error_exit = skjpeg_err_exit;
97 }
98
init()99 void JpegDecoderMgr::init() {
100 jpeg_create_decompress(&fDInfo);
101 fInit = true;
102 fDInfo.src = &fSrcMgr;
103 fDInfo.err->output_message = &output_message;
104 fDInfo.progress = &fProgressMgr;
105 fProgressMgr.progress_monitor = &progress_monitor;
106 }
107
~JpegDecoderMgr()108 JpegDecoderMgr::~JpegDecoderMgr() {
109 if (fInit) {
110 jpeg_destroy_decompress(&fDInfo);
111 }
112 }
113
114 ////////////////////////////////////////////////////////////////////////////////////////////////////
115 // JpegDecoderMgr::SourceMgr
116
117 // static
InitSource(j_decompress_ptr dinfo)118 void JpegDecoderMgr::SourceMgr::InitSource(j_decompress_ptr dinfo) {
119 JpegDecoderMgr::SourceMgr* src = (JpegDecoderMgr::SourceMgr*)dinfo->src;
120 src->fSourceMgr->initSource(src->next_input_byte, src->bytes_in_buffer);
121 }
122
123 // static
SkipInputData(j_decompress_ptr dinfo,long num_bytes_long)124 void JpegDecoderMgr::SourceMgr::SkipInputData(j_decompress_ptr dinfo, long num_bytes_long) {
125 JpegDecoderMgr::SourceMgr* src = (JpegDecoderMgr::SourceMgr*)dinfo->src;
126 size_t num_bytes = static_cast<size_t>(num_bytes_long);
127 if (!src->fSourceMgr->skipInputBytes(num_bytes, src->next_input_byte, src->bytes_in_buffer)) {
128 SkCodecPrintf("Failure to skip.\n");
129 src->next_input_byte = nullptr;
130 src->bytes_in_buffer = 0;
131 dinfo->err->error_exit((j_common_ptr)dinfo);
132 }
133 }
134
135 // static
FillInputBuffer(j_decompress_ptr dinfo)136 boolean JpegDecoderMgr::SourceMgr::FillInputBuffer(j_decompress_ptr dinfo) {
137 JpegDecoderMgr::SourceMgr* src = (JpegDecoderMgr::SourceMgr*)dinfo->src;
138 if (!src->fSourceMgr->fillInputBuffer(src->next_input_byte, src->bytes_in_buffer)) {
139 SkCodecPrintf("Failure to fill input buffer.\n");
140 src->next_input_byte = nullptr;
141 src->bytes_in_buffer = 0;
142 return false;
143 }
144 return true;
145 }
146
147 // static
TermSource(j_decompress_ptr dinfo)148 void JpegDecoderMgr::SourceMgr::TermSource(j_decompress_ptr dinfo) {}
149
SourceMgr(std::unique_ptr<SkJpegSourceMgr> sourceMgr)150 JpegDecoderMgr::SourceMgr::SourceMgr(std::unique_ptr<SkJpegSourceMgr> sourceMgr)
151 : fSourceMgr(std::move(sourceMgr)) {
152 init_source = JpegDecoderMgr::SourceMgr::InitSource;
153 fill_input_buffer = JpegDecoderMgr::SourceMgr::FillInputBuffer;
154 skip_input_data = JpegDecoderMgr::SourceMgr::SkipInputData;
155 resync_to_restart = jpeg_resync_to_restart;
156 term_source = JpegDecoderMgr::SourceMgr::TermSource;
157 }
158