blob: b5780c55817e670ae545d1c7f16bddc9e77368ea [file] [log] [blame]
msarette16b04a2015-04-15 07:32:19 -07001/*
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 "SkCodec.h"
mtkleine721a8e2016-02-06 19:12:23 -08009#include "SkMSAN.h"
msarette16b04a2015-04-15 07:32:19 -070010#include "SkJpegCodec.h"
11#include "SkJpegDecoderMgr.h"
mtklein525e90a2015-06-18 09:58:57 -070012#include "SkJpegUtility_codec.h"
msarette16b04a2015-04-15 07:32:19 -070013#include "SkCodecPriv.h"
14#include "SkColorPriv.h"
15#include "SkStream.h"
16#include "SkTemplates.h"
17#include "SkTypes.h"
18
msarett1c8a5872015-07-07 08:50:01 -070019// stdio is needed for libjpeg-turbo
msarette16b04a2015-04-15 07:32:19 -070020#include <stdio.h>
21
22extern "C" {
23 #include "jerror.h"
msarette16b04a2015-04-15 07:32:19 -070024 #include "jpeglib.h"
25}
26
scroggodb30be22015-12-08 18:54:13 -080027bool SkJpegCodec::IsJpeg(const void* buffer, size_t bytesRead) {
msarette16b04a2015-04-15 07:32:19 -070028 static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF };
scroggodb30be22015-12-08 18:54:13 -080029 return bytesRead >= 3 && !memcmp(buffer, jpegSig, sizeof(jpegSig));
msarette16b04a2015-04-15 07:32:19 -070030}
31
32bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
33 JpegDecoderMgr** decoderMgrOut) {
34
35 // Create a JpegDecoderMgr to own all of the decompress information
halcanary385fe4d2015-08-26 13:07:48 -070036 SkAutoTDelete<JpegDecoderMgr> decoderMgr(new JpegDecoderMgr(stream));
msarette16b04a2015-04-15 07:32:19 -070037
38 // libjpeg errors will be caught and reported here
39 if (setjmp(decoderMgr->getJmpBuf())) {
40 return decoderMgr->returnFalse("setjmp");
41 }
42
43 // Initialize the decompress info and the source manager
44 decoderMgr->init();
45
46 // Read the jpeg header
msarettfbccb592015-09-01 06:43:41 -070047 if (JPEG_HEADER_OK != jpeg_read_header(decoderMgr->dinfo(), true)) {
msarette16b04a2015-04-15 07:32:19 -070048 return decoderMgr->returnFalse("read_header");
49 }
50
halcanary96fcdcc2015-08-27 07:41:13 -070051 if (nullptr != codecOut) {
msarette16b04a2015-04-15 07:32:19 -070052 // Recommend the color type to decode to
53 const SkColorType colorType = decoderMgr->getColorType();
54
55 // Create image info object and the codec
56 const SkImageInfo& imageInfo = SkImageInfo::Make(decoderMgr->dinfo()->image_width,
57 decoderMgr->dinfo()->image_height, colorType, kOpaque_SkAlphaType);
halcanary385fe4d2015-08-26 13:07:48 -070058 *codecOut = new SkJpegCodec(imageInfo, stream, decoderMgr.detach());
msarette16b04a2015-04-15 07:32:19 -070059 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070060 SkASSERT(nullptr != decoderMgrOut);
msarette16b04a2015-04-15 07:32:19 -070061 *decoderMgrOut = decoderMgr.detach();
62 }
63 return true;
64}
65
66SkCodec* SkJpegCodec::NewFromStream(SkStream* stream) {
67 SkAutoTDelete<SkStream> streamDeleter(stream);
halcanary96fcdcc2015-08-27 07:41:13 -070068 SkCodec* codec = nullptr;
69 if (ReadHeader(stream, &codec, nullptr)) {
msarette16b04a2015-04-15 07:32:19 -070070 // Codec has taken ownership of the stream, we do not need to delete it
71 SkASSERT(codec);
72 streamDeleter.detach();
73 return codec;
74 }
halcanary96fcdcc2015-08-27 07:41:13 -070075 return nullptr;
msarette16b04a2015-04-15 07:32:19 -070076}
77
78SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream,
79 JpegDecoderMgr* decoderMgr)
80 : INHERITED(srcInfo, stream)
81 , fDecoderMgr(decoderMgr)
msarettfbccb592015-09-01 06:43:41 -070082 , fReadyState(decoderMgr->dinfo()->global_state)
msarett91c22b22016-02-22 12:27:46 -080083 , fSwizzlerSubset(SkIRect::MakeEmpty())
msarette16b04a2015-04-15 07:32:19 -070084{}
85
86/*
emmaleer8f4ba762015-08-14 07:44:46 -070087 * Return the row bytes of a particular image type and width
88 */
msarett23e78d32016-02-06 15:58:50 -080089static size_t get_row_bytes(const j_decompress_ptr dinfo) {
msarett70e418b2016-02-12 12:35:48 -080090#ifdef TURBO_HAS_565
91 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
92 dinfo->out_color_components;
93#else
94 const size_t colorBytes = dinfo->out_color_components;
95#endif
emmaleer8f4ba762015-08-14 07:44:46 -070096 return dinfo->output_width * colorBytes;
97
98}
scroggoe7fc14b2015-10-02 13:14:46 -070099
100/*
101 * Calculate output dimensions based on the provided factors.
102 *
103 * Not to be used on the actual jpeg_decompress_struct used for decoding, since it will
104 * incorrectly modify num_components.
105 */
106void calc_output_dimensions(jpeg_decompress_struct* dinfo, unsigned int num, unsigned int denom) {
107 dinfo->num_components = 0;
108 dinfo->scale_num = num;
109 dinfo->scale_denom = denom;
110 jpeg_calc_output_dimensions(dinfo);
111}
112
emmaleer8f4ba762015-08-14 07:44:46 -0700113/*
msarette16b04a2015-04-15 07:32:19 -0700114 * Return a valid set of output dimensions for this decoder, given an input scale
115 */
116SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
msarett1c8a5872015-07-07 08:50:01 -0700117 // libjpeg-turbo supports scaling by 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1, so we will
118 // support these as well
scroggoe7fc14b2015-10-02 13:14:46 -0700119 unsigned int num;
120 unsigned int denom = 8;
msarettfdb47572015-10-13 12:50:14 -0700121 if (desiredScale >= 0.9375) {
msarett1c8a5872015-07-07 08:50:01 -0700122 num = 8;
msarettfdb47572015-10-13 12:50:14 -0700123 } else if (desiredScale >= 0.8125) {
msarett1c8a5872015-07-07 08:50:01 -0700124 num = 7;
msarettfdb47572015-10-13 12:50:14 -0700125 } else if (desiredScale >= 0.6875f) {
msarett1c8a5872015-07-07 08:50:01 -0700126 num = 6;
msarettfdb47572015-10-13 12:50:14 -0700127 } else if (desiredScale >= 0.5625f) {
msarett1c8a5872015-07-07 08:50:01 -0700128 num = 5;
msarettfdb47572015-10-13 12:50:14 -0700129 } else if (desiredScale >= 0.4375f) {
msarett1c8a5872015-07-07 08:50:01 -0700130 num = 4;
msarettfdb47572015-10-13 12:50:14 -0700131 } else if (desiredScale >= 0.3125f) {
msarett1c8a5872015-07-07 08:50:01 -0700132 num = 3;
msarettfdb47572015-10-13 12:50:14 -0700133 } else if (desiredScale >= 0.1875f) {
msarett1c8a5872015-07-07 08:50:01 -0700134 num = 2;
msarette16b04a2015-04-15 07:32:19 -0700135 } else {
msarett1c8a5872015-07-07 08:50:01 -0700136 num = 1;
msarette16b04a2015-04-15 07:32:19 -0700137 }
138
139 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
140 jpeg_decompress_struct dinfo;
mtkleinf7aaadb2015-04-16 06:09:27 -0700141 sk_bzero(&dinfo, sizeof(dinfo));
msarette16b04a2015-04-15 07:32:19 -0700142 dinfo.image_width = this->getInfo().width();
143 dinfo.image_height = this->getInfo().height();
msarettfbccb592015-09-01 06:43:41 -0700144 dinfo.global_state = fReadyState;
scroggoe7fc14b2015-10-02 13:14:46 -0700145 calc_output_dimensions(&dinfo, num, denom);
msarette16b04a2015-04-15 07:32:19 -0700146
147 // Return the calculated output dimensions for the given scale
148 return SkISize::Make(dinfo.output_width, dinfo.output_height);
149}
150
scroggob427db12015-08-12 07:24:13 -0700151bool SkJpegCodec::onRewind() {
halcanary96fcdcc2015-08-27 07:41:13 -0700152 JpegDecoderMgr* decoderMgr = nullptr;
153 if (!ReadHeader(this->stream(), nullptr, &decoderMgr)) {
scroggob427db12015-08-12 07:24:13 -0700154 return fDecoderMgr->returnFalse("could not rewind");
msarett97fdea62015-04-29 08:17:15 -0700155 }
halcanary96fcdcc2015-08-27 07:41:13 -0700156 SkASSERT(nullptr != decoderMgr);
scroggob427db12015-08-12 07:24:13 -0700157 fDecoderMgr.reset(decoderMgr);
158 return true;
msarett97fdea62015-04-29 08:17:15 -0700159}
160
161/*
msarett1c8a5872015-07-07 08:50:01 -0700162 * Checks if the conversion between the input image and the requested output
163 * image has been implemented
164 * Sets the output color space
165 */
166bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
167 const SkImageInfo& src = this->getInfo();
168
169 // Ensure that the profile type is unchanged
170 if (dst.profileType() != src.profileType()) {
171 return false;
172 }
173
scroggoc5560be2016-02-03 09:42:42 -0800174 if (kUnknown_SkAlphaType == dst.alphaType()) {
msarett1c8a5872015-07-07 08:50:01 -0700175 return false;
176 }
177
scroggoc5560be2016-02-03 09:42:42 -0800178 if (kOpaque_SkAlphaType != dst.alphaType()) {
179 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
180 "- it is being decoded as non-opaque, which will draw slower\n");
181 }
182
msarett1c8a5872015-07-07 08:50:01 -0700183 // Check if we will decode to CMYK because a conversion to RGBA is not supported
184 J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space;
185 bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace;
186
187 // Check for valid color types and set the output color space
188 switch (dst.colorType()) {
189 case kN32_SkColorType:
190 if (isCMYK) {
191 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
192 } else {
msarett70e418b2016-02-12 12:35:48 -0800193#ifdef LIBJPEG_TURBO_VERSION
194 // Check the byte ordering of the RGBA color space for the
195 // current platform
196 #ifdef SK_PMCOLOR_IS_RGBA
197 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
198 #else
199 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
200 #endif
benjaminwagneraada3e82015-10-27 09:14:29 -0700201#else
msarett70e418b2016-02-12 12:35:48 -0800202 fDecoderMgr->dinfo()->out_color_space = JCS_RGB;
msarett1c8a5872015-07-07 08:50:01 -0700203#endif
204 }
205 return true;
206 case kRGB_565_SkColorType:
207 if (isCMYK) {
scroggoef27d892015-10-23 09:29:22 -0700208 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
msarett1c8a5872015-07-07 08:50:01 -0700209 } else {
msarett70e418b2016-02-12 12:35:48 -0800210#ifdef TURBO_HAS_565
msarett8ff6ca62015-09-18 12:06:04 -0700211 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
msarett1c8a5872015-07-07 08:50:01 -0700212 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
msarett70e418b2016-02-12 12:35:48 -0800213#else
214 fDecoderMgr->dinfo()->out_color_space = JCS_RGB;
215#endif
msarett1c8a5872015-07-07 08:50:01 -0700216 }
217 return true;
218 case kGray_8_SkColorType:
219 if (isCMYK) {
220 return false;
221 } else {
222 // We will enable decodes to gray even if the image is color because this is
223 // much faster than decoding to color and then converting
224 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
225 }
226 return true;
227 default:
228 return false;
229 }
230}
231
232/*
mtkleine721a8e2016-02-06 19:12:23 -0800233 * Checks if we can natively scale to the requested dimensions and natively scales the
emmaleer8f4ba762015-08-14 07:44:46 -0700234 * dimensions if possible
msarett97fdea62015-04-29 08:17:15 -0700235 */
scroggoe7fc14b2015-10-02 13:14:46 -0700236bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
237 if (setjmp(fDecoderMgr->getJmpBuf())) {
238 return fDecoderMgr->returnFalse("onDimensionsSupported/setjmp");
239 }
240
241 const unsigned int dstWidth = size.width();
242 const unsigned int dstHeight = size.height();
243
244 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
245 // FIXME: Why is this necessary?
246 jpeg_decompress_struct dinfo;
247 sk_bzero(&dinfo, sizeof(dinfo));
248 dinfo.image_width = this->getInfo().width();
249 dinfo.image_height = this->getInfo().height();
250 dinfo.global_state = fReadyState;
251
msarett1c8a5872015-07-07 08:50:01 -0700252 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
scroggoe7fc14b2015-10-02 13:14:46 -0700253 unsigned int num = 8;
254 const unsigned int denom = 8;
255 calc_output_dimensions(&dinfo, num, denom);
256 while (dinfo.output_width != dstWidth || dinfo.output_height != dstHeight) {
msarett97fdea62015-04-29 08:17:15 -0700257
258 // Return a failure if we have tried all of the possible scales
scroggoe7fc14b2015-10-02 13:14:46 -0700259 if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
emmaleer8f4ba762015-08-14 07:44:46 -0700260 return false;
msarett97fdea62015-04-29 08:17:15 -0700261 }
262
263 // Try the next scale
scroggoe7fc14b2015-10-02 13:14:46 -0700264 num -= 1;
265 calc_output_dimensions(&dinfo, num, denom);
msarett97fdea62015-04-29 08:17:15 -0700266 }
scroggoe7fc14b2015-10-02 13:14:46 -0700267
268 fDecoderMgr->dinfo()->scale_num = num;
269 fDecoderMgr->dinfo()->scale_denom = denom;
msarett97fdea62015-04-29 08:17:15 -0700270 return true;
271}
272
273/*
msarette16b04a2015-04-15 07:32:19 -0700274 * Performs the jpeg decode
275 */
276SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
277 void* dst, size_t dstRowBytes,
msarette6dd0042015-10-09 11:07:34 -0700278 const Options& options, SkPMColor*, int*,
279 int* rowsDecoded) {
scroggob636b452015-07-22 07:16:20 -0700280 if (options.fSubset) {
281 // Subsets are not supported.
282 return kUnimplemented;
283 }
284
msarette16b04a2015-04-15 07:32:19 -0700285 // Get a pointer to the decompress info since we will use it quite frequently
286 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
287
288 // Set the jump location for libjpeg errors
289 if (setjmp(fDecoderMgr->getJmpBuf())) {
290 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
291 }
292
msarett1c8a5872015-07-07 08:50:01 -0700293 // Check if we can decode to the requested destination and set the output color space
294 if (!this->setOutputColorSpace(dstInfo)) {
msarette16b04a2015-04-15 07:32:19 -0700295 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion);
296 }
msarette16b04a2015-04-15 07:32:19 -0700297
msarette16b04a2015-04-15 07:32:19 -0700298 // Now, given valid output dimensions, we can start the decompress
msarettfbccb592015-09-01 06:43:41 -0700299 if (!jpeg_start_decompress(dinfo)) {
msarette16b04a2015-04-15 07:32:19 -0700300 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
301 }
302
msarett1c8a5872015-07-07 08:50:01 -0700303 // The recommended output buffer height should always be 1 in high quality modes.
304 // If it's not, we want to know because it means our strategy is not optimal.
305 SkASSERT(1 == dinfo->rec_outbuf_height);
msarette16b04a2015-04-15 07:32:19 -0700306
msarett70e418b2016-02-12 12:35:48 -0800307 J_COLOR_SPACE colorSpace = dinfo->out_color_space;
308 if (JCS_CMYK == colorSpace || JCS_RGB == colorSpace) {
scroggoef27d892015-10-23 09:29:22 -0700309 this->initializeSwizzler(dstInfo, options);
310 }
311
msarett1c8a5872015-07-07 08:50:01 -0700312 // Perform the decode a single row at a time
msarett97fdea62015-04-29 08:17:15 -0700313 uint32_t dstHeight = dstInfo.height();
scroggoef27d892015-10-23 09:29:22 -0700314
315 JSAMPLE* dstRow;
316 if (fSwizzler) {
317 // write data to storage row, then sample using swizzler
318 dstRow = fSrcRow;
319 } else {
320 // write data directly to dst
321 dstRow = (JSAMPLE*) dst;
322 }
323
msarett1c8a5872015-07-07 08:50:01 -0700324 for (uint32_t y = 0; y < dstHeight; y++) {
msarette16b04a2015-04-15 07:32:19 -0700325 // Read rows of the image
msarette6dd0042015-10-09 11:07:34 -0700326 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1);
mtkleine721a8e2016-02-06 19:12:23 -0800327 sk_msan_mark_initialized(dstRow, dstRow + dstRowBytes, "skbug.com/4550");
msarette16b04a2015-04-15 07:32:19 -0700328
329 // If we cannot read enough rows, assume the input is incomplete
msarette6dd0042015-10-09 11:07:34 -0700330 if (lines != 1) {
331 *rowsDecoded = y;
msarette16b04a2015-04-15 07:32:19 -0700332
msarette16b04a2015-04-15 07:32:19 -0700333 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
334 }
msarett1c8a5872015-07-07 08:50:01 -0700335
scroggoef27d892015-10-23 09:29:22 -0700336 if (fSwizzler) {
337 // use swizzler to sample row
338 fSwizzler->swizzle(dst, dstRow);
339 dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
340 } else {
341 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
msarett1c8a5872015-07-07 08:50:01 -0700342 }
msarette16b04a2015-04-15 07:32:19 -0700343 }
msarette16b04a2015-04-15 07:32:19 -0700344
345 return kSuccess;
346}
msarett97fdea62015-04-29 08:17:15 -0700347
msarettfdb47572015-10-13 12:50:14 -0700348void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
msarettf724b992015-10-15 06:41:06 -0700349 SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown;
scroggoef27d892015-10-23 09:29:22 -0700350 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
351 srcConfig = SkSwizzler::kCMYK;
352 } else {
msarettbda86092016-01-19 10:40:12 -0800353 // If the out_color_space is not CMYK, the only reason we would need a swizzler is
354 // for sampling and/or subsetting.
scroggoef27d892015-10-23 09:29:22 -0700355 switch (dstInfo.colorType()) {
356 case kGray_8_SkColorType:
msarettbda86092016-01-19 10:40:12 -0800357 srcConfig = SkSwizzler::kNoOp8;
scroggoef27d892015-10-23 09:29:22 -0700358 break;
msarettbda86092016-01-19 10:40:12 -0800359 case kN32_SkColorType:
360 srcConfig = SkSwizzler::kNoOp32;
scroggoef27d892015-10-23 09:29:22 -0700361 break;
362 case kRGB_565_SkColorType:
msarettbda86092016-01-19 10:40:12 -0800363 srcConfig = SkSwizzler::kNoOp16;
scroggoef27d892015-10-23 09:29:22 -0700364 break;
365 default:
366 // This function should only be called if the colorType is supported by jpeg
scroggoef27d892015-10-23 09:29:22 -0700367 SkASSERT(false);
scroggoef27d892015-10-23 09:29:22 -0700368 }
emmaleer8f4ba762015-08-14 07:44:46 -0700369 }
370
msarett70e418b2016-02-12 12:35:48 -0800371 if (JCS_RGB == fDecoderMgr->dinfo()->out_color_space) {
372 srcConfig = SkSwizzler::kRGB;
373 }
374
msarett91c22b22016-02-22 12:27:46 -0800375 Options swizzlerOptions = options;
376 if (options.fSubset) {
377 // Use fSwizzlerSubset if this is a subset decode. This is necessary in the case
378 // where libjpeg-turbo provides a subset and then we need to subset it further.
379 // Also, verify that fSwizzlerSubset is initialized and valid.
380 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
381 fSwizzlerSubset.width() == options.fSubset->width());
382 swizzlerOptions.fSubset = &fSwizzlerSubset;
383 }
384 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, swizzlerOptions));
msarettb30d6982016-02-15 10:18:45 -0800385 SkASSERT(fSwizzler);
scroggoe7fc14b2015-10-02 13:14:46 -0700386 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
scroggo565901d2015-12-10 10:44:13 -0800387 fSrcRow = fStorage.get();
msarettfdb47572015-10-13 12:50:14 -0700388}
389
390SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
391 if (!createIfNecessary || fSwizzler) {
scroggo565901d2015-12-10 10:44:13 -0800392 SkASSERT(!fSwizzler || (fSrcRow && fStorage.get() == fSrcRow));
msarettfdb47572015-10-13 12:50:14 -0700393 return fSwizzler;
394 }
395
396 this->initializeSwizzler(this->dstInfo(), this->options());
scroggoe7fc14b2015-10-02 13:14:46 -0700397 return fSwizzler;
scroggo46c57472015-09-30 08:57:13 -0700398}
scroggo1c005e42015-08-04 09:24:45 -0700399
scroggo46c57472015-09-30 08:57:13 -0700400SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
401 const Options& options, SkPMColor ctable[], int* ctableCount) {
scroggo46c57472015-09-30 08:57:13 -0700402 // Set the jump location for libjpeg errors
403 if (setjmp(fDecoderMgr->getJmpBuf())) {
404 SkCodecPrintf("setjmp: Error from libjpeg\n");
405 return kInvalidInput;
406 }
407
408 // Check if we can decode to the requested destination and set the output color space
409 if (!this->setOutputColorSpace(dstInfo)) {
410 return kInvalidConversion;
411 }
412
scroggoe7fc14b2015-10-02 13:14:46 -0700413 // Remove objects used for sampling.
414 fSwizzler.reset(nullptr);
415 fSrcRow = nullptr;
416 fStorage.free();
scroggo46c57472015-09-30 08:57:13 -0700417
418 // Now, given valid output dimensions, we can start the decompress
419 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
420 SkCodecPrintf("start decompress failed\n");
421 return kInvalidInput;
422 }
423
msarett91c22b22016-02-22 12:27:46 -0800424 if (options.fSubset) {
425 fSwizzlerSubset = *options.fSubset;
426 }
427
428#ifdef TURBO_HAS_CROP
429 if (options.fSubset) {
430 uint32_t startX = options.fSubset->x();
431 uint32_t width = options.fSubset->width();
432
433 // libjpeg-turbo may need to align startX to a multiple of the IDCT
434 // block size. If this is the case, it will decrease the value of
435 // startX to the appropriate alignment and also increase the value
436 // of width so that the right edge of the requested subset remains
437 // the same.
438 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width);
439
440 SkASSERT(startX <= (uint32_t) options.fSubset->x());
441 SkASSERT(width >= (uint32_t) options.fSubset->width());
442 SkASSERT(startX + width >= (uint32_t) options.fSubset->right());
443
444 // Instruct the swizzler (if it is necessary) to further subset the
445 // output provided by libjpeg-turbo.
446 //
447 // We set this here (rather than in the if statement below), so that
448 // if (1) we don't need a swizzler for the subset, and (2) we need a
449 // swizzler for CMYK, the swizzler will still use the proper subset
450 // dimensions.
451 //
452 // Note that the swizzler will ignore the y and height parameters of
453 // the subset. Since the scanline decoder (and the swizzler) handle
454 // one row at a time, only the subsetting in the x-dimension matters.
455 fSwizzlerSubset.setXYWH(options.fSubset->x() - startX, 0,
456 options.fSubset->width(), options.fSubset->height());
457
458 // We will need a swizzler if libjpeg-turbo cannot provide the exact
459 // subset that we request.
460 if (startX != (uint32_t) options.fSubset->x() ||
461 width != (uint32_t) options.fSubset->width()) {
462 this->initializeSwizzler(dstInfo, options);
463 }
464 }
465
466 // Make sure we have a swizzler if we are converting from CMYK.
467 if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
468 this->initializeSwizzler(dstInfo, options);
469 }
470#else
scroggoef27d892015-10-23 09:29:22 -0700471 // We will need a swizzler if we are performing a subset decode or
472 // converting from CMYK.
msarett70e418b2016-02-12 12:35:48 -0800473 J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->out_color_space;
474 if (options.fSubset || JCS_CMYK == colorSpace || JCS_RGB == colorSpace) {
msarettfdb47572015-10-13 12:50:14 -0700475 this->initializeSwizzler(dstInfo, options);
476 }
msarett91c22b22016-02-22 12:27:46 -0800477#endif
msarettfdb47572015-10-13 12:50:14 -0700478
scroggo46c57472015-09-30 08:57:13 -0700479 return kSuccess;
480}
481
mtkleine721a8e2016-02-06 19:12:23 -0800482int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
scroggo46c57472015-09-30 08:57:13 -0700483 // Set the jump location for libjpeg errors
484 if (setjmp(fDecoderMgr->getJmpBuf())) {
485 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
486 }
487 // Read rows one at a time
488 JSAMPLE* dstRow;
mtkleine721a8e2016-02-06 19:12:23 -0800489 size_t srcRowBytes = get_row_bytes(fDecoderMgr->dinfo());
scroggo46c57472015-09-30 08:57:13 -0700490 if (fSwizzler) {
msarettfdb47572015-10-13 12:50:14 -0700491 // write data to storage row, then sample using swizzler
scroggo46c57472015-09-30 08:57:13 -0700492 dstRow = fSrcRow;
493 } else {
494 // write data directly to dst
mtkleine721a8e2016-02-06 19:12:23 -0800495 SkASSERT(count == 1 || dstRowBytes >= srcRowBytes);
scroggo46c57472015-09-30 08:57:13 -0700496 dstRow = (JSAMPLE*) dst;
497 }
498
499 for (int y = 0; y < count; y++) {
500 // Read row of the image
501 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow, 1);
mtkleine721a8e2016-02-06 19:12:23 -0800502 sk_msan_mark_initialized(dstRow, dstRow + srcRowBytes, "skbug.com/4550");
scroggo46c57472015-09-30 08:57:13 -0700503 if (rowsDecoded != 1) {
scroggo46c57472015-09-30 08:57:13 -0700504 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
msarette6dd0042015-10-09 11:07:34 -0700505 return y;
scroggo1c005e42015-08-04 09:24:45 -0700506 }
507
scroggoef27d892015-10-23 09:29:22 -0700508 if (fSwizzler) {
scroggo46c57472015-09-30 08:57:13 -0700509 // use swizzler to sample row
510 fSwizzler->swizzle(dst, dstRow);
mtkleine721a8e2016-02-06 19:12:23 -0800511 dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
emmaleer8f4ba762015-08-14 07:44:46 -0700512 } else {
mtkleine721a8e2016-02-06 19:12:23 -0800513 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
scroggo1c005e42015-08-04 09:24:45 -0700514 }
scroggo1c005e42015-08-04 09:24:45 -0700515 }
msarette6dd0042015-10-09 11:07:34 -0700516 return count;
scroggo46c57472015-09-30 08:57:13 -0700517}
msarett97fdea62015-04-29 08:17:15 -0700518
msarette6dd0042015-10-09 11:07:34 -0700519bool SkJpegCodec::onSkipScanlines(int count) {
scroggo46c57472015-09-30 08:57:13 -0700520 // Set the jump location for libjpeg errors
521 if (setjmp(fDecoderMgr->getJmpBuf())) {
msarette6dd0042015-10-09 11:07:34 -0700522 return fDecoderMgr->returnFalse("setjmp");
msarett97fdea62015-04-29 08:17:15 -0700523 }
524
msarettd5951b12016-02-10 13:49:36 -0800525#ifdef TURBO_HAS_SKIP
msarettf724b992015-10-15 06:41:06 -0700526 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
msarettd5951b12016-02-10 13:49:36 -0800527#else
528 if (!fSrcRow) {
529 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
530 fSrcRow = fStorage.get();
531 }
532
533 for (int y = 0; y < count; y++) {
534 if (1 != jpeg_read_scanlines(fDecoderMgr->dinfo(), &fSrcRow, 1)) {
535 return false;
536 }
537 }
538 return true;
539#endif
msarett97fdea62015-04-29 08:17:15 -0700540}
msarettb714fb02016-01-22 14:46:42 -0800541
542static bool is_yuv_supported(jpeg_decompress_struct* dinfo) {
543 // Scaling is not supported in raw data mode.
544 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
545
546 // I can't imagine that this would ever change, but we do depend on it.
547 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8.");
548
549 if (JCS_YCbCr != dinfo->jpeg_color_space) {
550 return false;
551 }
552
553 SkASSERT(3 == dinfo->num_components);
554 SkASSERT(dinfo->comp_info);
555
556 // It is possible to perform a YUV decode for any combination of
557 // horizontal and vertical sampling that is supported by
558 // libjpeg/libjpeg-turbo. However, we will start by supporting only the
559 // common cases (where U and V have samp_factors of one).
560 //
561 // The definition of samp_factor is kind of the opposite of what SkCodec
562 // thinks of as a sampling factor. samp_factor is essentially a
563 // multiplier, and the larger the samp_factor is, the more samples that
564 // there will be. Ex:
565 // U_plane_width = image_width * (U_h_samp_factor / max_h_samp_factor)
566 //
567 // Supporting cases where the samp_factors for U or V were larger than
568 // that of Y would be an extremely difficult change, given that clients
569 // allocate memory as if the size of the Y plane is always the size of the
570 // image. However, this case is very, very rare.
msarett7c87cf42016-03-04 06:23:20 -0800571 if ((1 != dinfo->comp_info[1].h_samp_factor) ||
572 (1 != dinfo->comp_info[1].v_samp_factor) ||
573 (1 != dinfo->comp_info[2].h_samp_factor) ||
574 (1 != dinfo->comp_info[2].v_samp_factor))
575 {
msarettb714fb02016-01-22 14:46:42 -0800576 return false;
577 }
578
579 // Support all common cases of Y samp_factors.
580 // TODO (msarett): As mentioned above, it would be possible to support
581 // more combinations of samp_factors. The issues are:
582 // (1) Are there actually any images that are not covered
583 // by these cases?
584 // (2) How much complexity would be added to the
585 // implementation in order to support these rare
586 // cases?
587 int hSampY = dinfo->comp_info[0].h_samp_factor;
588 int vSampY = dinfo->comp_info[0].v_samp_factor;
589 return (1 == hSampY && 1 == vSampY) ||
590 (2 == hSampY && 1 == vSampY) ||
591 (2 == hSampY && 2 == vSampY) ||
592 (1 == hSampY && 2 == vSampY) ||
593 (4 == hSampY && 1 == vSampY) ||
594 (4 == hSampY && 2 == vSampY);
595}
596
597bool SkJpegCodec::onQueryYUV8(YUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
598 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
599 if (!is_yuv_supported(dinfo)) {
600 return false;
601 }
602
603 sizeInfo->fYSize.set(dinfo->comp_info[0].downsampled_width,
604 dinfo->comp_info[0].downsampled_height);
605 sizeInfo->fUSize.set(dinfo->comp_info[1].downsampled_width,
606 dinfo->comp_info[1].downsampled_height);
607 sizeInfo->fVSize.set(dinfo->comp_info[2].downsampled_width,
608 dinfo->comp_info[2].downsampled_height);
609 sizeInfo->fYWidthBytes = dinfo->comp_info[0].width_in_blocks * DCTSIZE;
610 sizeInfo->fUWidthBytes = dinfo->comp_info[1].width_in_blocks * DCTSIZE;
611 sizeInfo->fVWidthBytes = dinfo->comp_info[2].width_in_blocks * DCTSIZE;
612
613 if (colorSpace) {
614 *colorSpace = kJPEG_SkYUVColorSpace;
615 }
616
617 return true;
618}
619
620SkCodec::Result SkJpegCodec::onGetYUV8Planes(const YUVSizeInfo& sizeInfo, void* pixels[3]) {
621 YUVSizeInfo defaultInfo;
622
623 // This will check is_yuv_supported(), so we don't need to here.
624 bool supportsYUV = this->onQueryYUV8(&defaultInfo, nullptr);
625 if (!supportsYUV || sizeInfo.fYSize != defaultInfo.fYSize ||
626 sizeInfo.fUSize != defaultInfo.fUSize ||
627 sizeInfo.fVSize != defaultInfo.fVSize ||
628 sizeInfo.fYWidthBytes < defaultInfo.fYWidthBytes ||
629 sizeInfo.fUWidthBytes < defaultInfo.fUWidthBytes ||
630 sizeInfo.fVWidthBytes < defaultInfo.fVWidthBytes) {
631 return fDecoderMgr->returnFailure("onGetYUV8Planes", kInvalidInput);
632 }
633
634 // Set the jump location for libjpeg errors
635 if (setjmp(fDecoderMgr->getJmpBuf())) {
636 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
637 }
638
639 // Get a pointer to the decompress info since we will use it quite frequently
640 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
641
642 dinfo->raw_data_out = TRUE;
643 if (!jpeg_start_decompress(dinfo)) {
644 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
645 }
646
647 // A previous implementation claims that the return value of is_yuv_supported()
648 // may change after calling jpeg_start_decompress(). It looks to me like this
649 // was caused by a bug in the old code, but we'll be safe and check here.
650 SkASSERT(is_yuv_supported(dinfo));
651
652 // Currently, we require that the Y plane dimensions match the image dimensions
653 // and that the U and V planes are the same dimensions.
654 SkASSERT(sizeInfo.fUSize == sizeInfo.fVSize);
655 SkASSERT((uint32_t) sizeInfo.fYSize.width() == dinfo->output_width &&
656 (uint32_t) sizeInfo.fYSize.height() == dinfo->output_height);
657
658 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
659 // a 2-D array of pixels for each of the components (Y, U, V) in the image.
660 // Cheat Sheet:
661 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE***
662 JSAMPARRAY yuv[3];
663
664 // Set aside enough space for pointers to rows of Y, U, and V.
665 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
666 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE)
667 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE)
668 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE)
669
670 // Initialize rowptrs.
671 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
672 for (int i = 0; i < numYRowsPerBlock; i++) {
673 rowptrs[i] = SkTAddOffset<JSAMPLE>(pixels[0], i * sizeInfo.fYWidthBytes);
674 }
675 for (int i = 0; i < DCTSIZE; i++) {
676 rowptrs[i + 2 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[1], i * sizeInfo.fUWidthBytes);
677 rowptrs[i + 3 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[2], i * sizeInfo.fVWidthBytes);
678 }
679
680 // After each loop iteration, we will increment pointers to Y, U, and V.
681 size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fYWidthBytes;
682 size_t blockIncrementU = DCTSIZE * sizeInfo.fUWidthBytes;
683 size_t blockIncrementV = DCTSIZE * sizeInfo.fVWidthBytes;
684
685 uint32_t numRowsPerBlock = numYRowsPerBlock;
686
687 // We intentionally round down here, as this first loop will only handle
688 // full block rows. As a special case at the end, we will handle any
689 // remaining rows that do not make up a full block.
690 const int numIters = dinfo->output_height / numRowsPerBlock;
691 for (int i = 0; i < numIters; i++) {
692 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
693 if (linesRead < numRowsPerBlock) {
694 // FIXME: Handle incomplete YUV decodes without signalling an error.
695 return kInvalidInput;
696 }
697
698 // Update rowptrs.
699 for (int i = 0; i < numYRowsPerBlock; i++) {
700 rowptrs[i] += blockIncrementY;
701 }
702 for (int i = 0; i < DCTSIZE; i++) {
703 rowptrs[i + 2 * DCTSIZE] += blockIncrementU;
704 rowptrs[i + 3 * DCTSIZE] += blockIncrementV;
705 }
706 }
707
708 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
709 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
710 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
711 if (remainingRows > 0) {
712 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill
713 // this requirement using a dummy row buffer.
714 // FIXME: Should SkCodec have an extra memory buffer that can be shared among
715 // all of the implementations that use temporary/garbage memory?
716 SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fYWidthBytes);
717 for (int i = remainingRows; i < numYRowsPerBlock; i++) {
718 rowptrs[i] = dummyRow.get();
719 }
720 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
721 for (int i = remainingUVRows; i < DCTSIZE; i++) {
722 rowptrs[i + 2 * DCTSIZE] = dummyRow.get();
723 rowptrs[i + 3 * DCTSIZE] = dummyRow.get();
724 }
725
726 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
727 if (linesRead < remainingRows) {
728 // FIXME: Handle incomplete YUV decodes without signalling an error.
729 return kInvalidInput;
730 }
731 }
732
733 return kSuccess;
734}