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 "SkJpegDecoderMgr.h"
9
10 #include "SkJpegUtility.h"
11
12 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
13 #include "SkAndroidFrameworkUtils.h"
14 #endif
15
16 /*
17 * Print information, warning, and error messages
18 */
print_message(const j_common_ptr info,const char caller[])19 static void print_message(const j_common_ptr info, const char caller[]) {
20 char buffer[JMSG_LENGTH_MAX];
21 info->err->format_message(info, buffer);
22 SkCodecPrintf("libjpeg error %d <%s> from %s\n", info->err->msg_code, buffer, caller);
23 }
24
25 /*
26 * Reporting function for error and warning messages.
27 */
output_message(j_common_ptr info)28 static void output_message(j_common_ptr info) {
29 print_message(info, "output_message");
30 }
31
progress_monitor(j_common_ptr info)32 static void progress_monitor(j_common_ptr info) {
33 int scan = ((j_decompress_ptr)info)->input_scan_number;
34 // Progressive images with a very large number of scans can cause the
35 // decoder to hang. Here we use the progress monitor to abort on
36 // a very large number of scans. 100 is arbitrary, but much larger
37 // than the number of scans we might expect in a normal image.
38 if (scan >= 100) {
39 skjpeg_err_exit(info);
40 }
41 }
42
returnFalse(const char caller[])43 bool JpegDecoderMgr::returnFalse(const char caller[]) {
44 print_message((j_common_ptr) &fDInfo, caller);
45 return false;
46 }
47
returnFailure(const char caller[],SkCodec::Result result)48 SkCodec::Result JpegDecoderMgr::returnFailure(const char caller[], SkCodec::Result result) {
49 print_message((j_common_ptr) &fDInfo, caller);
50 return result;
51 }
52
getEncodedColor(SkEncodedInfo::Color * outColor)53 bool JpegDecoderMgr::getEncodedColor(SkEncodedInfo::Color* outColor) {
54 switch (fDInfo.jpeg_color_space) {
55 case JCS_GRAYSCALE:
56 *outColor = SkEncodedInfo::kGray_Color;
57 return true;
58 case JCS_YCbCr:
59 *outColor = SkEncodedInfo::kYUV_Color;
60 return true;
61 case JCS_RGB:
62 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
63 SkAndroidFrameworkUtils::SafetyNetLog("118372692");
64 #endif
65 *outColor = SkEncodedInfo::kRGB_Color;
66 return true;
67 case JCS_YCCK:
68 *outColor = SkEncodedInfo::kYCCK_Color;
69 return true;
70 case JCS_CMYK:
71 *outColor = SkEncodedInfo::kInvertedCMYK_Color;
72 return true;
73 default:
74 return false;
75 }
76 }
77
JpegDecoderMgr(SkStream * stream)78 JpegDecoderMgr::JpegDecoderMgr(SkStream* stream)
79 : fSrcMgr(stream)
80 , fInit(false)
81 {
82 // Error manager must be set before any calls to libjeg in order to handle failures
83 fDInfo.err = jpeg_std_error(&fErrorMgr);
84 fErrorMgr.error_exit = skjpeg_err_exit;
85 }
86
init()87 void JpegDecoderMgr::init() {
88 jpeg_create_decompress(&fDInfo);
89 fInit = true;
90 fDInfo.src = &fSrcMgr;
91 fDInfo.err->output_message = &output_message;
92 fDInfo.progress = &fProgressMgr;
93 fProgressMgr.progress_monitor = &progress_monitor;
94 }
95
~JpegDecoderMgr()96 JpegDecoderMgr::~JpegDecoderMgr() {
97 if (fInit) {
98 jpeg_destroy_decompress(&fDInfo);
99 }
100 }
101