blob: 0c4f99bb0ec105c36b9c2ba657a6ccc9ad65871d [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)
Matt Sarettea3121e2016-07-21 09:19:47 -040083 , fSrcRow(nullptr)
msarett91c22b22016-02-22 12:27:46 -080084 , fSwizzlerSubset(SkIRect::MakeEmpty())
msarette16b04a2015-04-15 07:32:19 -070085{}
86
87/*
emmaleer8f4ba762015-08-14 07:44:46 -070088 * Return the row bytes of a particular image type and width
89 */
msarett23e78d32016-02-06 15:58:50 -080090static size_t get_row_bytes(const j_decompress_ptr dinfo) {
msarett70e418b2016-02-12 12:35:48 -080091#ifdef TURBO_HAS_565
92 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
93 dinfo->out_color_components;
94#else
95 const size_t colorBytes = dinfo->out_color_components;
96#endif
emmaleer8f4ba762015-08-14 07:44:46 -070097 return dinfo->output_width * colorBytes;
98
99}
scroggoe7fc14b2015-10-02 13:14:46 -0700100
101/*
102 * Calculate output dimensions based on the provided factors.
103 *
104 * Not to be used on the actual jpeg_decompress_struct used for decoding, since it will
105 * incorrectly modify num_components.
106 */
107void calc_output_dimensions(jpeg_decompress_struct* dinfo, unsigned int num, unsigned int denom) {
108 dinfo->num_components = 0;
109 dinfo->scale_num = num;
110 dinfo->scale_denom = denom;
111 jpeg_calc_output_dimensions(dinfo);
112}
113
emmaleer8f4ba762015-08-14 07:44:46 -0700114/*
msarette16b04a2015-04-15 07:32:19 -0700115 * Return a valid set of output dimensions for this decoder, given an input scale
116 */
117SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
msarett1c8a5872015-07-07 08:50:01 -0700118 // 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
119 // support these as well
scroggoe7fc14b2015-10-02 13:14:46 -0700120 unsigned int num;
121 unsigned int denom = 8;
msarettfdb47572015-10-13 12:50:14 -0700122 if (desiredScale >= 0.9375) {
msarett1c8a5872015-07-07 08:50:01 -0700123 num = 8;
msarettfdb47572015-10-13 12:50:14 -0700124 } else if (desiredScale >= 0.8125) {
msarett1c8a5872015-07-07 08:50:01 -0700125 num = 7;
msarettfdb47572015-10-13 12:50:14 -0700126 } else if (desiredScale >= 0.6875f) {
msarett1c8a5872015-07-07 08:50:01 -0700127 num = 6;
msarettfdb47572015-10-13 12:50:14 -0700128 } else if (desiredScale >= 0.5625f) {
msarett1c8a5872015-07-07 08:50:01 -0700129 num = 5;
msarettfdb47572015-10-13 12:50:14 -0700130 } else if (desiredScale >= 0.4375f) {
msarett1c8a5872015-07-07 08:50:01 -0700131 num = 4;
msarettfdb47572015-10-13 12:50:14 -0700132 } else if (desiredScale >= 0.3125f) {
msarett1c8a5872015-07-07 08:50:01 -0700133 num = 3;
msarettfdb47572015-10-13 12:50:14 -0700134 } else if (desiredScale >= 0.1875f) {
msarett1c8a5872015-07-07 08:50:01 -0700135 num = 2;
msarette16b04a2015-04-15 07:32:19 -0700136 } else {
msarett1c8a5872015-07-07 08:50:01 -0700137 num = 1;
msarette16b04a2015-04-15 07:32:19 -0700138 }
139
140 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
141 jpeg_decompress_struct dinfo;
mtkleinf7aaadb2015-04-16 06:09:27 -0700142 sk_bzero(&dinfo, sizeof(dinfo));
msarette16b04a2015-04-15 07:32:19 -0700143 dinfo.image_width = this->getInfo().width();
144 dinfo.image_height = this->getInfo().height();
msarettfbccb592015-09-01 06:43:41 -0700145 dinfo.global_state = fReadyState;
scroggoe7fc14b2015-10-02 13:14:46 -0700146 calc_output_dimensions(&dinfo, num, denom);
msarette16b04a2015-04-15 07:32:19 -0700147
148 // Return the calculated output dimensions for the given scale
149 return SkISize::Make(dinfo.output_width, dinfo.output_height);
150}
151
scroggob427db12015-08-12 07:24:13 -0700152bool SkJpegCodec::onRewind() {
halcanary96fcdcc2015-08-27 07:41:13 -0700153 JpegDecoderMgr* decoderMgr = nullptr;
154 if (!ReadHeader(this->stream(), nullptr, &decoderMgr)) {
scroggob427db12015-08-12 07:24:13 -0700155 return fDecoderMgr->returnFalse("could not rewind");
msarett97fdea62015-04-29 08:17:15 -0700156 }
halcanary96fcdcc2015-08-27 07:41:13 -0700157 SkASSERT(nullptr != decoderMgr);
scroggob427db12015-08-12 07:24:13 -0700158 fDecoderMgr.reset(decoderMgr);
Matt Sarettea3121e2016-07-21 09:19:47 -0400159
160 fSwizzler.reset(nullptr);
161 fSrcRow = nullptr;
162 fStorage.free();
163
scroggob427db12015-08-12 07:24:13 -0700164 return true;
msarett97fdea62015-04-29 08:17:15 -0700165}
166
167/*
msarett1c8a5872015-07-07 08:50:01 -0700168 * Checks if the conversion between the input image and the requested output
169 * image has been implemented
170 * Sets the output color space
171 */
172bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
173 const SkImageInfo& src = this->getInfo();
174
175 // Ensure that the profile type is unchanged
176 if (dst.profileType() != src.profileType()) {
177 return false;
178 }
179
scroggoc5560be2016-02-03 09:42:42 -0800180 if (kUnknown_SkAlphaType == dst.alphaType()) {
msarett1c8a5872015-07-07 08:50:01 -0700181 return false;
182 }
183
scroggoc5560be2016-02-03 09:42:42 -0800184 if (kOpaque_SkAlphaType != dst.alphaType()) {
185 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
186 "- it is being decoded as non-opaque, which will draw slower\n");
187 }
188
msarett1c8a5872015-07-07 08:50:01 -0700189 // Check if we will decode to CMYK because a conversion to RGBA is not supported
190 J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space;
191 bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace;
192
193 // Check for valid color types and set the output color space
194 switch (dst.colorType()) {
195 case kN32_SkColorType:
196 if (isCMYK) {
197 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
198 } else {
msarett70e418b2016-02-12 12:35:48 -0800199#ifdef LIBJPEG_TURBO_VERSION
200 // Check the byte ordering of the RGBA color space for the
201 // current platform
202 #ifdef SK_PMCOLOR_IS_RGBA
203 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
204 #else
205 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
206 #endif
benjaminwagneraada3e82015-10-27 09:14:29 -0700207#else
msarett70e418b2016-02-12 12:35:48 -0800208 fDecoderMgr->dinfo()->out_color_space = JCS_RGB;
msarett1c8a5872015-07-07 08:50:01 -0700209#endif
210 }
211 return true;
212 case kRGB_565_SkColorType:
213 if (isCMYK) {
scroggoef27d892015-10-23 09:29:22 -0700214 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
msarett1c8a5872015-07-07 08:50:01 -0700215 } else {
msarett70e418b2016-02-12 12:35:48 -0800216#ifdef TURBO_HAS_565
msarett8ff6ca62015-09-18 12:06:04 -0700217 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
msarett1c8a5872015-07-07 08:50:01 -0700218 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
msarett70e418b2016-02-12 12:35:48 -0800219#else
220 fDecoderMgr->dinfo()->out_color_space = JCS_RGB;
221#endif
msarett1c8a5872015-07-07 08:50:01 -0700222 }
223 return true;
224 case kGray_8_SkColorType:
225 if (isCMYK) {
226 return false;
227 } else {
228 // We will enable decodes to gray even if the image is color because this is
229 // much faster than decoding to color and then converting
230 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
231 }
232 return true;
233 default:
234 return false;
235 }
236}
237
238/*
mtkleine721a8e2016-02-06 19:12:23 -0800239 * Checks if we can natively scale to the requested dimensions and natively scales the
emmaleer8f4ba762015-08-14 07:44:46 -0700240 * dimensions if possible
msarett97fdea62015-04-29 08:17:15 -0700241 */
scroggoe7fc14b2015-10-02 13:14:46 -0700242bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
243 if (setjmp(fDecoderMgr->getJmpBuf())) {
244 return fDecoderMgr->returnFalse("onDimensionsSupported/setjmp");
245 }
246
247 const unsigned int dstWidth = size.width();
248 const unsigned int dstHeight = size.height();
249
250 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
251 // FIXME: Why is this necessary?
252 jpeg_decompress_struct dinfo;
253 sk_bzero(&dinfo, sizeof(dinfo));
254 dinfo.image_width = this->getInfo().width();
255 dinfo.image_height = this->getInfo().height();
256 dinfo.global_state = fReadyState;
257
msarett1c8a5872015-07-07 08:50:01 -0700258 // 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 -0700259 unsigned int num = 8;
260 const unsigned int denom = 8;
261 calc_output_dimensions(&dinfo, num, denom);
262 while (dinfo.output_width != dstWidth || dinfo.output_height != dstHeight) {
msarett97fdea62015-04-29 08:17:15 -0700263
264 // Return a failure if we have tried all of the possible scales
scroggoe7fc14b2015-10-02 13:14:46 -0700265 if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
emmaleer8f4ba762015-08-14 07:44:46 -0700266 return false;
msarett97fdea62015-04-29 08:17:15 -0700267 }
268
269 // Try the next scale
scroggoe7fc14b2015-10-02 13:14:46 -0700270 num -= 1;
271 calc_output_dimensions(&dinfo, num, denom);
msarett97fdea62015-04-29 08:17:15 -0700272 }
scroggoe7fc14b2015-10-02 13:14:46 -0700273
274 fDecoderMgr->dinfo()->scale_num = num;
275 fDecoderMgr->dinfo()->scale_denom = denom;
msarett97fdea62015-04-29 08:17:15 -0700276 return true;
277}
278
279/*
msarette16b04a2015-04-15 07:32:19 -0700280 * Performs the jpeg decode
281 */
282SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
283 void* dst, size_t dstRowBytes,
msarette6dd0042015-10-09 11:07:34 -0700284 const Options& options, SkPMColor*, int*,
285 int* rowsDecoded) {
scroggob636b452015-07-22 07:16:20 -0700286 if (options.fSubset) {
287 // Subsets are not supported.
288 return kUnimplemented;
289 }
290
msarette16b04a2015-04-15 07:32:19 -0700291 // Get a pointer to the decompress info since we will use it quite frequently
292 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
293
294 // Set the jump location for libjpeg errors
295 if (setjmp(fDecoderMgr->getJmpBuf())) {
296 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
297 }
298
msarett1c8a5872015-07-07 08:50:01 -0700299 // Check if we can decode to the requested destination and set the output color space
300 if (!this->setOutputColorSpace(dstInfo)) {
msarette16b04a2015-04-15 07:32:19 -0700301 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion);
302 }
msarette16b04a2015-04-15 07:32:19 -0700303
Pritesh Kumar662baab2016-05-27 16:47:36 -0700304#ifdef DCT_IFAST_SUPPORTED
305 dinfo->dct_method = JDCT_IFAST;
306#else
307 dinfo->dct_method = JDCT_ISLOW;
308#endif
309// Now, given valid output dimensions, we can start the decompress
msarettfbccb592015-09-01 06:43:41 -0700310 if (!jpeg_start_decompress(dinfo)) {
msarette16b04a2015-04-15 07:32:19 -0700311 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
312 }
313
msarett1c8a5872015-07-07 08:50:01 -0700314 // The recommended output buffer height should always be 1 in high quality modes.
315 // If it's not, we want to know because it means our strategy is not optimal.
316 SkASSERT(1 == dinfo->rec_outbuf_height);
msarette16b04a2015-04-15 07:32:19 -0700317
msarett70e418b2016-02-12 12:35:48 -0800318 J_COLOR_SPACE colorSpace = dinfo->out_color_space;
319 if (JCS_CMYK == colorSpace || JCS_RGB == colorSpace) {
scroggoef27d892015-10-23 09:29:22 -0700320 this->initializeSwizzler(dstInfo, options);
321 }
322
msarett1c8a5872015-07-07 08:50:01 -0700323 // Perform the decode a single row at a time
msarett97fdea62015-04-29 08:17:15 -0700324 uint32_t dstHeight = dstInfo.height();
scroggoef27d892015-10-23 09:29:22 -0700325
326 JSAMPLE* dstRow;
327 if (fSwizzler) {
328 // write data to storage row, then sample using swizzler
329 dstRow = fSrcRow;
330 } else {
331 // write data directly to dst
332 dstRow = (JSAMPLE*) dst;
333 }
334
msarett1c8a5872015-07-07 08:50:01 -0700335 for (uint32_t y = 0; y < dstHeight; y++) {
msarette16b04a2015-04-15 07:32:19 -0700336 // Read rows of the image
msarette6dd0042015-10-09 11:07:34 -0700337 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1);
mtkleine721a8e2016-02-06 19:12:23 -0800338 sk_msan_mark_initialized(dstRow, dstRow + dstRowBytes, "skbug.com/4550");
msarette16b04a2015-04-15 07:32:19 -0700339
340 // If we cannot read enough rows, assume the input is incomplete
msarette6dd0042015-10-09 11:07:34 -0700341 if (lines != 1) {
342 *rowsDecoded = y;
msarette16b04a2015-04-15 07:32:19 -0700343
msarette16b04a2015-04-15 07:32:19 -0700344 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
345 }
msarett1c8a5872015-07-07 08:50:01 -0700346
scroggoef27d892015-10-23 09:29:22 -0700347 if (fSwizzler) {
348 // use swizzler to sample row
349 fSwizzler->swizzle(dst, dstRow);
350 dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
351 } else {
352 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
msarett1c8a5872015-07-07 08:50:01 -0700353 }
msarette16b04a2015-04-15 07:32:19 -0700354 }
msarette16b04a2015-04-15 07:32:19 -0700355
356 return kSuccess;
357}
msarett97fdea62015-04-29 08:17:15 -0700358
msarettfdb47572015-10-13 12:50:14 -0700359void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
msarettf724b992015-10-15 06:41:06 -0700360 SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown;
scroggoef27d892015-10-23 09:29:22 -0700361 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
362 srcConfig = SkSwizzler::kCMYK;
363 } else {
msarettbda86092016-01-19 10:40:12 -0800364 // If the out_color_space is not CMYK, the only reason we would need a swizzler is
365 // for sampling and/or subsetting.
scroggoef27d892015-10-23 09:29:22 -0700366 switch (dstInfo.colorType()) {
367 case kGray_8_SkColorType:
msarettbda86092016-01-19 10:40:12 -0800368 srcConfig = SkSwizzler::kNoOp8;
scroggoef27d892015-10-23 09:29:22 -0700369 break;
msarettbda86092016-01-19 10:40:12 -0800370 case kN32_SkColorType:
371 srcConfig = SkSwizzler::kNoOp32;
scroggoef27d892015-10-23 09:29:22 -0700372 break;
373 case kRGB_565_SkColorType:
msarettbda86092016-01-19 10:40:12 -0800374 srcConfig = SkSwizzler::kNoOp16;
scroggoef27d892015-10-23 09:29:22 -0700375 break;
376 default:
377 // This function should only be called if the colorType is supported by jpeg
scroggoef27d892015-10-23 09:29:22 -0700378 SkASSERT(false);
scroggoef27d892015-10-23 09:29:22 -0700379 }
emmaleer8f4ba762015-08-14 07:44:46 -0700380 }
381
msarett70e418b2016-02-12 12:35:48 -0800382 if (JCS_RGB == fDecoderMgr->dinfo()->out_color_space) {
383 srcConfig = SkSwizzler::kRGB;
384 }
385
msarett91c22b22016-02-22 12:27:46 -0800386 Options swizzlerOptions = options;
387 if (options.fSubset) {
388 // Use fSwizzlerSubset if this is a subset decode. This is necessary in the case
389 // where libjpeg-turbo provides a subset and then we need to subset it further.
390 // Also, verify that fSwizzlerSubset is initialized and valid.
391 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
392 fSwizzlerSubset.width() == options.fSubset->width());
393 swizzlerOptions.fSubset = &fSwizzlerSubset;
394 }
395 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, swizzlerOptions));
msarettb30d6982016-02-15 10:18:45 -0800396 SkASSERT(fSwizzler);
scroggoe7fc14b2015-10-02 13:14:46 -0700397 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
scroggo565901d2015-12-10 10:44:13 -0800398 fSrcRow = fStorage.get();
msarettfdb47572015-10-13 12:50:14 -0700399}
400
401SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
402 if (!createIfNecessary || fSwizzler) {
scroggo565901d2015-12-10 10:44:13 -0800403 SkASSERT(!fSwizzler || (fSrcRow && fStorage.get() == fSrcRow));
msarettfdb47572015-10-13 12:50:14 -0700404 return fSwizzler;
405 }
406
407 this->initializeSwizzler(this->dstInfo(), this->options());
scroggoe7fc14b2015-10-02 13:14:46 -0700408 return fSwizzler;
scroggo46c57472015-09-30 08:57:13 -0700409}
scroggo1c005e42015-08-04 09:24:45 -0700410
scroggo46c57472015-09-30 08:57:13 -0700411SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
412 const Options& options, SkPMColor ctable[], int* ctableCount) {
scroggo46c57472015-09-30 08:57:13 -0700413 // Set the jump location for libjpeg errors
414 if (setjmp(fDecoderMgr->getJmpBuf())) {
415 SkCodecPrintf("setjmp: Error from libjpeg\n");
416 return kInvalidInput;
417 }
418
419 // Check if we can decode to the requested destination and set the output color space
420 if (!this->setOutputColorSpace(dstInfo)) {
421 return kInvalidConversion;
422 }
423
Pritesh Kumar662baab2016-05-27 16:47:36 -0700424#ifdef DCT_IFAST_SUPPORTED
425 (fDecoderMgr->dinfo())->dct_method = JDCT_IFAST;
426#else
427 (fDecoderMgr->dinfo())->dct_method = JDCT_ISLOW;
428#endif
Matt Sarettea3121e2016-07-21 09:19:47 -0400429 // Now, given valid output dimensions, we can start the decompress
scroggo46c57472015-09-30 08:57:13 -0700430 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
431 SkCodecPrintf("start decompress failed\n");
432 return kInvalidInput;
433 }
434
msarett91c22b22016-02-22 12:27:46 -0800435 if (options.fSubset) {
436 fSwizzlerSubset = *options.fSubset;
437 }
438
439#ifdef TURBO_HAS_CROP
440 if (options.fSubset) {
441 uint32_t startX = options.fSubset->x();
442 uint32_t width = options.fSubset->width();
443
444 // libjpeg-turbo may need to align startX to a multiple of the IDCT
445 // block size. If this is the case, it will decrease the value of
446 // startX to the appropriate alignment and also increase the value
447 // of width so that the right edge of the requested subset remains
448 // the same.
449 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width);
450
451 SkASSERT(startX <= (uint32_t) options.fSubset->x());
452 SkASSERT(width >= (uint32_t) options.fSubset->width());
453 SkASSERT(startX + width >= (uint32_t) options.fSubset->right());
454
455 // Instruct the swizzler (if it is necessary) to further subset the
456 // output provided by libjpeg-turbo.
457 //
458 // We set this here (rather than in the if statement below), so that
459 // if (1) we don't need a swizzler for the subset, and (2) we need a
460 // swizzler for CMYK, the swizzler will still use the proper subset
461 // dimensions.
462 //
463 // Note that the swizzler will ignore the y and height parameters of
464 // the subset. Since the scanline decoder (and the swizzler) handle
465 // one row at a time, only the subsetting in the x-dimension matters.
466 fSwizzlerSubset.setXYWH(options.fSubset->x() - startX, 0,
467 options.fSubset->width(), options.fSubset->height());
468
469 // We will need a swizzler if libjpeg-turbo cannot provide the exact
470 // subset that we request.
471 if (startX != (uint32_t) options.fSubset->x() ||
472 width != (uint32_t) options.fSubset->width()) {
473 this->initializeSwizzler(dstInfo, options);
474 }
475 }
476
477 // Make sure we have a swizzler if we are converting from CMYK.
478 if (!fSwizzler && JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
479 this->initializeSwizzler(dstInfo, options);
480 }
481#else
scroggoef27d892015-10-23 09:29:22 -0700482 // We will need a swizzler if we are performing a subset decode or
483 // converting from CMYK.
msarett70e418b2016-02-12 12:35:48 -0800484 J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->out_color_space;
485 if (options.fSubset || JCS_CMYK == colorSpace || JCS_RGB == colorSpace) {
msarettfdb47572015-10-13 12:50:14 -0700486 this->initializeSwizzler(dstInfo, options);
487 }
msarett91c22b22016-02-22 12:27:46 -0800488#endif
msarettfdb47572015-10-13 12:50:14 -0700489
scroggo46c57472015-09-30 08:57:13 -0700490 return kSuccess;
491}
492
mtkleine721a8e2016-02-06 19:12:23 -0800493int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
scroggo46c57472015-09-30 08:57:13 -0700494 // Set the jump location for libjpeg errors
495 if (setjmp(fDecoderMgr->getJmpBuf())) {
496 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
497 }
498 // Read rows one at a time
499 JSAMPLE* dstRow;
mtkleine721a8e2016-02-06 19:12:23 -0800500 size_t srcRowBytes = get_row_bytes(fDecoderMgr->dinfo());
scroggo46c57472015-09-30 08:57:13 -0700501 if (fSwizzler) {
msarettfdb47572015-10-13 12:50:14 -0700502 // write data to storage row, then sample using swizzler
scroggo46c57472015-09-30 08:57:13 -0700503 dstRow = fSrcRow;
504 } else {
505 // write data directly to dst
mtkleine721a8e2016-02-06 19:12:23 -0800506 SkASSERT(count == 1 || dstRowBytes >= srcRowBytes);
scroggo46c57472015-09-30 08:57:13 -0700507 dstRow = (JSAMPLE*) dst;
508 }
509
510 for (int y = 0; y < count; y++) {
511 // Read row of the image
512 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow, 1);
mtkleine721a8e2016-02-06 19:12:23 -0800513 sk_msan_mark_initialized(dstRow, dstRow + srcRowBytes, "skbug.com/4550");
scroggo46c57472015-09-30 08:57:13 -0700514 if (rowsDecoded != 1) {
scroggo46c57472015-09-30 08:57:13 -0700515 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
msarette6dd0042015-10-09 11:07:34 -0700516 return y;
scroggo1c005e42015-08-04 09:24:45 -0700517 }
518
scroggoef27d892015-10-23 09:29:22 -0700519 if (fSwizzler) {
scroggo46c57472015-09-30 08:57:13 -0700520 // use swizzler to sample row
521 fSwizzler->swizzle(dst, dstRow);
mtkleine721a8e2016-02-06 19:12:23 -0800522 dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
emmaleer8f4ba762015-08-14 07:44:46 -0700523 } else {
mtkleine721a8e2016-02-06 19:12:23 -0800524 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
scroggo1c005e42015-08-04 09:24:45 -0700525 }
scroggo1c005e42015-08-04 09:24:45 -0700526 }
msarette6dd0042015-10-09 11:07:34 -0700527 return count;
scroggo46c57472015-09-30 08:57:13 -0700528}
msarett97fdea62015-04-29 08:17:15 -0700529
msarette6dd0042015-10-09 11:07:34 -0700530bool SkJpegCodec::onSkipScanlines(int count) {
scroggo46c57472015-09-30 08:57:13 -0700531 // Set the jump location for libjpeg errors
532 if (setjmp(fDecoderMgr->getJmpBuf())) {
msarette6dd0042015-10-09 11:07:34 -0700533 return fDecoderMgr->returnFalse("setjmp");
msarett97fdea62015-04-29 08:17:15 -0700534 }
535
msarettd5951b12016-02-10 13:49:36 -0800536#ifdef TURBO_HAS_SKIP
msarettf724b992015-10-15 06:41:06 -0700537 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
msarettd5951b12016-02-10 13:49:36 -0800538#else
539 if (!fSrcRow) {
540 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
541 fSrcRow = fStorage.get();
542 }
543
544 for (int y = 0; y < count; y++) {
545 if (1 != jpeg_read_scanlines(fDecoderMgr->dinfo(), &fSrcRow, 1)) {
546 return false;
547 }
548 }
549 return true;
550#endif
msarett97fdea62015-04-29 08:17:15 -0700551}
msarettb714fb02016-01-22 14:46:42 -0800552
553static bool is_yuv_supported(jpeg_decompress_struct* dinfo) {
554 // Scaling is not supported in raw data mode.
555 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
556
557 // I can't imagine that this would ever change, but we do depend on it.
558 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8.");
559
560 if (JCS_YCbCr != dinfo->jpeg_color_space) {
561 return false;
562 }
563
564 SkASSERT(3 == dinfo->num_components);
565 SkASSERT(dinfo->comp_info);
566
567 // It is possible to perform a YUV decode for any combination of
568 // horizontal and vertical sampling that is supported by
569 // libjpeg/libjpeg-turbo. However, we will start by supporting only the
570 // common cases (where U and V have samp_factors of one).
571 //
572 // The definition of samp_factor is kind of the opposite of what SkCodec
573 // thinks of as a sampling factor. samp_factor is essentially a
574 // multiplier, and the larger the samp_factor is, the more samples that
575 // there will be. Ex:
576 // U_plane_width = image_width * (U_h_samp_factor / max_h_samp_factor)
577 //
578 // Supporting cases where the samp_factors for U or V were larger than
579 // that of Y would be an extremely difficult change, given that clients
580 // allocate memory as if the size of the Y plane is always the size of the
581 // image. However, this case is very, very rare.
582 if (!(1 == dinfo->comp_info[1].h_samp_factor) &&
583 (1 == dinfo->comp_info[1].v_samp_factor) &&
584 (1 == dinfo->comp_info[2].h_samp_factor) &&
585 (1 == dinfo->comp_info[2].v_samp_factor)) {
586 return false;
587 }
588
589 // Support all common cases of Y samp_factors.
590 // TODO (msarett): As mentioned above, it would be possible to support
591 // more combinations of samp_factors. The issues are:
592 // (1) Are there actually any images that are not covered
593 // by these cases?
594 // (2) How much complexity would be added to the
595 // implementation in order to support these rare
596 // cases?
597 int hSampY = dinfo->comp_info[0].h_samp_factor;
598 int vSampY = dinfo->comp_info[0].v_samp_factor;
599 return (1 == hSampY && 1 == vSampY) ||
600 (2 == hSampY && 1 == vSampY) ||
601 (2 == hSampY && 2 == vSampY) ||
602 (1 == hSampY && 2 == vSampY) ||
603 (4 == hSampY && 1 == vSampY) ||
604 (4 == hSampY && 2 == vSampY);
605}
606
607bool SkJpegCodec::onQueryYUV8(YUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
608 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
609 if (!is_yuv_supported(dinfo)) {
610 return false;
611 }
612
613 sizeInfo->fYSize.set(dinfo->comp_info[0].downsampled_width,
614 dinfo->comp_info[0].downsampled_height);
615 sizeInfo->fUSize.set(dinfo->comp_info[1].downsampled_width,
616 dinfo->comp_info[1].downsampled_height);
617 sizeInfo->fVSize.set(dinfo->comp_info[2].downsampled_width,
618 dinfo->comp_info[2].downsampled_height);
619 sizeInfo->fYWidthBytes = dinfo->comp_info[0].width_in_blocks * DCTSIZE;
620 sizeInfo->fUWidthBytes = dinfo->comp_info[1].width_in_blocks * DCTSIZE;
621 sizeInfo->fVWidthBytes = dinfo->comp_info[2].width_in_blocks * DCTSIZE;
622
623 if (colorSpace) {
624 *colorSpace = kJPEG_SkYUVColorSpace;
625 }
626
627 return true;
628}
629
630SkCodec::Result SkJpegCodec::onGetYUV8Planes(const YUVSizeInfo& sizeInfo, void* pixels[3]) {
631 YUVSizeInfo defaultInfo;
632
633 // This will check is_yuv_supported(), so we don't need to here.
634 bool supportsYUV = this->onQueryYUV8(&defaultInfo, nullptr);
635 if (!supportsYUV || sizeInfo.fYSize != defaultInfo.fYSize ||
636 sizeInfo.fUSize != defaultInfo.fUSize ||
637 sizeInfo.fVSize != defaultInfo.fVSize ||
638 sizeInfo.fYWidthBytes < defaultInfo.fYWidthBytes ||
639 sizeInfo.fUWidthBytes < defaultInfo.fUWidthBytes ||
640 sizeInfo.fVWidthBytes < defaultInfo.fVWidthBytes) {
641 return fDecoderMgr->returnFailure("onGetYUV8Planes", kInvalidInput);
642 }
643
644 // Set the jump location for libjpeg errors
645 if (setjmp(fDecoderMgr->getJmpBuf())) {
646 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
647 }
648
649 // Get a pointer to the decompress info since we will use it quite frequently
650 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
msarettb714fb02016-01-22 14:46:42 -0800651 dinfo->raw_data_out = TRUE;
652 if (!jpeg_start_decompress(dinfo)) {
653 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
654 }
655
656 // A previous implementation claims that the return value of is_yuv_supported()
657 // may change after calling jpeg_start_decompress(). It looks to me like this
658 // was caused by a bug in the old code, but we'll be safe and check here.
659 SkASSERT(is_yuv_supported(dinfo));
660
661 // Currently, we require that the Y plane dimensions match the image dimensions
662 // and that the U and V planes are the same dimensions.
663 SkASSERT(sizeInfo.fUSize == sizeInfo.fVSize);
664 SkASSERT((uint32_t) sizeInfo.fYSize.width() == dinfo->output_width &&
665 (uint32_t) sizeInfo.fYSize.height() == dinfo->output_height);
666
667 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
668 // a 2-D array of pixels for each of the components (Y, U, V) in the image.
669 // Cheat Sheet:
670 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE***
671 JSAMPARRAY yuv[3];
672
673 // Set aside enough space for pointers to rows of Y, U, and V.
674 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
675 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE)
676 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE)
677 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE)
678
679 // Initialize rowptrs.
680 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
681 for (int i = 0; i < numYRowsPerBlock; i++) {
682 rowptrs[i] = SkTAddOffset<JSAMPLE>(pixels[0], i * sizeInfo.fYWidthBytes);
683 }
684 for (int i = 0; i < DCTSIZE; i++) {
685 rowptrs[i + 2 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[1], i * sizeInfo.fUWidthBytes);
686 rowptrs[i + 3 * DCTSIZE] = SkTAddOffset<JSAMPLE>(pixels[2], i * sizeInfo.fVWidthBytes);
687 }
688
689 // After each loop iteration, we will increment pointers to Y, U, and V.
690 size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fYWidthBytes;
691 size_t blockIncrementU = DCTSIZE * sizeInfo.fUWidthBytes;
692 size_t blockIncrementV = DCTSIZE * sizeInfo.fVWidthBytes;
693
694 uint32_t numRowsPerBlock = numYRowsPerBlock;
695
696 // We intentionally round down here, as this first loop will only handle
697 // full block rows. As a special case at the end, we will handle any
698 // remaining rows that do not make up a full block.
699 const int numIters = dinfo->output_height / numRowsPerBlock;
700 for (int i = 0; i < numIters; i++) {
701 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
702 if (linesRead < numRowsPerBlock) {
703 // FIXME: Handle incomplete YUV decodes without signalling an error.
704 return kInvalidInput;
705 }
706
707 // Update rowptrs.
708 for (int i = 0; i < numYRowsPerBlock; i++) {
709 rowptrs[i] += blockIncrementY;
710 }
711 for (int i = 0; i < DCTSIZE; i++) {
712 rowptrs[i + 2 * DCTSIZE] += blockIncrementU;
713 rowptrs[i + 3 * DCTSIZE] += blockIncrementV;
714 }
715 }
716
717 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
718 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
719 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
720 if (remainingRows > 0) {
721 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill
722 // this requirement using a dummy row buffer.
723 // FIXME: Should SkCodec have an extra memory buffer that can be shared among
724 // all of the implementations that use temporary/garbage memory?
725 SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fYWidthBytes);
726 for (int i = remainingRows; i < numYRowsPerBlock; i++) {
727 rowptrs[i] = dummyRow.get();
728 }
729 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
730 for (int i = remainingUVRows; i < DCTSIZE; i++) {
731 rowptrs[i + 2 * DCTSIZE] = dummyRow.get();
732 rowptrs[i + 3 * DCTSIZE] = dummyRow.get();
733 }
734
735 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
736 if (linesRead < remainingRows) {
737 // FIXME: Handle incomplete YUV decodes without signalling an error.
738 return kInvalidInput;
739 }
740 }
741
742 return kSuccess;
743}