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  */
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  */
28 static void output_message(j_common_ptr info) {
29     print_message(info, "output_message");
30 }
31 
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 
43 bool JpegDecoderMgr::returnFalse(const char caller[]) {
44     print_message((j_common_ptr) &fDInfo, caller);
45     return false;
46 }
47 
48 SkCodec::Result JpegDecoderMgr::returnFailure(const char caller[], SkCodec::Result result) {
49     print_message((j_common_ptr) &fDInfo, caller);
50     return result;
51 }
52 
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 
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 
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 
96 JpegDecoderMgr::~JpegDecoderMgr() {
97     if (fInit) {
98         jpeg_destroy_decompress(&fDInfo);
99     }
100 }
101