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