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 */
print_message(const j_common_ptr info,const char caller[])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 */
output_message(j_common_ptr info)24 static void output_message(j_common_ptr info) {
25 print_message(info, "output_message");
26 }
27
progress_monitor(j_common_ptr info)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
returnFalse(const char caller[])39 bool JpegDecoderMgr::returnFalse(const char caller[]) {
40 print_message((j_common_ptr) &fDInfo, caller);
41 return false;
42 }
43
returnFailure(const char caller[],SkCodec::Result result)44 SkCodec::Result JpegDecoderMgr::returnFailure(const char caller[], SkCodec::Result result) {
45 print_message((j_common_ptr) &fDInfo, caller);
46 return result;
47 }
48
getEncodedColor(SkEncodedInfo::Color * outColor)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
JpegDecoderMgr(SkStream * stream)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
init()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
~JpegDecoderMgr()89 JpegDecoderMgr::~JpegDecoderMgr() {
90 if (fInit) {
91 jpeg_destroy_decompress(&fDInfo);
92 }
93 }
94
getJmpBuf()95 jmp_buf& JpegDecoderMgr::getJmpBuf() {
96 return fErrorMgr.fJmpBuf;
97 }
98
dinfo()99 jpeg_decompress_struct* JpegDecoderMgr::dinfo() {
100 return &fDInfo;
101 }
102