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 "src/codec/SkJpegCodec.h"
9
10 #include "include/codec/SkCodec.h"
11 #include "include/codec/SkJpegDecoder.h"
12 #include "include/core/SkAlphaType.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkData.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkPixmap.h"
17 #include "include/core/SkRefCnt.h"
18 #include "include/core/SkStream.h"
19 #include "include/core/SkTypes.h"
20 #include "include/core/SkYUVAInfo.h"
21 #include "include/private/base/SkAlign.h"
22 #include "include/private/base/SkMalloc.h"
23 #include "include/private/base/SkTemplates.h"
24 #include "modules/skcms/skcms.h"
25 #include "src/codec/SkCodecPriv.h"
26 #include "src/codec/SkJpegConstants.h"
27 #include "src/codec/SkJpegDecoderMgr.h"
28 #include "src/codec/SkJpegMetadataDecoderImpl.h"
29 #include "src/codec/SkJpegPriv.h"
30 #include "src/codec/SkParseEncodedOrigin.h"
31 #include "src/codec/SkSwizzler.h"
32
33 #ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
34 #include "include/private/SkGainmapInfo.h"
35 #endif // SK_CODEC_DECODES_JPEG_GAINMAPS
36
37 #include <array>
38 #include <csetjmp>
39 #include <cstring>
40 #include <utility>
41
42 using namespace skia_private;
43
44 class SkSampler;
45 struct SkGainmapInfo;
46
47 // This warning triggers false postives way too often in here.
48 #if defined(__GNUC__) && !defined(__clang__)
49 #pragma GCC diagnostic ignored "-Wclobbered"
50 #endif
51
52 extern "C" {
53 #include "jpeglib.h" // NO_G3_REWRITE
54 }
55
IsJpeg(const void * buffer,size_t bytesRead)56 bool SkJpegCodec::IsJpeg(const void* buffer, size_t bytesRead) {
57 return bytesRead >= sizeof(kJpegSig) && !memcmp(buffer, kJpegSig, sizeof(kJpegSig));
58 }
59
get_sk_marker_list(jpeg_decompress_struct * dinfo)60 SkJpegMarkerList get_sk_marker_list(jpeg_decompress_struct* dinfo) {
61 SkJpegMarkerList markerList;
62 for (auto* marker = dinfo->marker_list; marker; marker = marker->next) {
63 markerList.emplace_back(marker->marker,
64 SkData::MakeWithoutCopy(marker->data, marker->data_length));
65 }
66 return markerList;
67 }
68
get_exif_orientation(sk_sp<SkData> exifData)69 static SkEncodedOrigin get_exif_orientation(sk_sp<SkData> exifData) {
70 SkEncodedOrigin origin = kDefault_SkEncodedOrigin;
71 if (exifData && SkParseEncodedOrigin(exifData->bytes(), exifData->size(), &origin)) {
72 return origin;
73 }
74 return kDefault_SkEncodedOrigin;
75 }
76
ReadHeader(SkStream * stream,SkCodec ** codecOut,JpegDecoderMgr ** decoderMgrOut,std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile)77 SkCodec::Result SkJpegCodec::ReadHeader(
78 SkStream* stream,
79 SkCodec** codecOut,
80 JpegDecoderMgr** decoderMgrOut,
81 std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
82 // Create a JpegDecoderMgr to own all of the decompress information
83 std::unique_ptr<JpegDecoderMgr> decoderMgr(new JpegDecoderMgr(stream));
84
85 // libjpeg errors will be caught and reported here
86 skjpeg_error_mgr::AutoPushJmpBuf jmp(decoderMgr->errorMgr());
87 if (setjmp(jmp)) {
88 return decoderMgr->returnFailure("ReadHeader", kInvalidInput);
89 }
90
91 // Initialize the decompress info and the source manager
92 decoderMgr->init();
93 auto* dinfo = decoderMgr->dinfo();
94
95 // Instruct jpeg library to save the markers that we care about. Since
96 // the orientation and color profile will not change, we can skip this
97 // step on rewinds.
98 if (codecOut) {
99 jpeg_save_markers(dinfo, kExifMarker, 0xFFFF);
100 jpeg_save_markers(dinfo, kICCMarker, 0xFFFF);
101 jpeg_save_markers(dinfo, kMpfMarker, 0xFFFF);
102 }
103
104 // Read the jpeg header
105 switch (jpeg_read_header(dinfo, true)) {
106 case JPEG_HEADER_OK:
107 break;
108 case JPEG_SUSPENDED:
109 return decoderMgr->returnFailure("ReadHeader", kIncompleteInput);
110 default:
111 return decoderMgr->returnFailure("ReadHeader", kInvalidInput);
112 }
113
114 if (codecOut) {
115 // Get the encoded color type
116 SkEncodedInfo::Color color;
117 if (!decoderMgr->getEncodedColor(&color)) {
118 return kInvalidInput;
119 }
120
121 auto metadataDecoder =
122 std::make_unique<SkJpegMetadataDecoderImpl>(get_sk_marker_list(dinfo));
123
124 SkEncodedOrigin orientation =
125 get_exif_orientation(metadataDecoder->getExifMetadata(/*copyData=*/false));
126
127 std::unique_ptr<SkEncodedInfo::ICCProfile> profile;
128 if (auto iccProfileData = metadataDecoder->getICCProfileData(/*copyData=*/true)) {
129 profile = SkEncodedInfo::ICCProfile::Make(std::move(iccProfileData));
130 }
131 if (profile) {
132 auto type = profile->profile()->data_color_space;
133 switch (decoderMgr->dinfo()->jpeg_color_space) {
134 case JCS_CMYK:
135 case JCS_YCCK:
136 if (type != skcms_Signature_CMYK) {
137 profile = nullptr;
138 }
139 break;
140 case JCS_GRAYSCALE:
141 if (type != skcms_Signature_Gray &&
142 type != skcms_Signature_RGB)
143 {
144 profile = nullptr;
145 }
146 break;
147 default:
148 if (type != skcms_Signature_RGB) {
149 profile = nullptr;
150 }
151 break;
152 }
153 }
154 if (!profile) {
155 profile = std::move(defaultColorProfile);
156 }
157
158 SkEncodedInfo info = SkEncodedInfo::Make(dinfo->image_width, dinfo->image_height,
159 color, SkEncodedInfo::kOpaque_Alpha, 8,
160 std::move(profile));
161
162 SkJpegCodec* codec = new SkJpegCodec(std::move(info),
163 std::unique_ptr<SkStream>(stream),
164 decoderMgr.release(),
165 orientation);
166 *codecOut = codec;
167 } else {
168 SkASSERT(nullptr != decoderMgrOut);
169 *decoderMgrOut = decoderMgr.release();
170 }
171 return kSuccess;
172 }
173
MakeFromStream(std::unique_ptr<SkStream> stream,Result * result)174 std::unique_ptr<SkCodec> SkJpegCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
175 Result* result) {
176 return SkJpegCodec::MakeFromStream(std::move(stream), result, nullptr);
177 }
178
MakeFromStream(std::unique_ptr<SkStream> stream,Result * result,std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile)179 std::unique_ptr<SkCodec> SkJpegCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
180 Result* result, std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
181 SkASSERT(result);
182 if (!stream) {
183 *result = SkCodec::kInvalidInput;
184 return nullptr;
185 }
186 SkCodec* codec = nullptr;
187 *result = ReadHeader(stream.get(), &codec, nullptr, std::move(defaultColorProfile));
188 if (kSuccess == *result) {
189 // Codec has taken ownership of the stream, we do not need to delete it
190 SkASSERT(codec);
191 stream.release();
192 return std::unique_ptr<SkCodec>(codec);
193 }
194 return nullptr;
195 }
196
SkJpegCodec(SkEncodedInfo && info,std::unique_ptr<SkStream> stream,JpegDecoderMgr * decoderMgr,SkEncodedOrigin origin)197 SkJpegCodec::SkJpegCodec(SkEncodedInfo&& info,
198 std::unique_ptr<SkStream> stream,
199 JpegDecoderMgr* decoderMgr,
200 SkEncodedOrigin origin)
201 : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, std::move(stream), origin)
202 , fDecoderMgr(decoderMgr)
203 , fReadyState(decoderMgr->dinfo()->global_state) {}
204 SkJpegCodec::~SkJpegCodec() = default;
205
206 /*
207 * Return the row bytes of a particular image type and width
208 */
get_row_bytes(const j_decompress_ptr dinfo)209 static size_t get_row_bytes(const j_decompress_ptr dinfo) {
210 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
211 dinfo->out_color_components;
212 return dinfo->output_width * colorBytes;
213
214 }
215
216 /*
217 * Calculate output dimensions based on the provided factors.
218 *
219 * Not to be used on the actual jpeg_decompress_struct used for decoding, since it will
220 * incorrectly modify num_components.
221 */
calc_output_dimensions(jpeg_decompress_struct * dinfo,unsigned int num,unsigned int denom)222 void calc_output_dimensions(jpeg_decompress_struct* dinfo, unsigned int num, unsigned int denom) {
223 dinfo->num_components = 0;
224 dinfo->scale_num = num;
225 dinfo->scale_denom = denom;
226 jpeg_calc_output_dimensions(dinfo);
227 }
228
229 /*
230 * Return a valid set of output dimensions for this decoder, given an input scale
231 */
onGetScaledDimensions(float desiredScale) const232 SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
233 // 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
234 // support these as well
235 unsigned int num;
236 unsigned int denom = 8;
237 if (desiredScale >= 0.9375) {
238 num = 8;
239 } else if (desiredScale >= 0.8125) {
240 num = 7;
241 } else if (desiredScale >= 0.6875f) {
242 num = 6;
243 } else if (desiredScale >= 0.5625f) {
244 num = 5;
245 } else if (desiredScale >= 0.4375f) {
246 num = 4;
247 } else if (desiredScale >= 0.3125f) {
248 num = 3;
249 } else if (desiredScale >= 0.1875f) {
250 num = 2;
251 } else {
252 num = 1;
253 }
254
255 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
256 jpeg_decompress_struct dinfo;
257 sk_bzero(&dinfo, sizeof(dinfo));
258 dinfo.image_width = this->dimensions().width();
259 dinfo.image_height = this->dimensions().height();
260 dinfo.global_state = fReadyState;
261 calc_output_dimensions(&dinfo, num, denom);
262
263 // Return the calculated output dimensions for the given scale
264 return SkISize::Make(dinfo.output_width, dinfo.output_height);
265 }
266
onRewind()267 bool SkJpegCodec::onRewind() {
268 JpegDecoderMgr* decoderMgr = nullptr;
269 if (kSuccess != ReadHeader(this->stream(), nullptr, &decoderMgr, nullptr)) {
270 return fDecoderMgr->returnFalse("onRewind");
271 }
272 SkASSERT(nullptr != decoderMgr);
273 fDecoderMgr.reset(decoderMgr);
274
275 fSwizzler.reset(nullptr);
276 fSwizzleSrcRow = nullptr;
277 fColorXformSrcRow = nullptr;
278 fStorage.reset();
279
280 return true;
281 }
282
conversionSupported(const SkImageInfo & dstInfo,bool srcIsOpaque,bool needsColorXform)283 bool SkJpegCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
284 bool needsColorXform) {
285 SkASSERT(srcIsOpaque);
286
287 if (kUnknown_SkAlphaType == dstInfo.alphaType()) {
288 return false;
289 }
290
291 if (kOpaque_SkAlphaType != dstInfo.alphaType()) {
292 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
293 "- it is being decoded as non-opaque, which will draw slower\n");
294 }
295
296 J_COLOR_SPACE encodedColorType = fDecoderMgr->dinfo()->jpeg_color_space;
297
298 // Check for valid color types and set the output color space
299 switch (dstInfo.colorType()) {
300 case kRGBA_8888_SkColorType:
301 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
302 break;
303 case kBGRA_8888_SkColorType:
304 if (needsColorXform) {
305 // Always using RGBA as the input format for color xforms makes the
306 // implementation a little simpler.
307 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
308 } else {
309 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
310 }
311 break;
312 case kRGB_565_SkColorType:
313 if (needsColorXform) {
314 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
315 } else {
316 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
317 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
318 }
319 break;
320 case kGray_8_SkColorType:
321 if (JCS_GRAYSCALE != encodedColorType) {
322 return false;
323 }
324
325 if (needsColorXform) {
326 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
327 } else {
328 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
329 }
330 break;
331 case kBGRA_10101010_XR_SkColorType:
332 case kBGR_101010x_XR_SkColorType:
333 case kRGBA_F16_SkColorType:
334 SkASSERT(needsColorXform);
335 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
336 break;
337 default:
338 return false;
339 }
340
341 // Check if we will decode to CMYK. libjpeg-turbo does not convert CMYK to RGBA, so
342 // we must do it ourselves.
343 if (JCS_CMYK == encodedColorType || JCS_YCCK == encodedColorType) {
344 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
345 }
346
347 return true;
348 }
349
350 /*
351 * Checks if we can natively scale to the requested dimensions and natively scales the
352 * dimensions if possible
353 */
onDimensionsSupported(const SkISize & size)354 bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
355 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
356 if (setjmp(jmp)) {
357 return fDecoderMgr->returnFalse("onDimensionsSupported");
358 }
359
360 const unsigned int dstWidth = size.width();
361 const unsigned int dstHeight = size.height();
362
363 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
364 // FIXME: Why is this necessary?
365 jpeg_decompress_struct dinfo;
366 sk_bzero(&dinfo, sizeof(dinfo));
367 dinfo.image_width = this->dimensions().width();
368 dinfo.image_height = this->dimensions().height();
369 dinfo.global_state = fReadyState;
370
371 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
372 unsigned int num = 8;
373 const unsigned int denom = 8;
374 calc_output_dimensions(&dinfo, num, denom);
375 while (dinfo.output_width != dstWidth || dinfo.output_height != dstHeight) {
376
377 // Return a failure if we have tried all of the possible scales
378 if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
379 return false;
380 }
381
382 // Try the next scale
383 num -= 1;
384 calc_output_dimensions(&dinfo, num, denom);
385 }
386
387 fDecoderMgr->dinfo()->scale_num = num;
388 fDecoderMgr->dinfo()->scale_denom = denom;
389 return true;
390 }
391
readRows(const SkImageInfo & dstInfo,void * dst,size_t rowBytes,int count,const Options & opts)392 int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
393 const Options& opts) {
394 // Set the jump location for libjpeg-turbo errors
395 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
396 if (setjmp(jmp)) {
397 return 0;
398 }
399
400 // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case,
401 // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer.
402 // We can never swizzle "in place" because the swizzler may perform sampling and/or
403 // subsetting.
404 // When fColorXformSrcRow is non-null, it means that we need to color xform and that
405 // we cannot color xform "in place" (many times we can, but not when the src and dst
406 // are different sizes).
407 // In this case, we will color xform from fColorXformSrcRow into the dst.
408 JSAMPLE* decodeDst = (JSAMPLE*) dst;
409 uint32_t* swizzleDst = (uint32_t*) dst;
410 size_t decodeDstRowBytes = rowBytes;
411 size_t swizzleDstRowBytes = rowBytes;
412 int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width();
413 if (fSwizzleSrcRow && fColorXformSrcRow) {
414 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
415 swizzleDst = fColorXformSrcRow;
416 decodeDstRowBytes = 0;
417 swizzleDstRowBytes = 0;
418 dstWidth = fSwizzler->swizzleWidth();
419 } else if (fColorXformSrcRow) {
420 decodeDst = (JSAMPLE*) fColorXformSrcRow;
421 swizzleDst = fColorXformSrcRow;
422 decodeDstRowBytes = 0;
423 swizzleDstRowBytes = 0;
424 } else if (fSwizzleSrcRow) {
425 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
426 decodeDstRowBytes = 0;
427 dstWidth = fSwizzler->swizzleWidth();
428 }
429
430 for (int y = 0; y < count; y++) {
431 uint32_t lines = jpeg_read_scanlines(fDecoderMgr->dinfo(), &decodeDst, 1);
432 if (0 == lines) {
433 return y;
434 }
435
436 if (fSwizzler) {
437 fSwizzler->swizzle(swizzleDst, decodeDst);
438 }
439
440 if (this->colorXform()) {
441 this->applyColorXform(dst, swizzleDst, dstWidth);
442 dst = SkTAddOffset<void>(dst, rowBytes);
443 }
444
445 decodeDst = SkTAddOffset<JSAMPLE>(decodeDst, decodeDstRowBytes);
446 swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
447 }
448
449 return count;
450 }
451
452 /*
453 * This is a bit tricky. We only need the swizzler to do format conversion if the jpeg is
454 * encoded as CMYK.
455 * And even then we still may not need it. If the jpeg has a CMYK color profile and a color
456 * xform, the color xform will handle the CMYK->RGB conversion.
457 */
needs_swizzler_to_convert_from_cmyk(J_COLOR_SPACE jpegColorType,const skcms_ICCProfile * srcProfile,bool hasColorSpaceXform)458 static inline bool needs_swizzler_to_convert_from_cmyk(J_COLOR_SPACE jpegColorType,
459 const skcms_ICCProfile* srcProfile,
460 bool hasColorSpaceXform) {
461 if (JCS_CMYK != jpegColorType) {
462 return false;
463 }
464
465 bool hasCMYKColorSpace = srcProfile && srcProfile->data_color_space == skcms_Signature_CMYK;
466 return !hasCMYKColorSpace || !hasColorSpaceXform;
467 }
468
469 /*
470 * Performs the jpeg decode
471 */
onGetPixels(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & options,int * rowsDecoded)472 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
473 void* dst, size_t dstRowBytes,
474 const Options& options,
475 int* rowsDecoded) {
476 if (options.fSubset) {
477 // Subsets are not supported.
478 return kUnimplemented;
479 }
480
481 // Get a pointer to the decompress info since we will use it quite frequently
482 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
483
484 // Set the jump location for libjpeg errors
485 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
486 if (setjmp(jmp)) {
487 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
488 }
489
490 if (!jpeg_start_decompress(dinfo)) {
491 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
492 }
493
494 // The recommended output buffer height should always be 1 in high quality modes.
495 // If it's not, we want to know because it means our strategy is not optimal.
496 SkASSERT(1 == dinfo->rec_outbuf_height);
497
498 if (needs_swizzler_to_convert_from_cmyk(dinfo->out_color_space,
499 this->getEncodedInfo().profile(), this->colorXform())) {
500 this->initializeSwizzler(dstInfo, options, true);
501 }
502
503 if (!this->allocateStorage(dstInfo)) {
504 return kInternalError;
505 }
506
507 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options);
508 if (rows < dstInfo.height()) {
509 *rowsDecoded = rows;
510 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
511 }
512
513 return kSuccess;
514 }
515
allocateStorage(const SkImageInfo & dstInfo)516 bool SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) {
517 int dstWidth = dstInfo.width();
518
519 size_t swizzleBytes = 0;
520 if (fSwizzler) {
521 swizzleBytes = get_row_bytes(fDecoderMgr->dinfo());
522 dstWidth = fSwizzler->swizzleWidth();
523 SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes));
524 }
525
526 size_t xformBytes = 0;
527
528 if (this->colorXform() && sizeof(uint32_t) != dstInfo.bytesPerPixel()) {
529 xformBytes = dstWidth * sizeof(uint32_t);
530 }
531
532 size_t totalBytes = swizzleBytes + xformBytes;
533 if (totalBytes > 0) {
534 if (!fStorage.reset(totalBytes)) {
535 return false;
536 }
537 fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
538 fColorXformSrcRow = (xformBytes > 0) ?
539 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
540 }
541 return true;
542 }
543
initializeSwizzler(const SkImageInfo & dstInfo,const Options & options,bool needsCMYKToRGB)544 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
545 bool needsCMYKToRGB) {
546 Options swizzlerOptions = options;
547 if (options.fSubset) {
548 // Use fSwizzlerSubset if this is a subset decode. This is necessary in the case
549 // where libjpeg-turbo provides a subset and then we need to subset it further.
550 // Also, verify that fSwizzlerSubset is initialized and valid.
551 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
552 fSwizzlerSubset.width() == options.fSubset->width());
553 swizzlerOptions.fSubset = &fSwizzlerSubset;
554 }
555
556 SkImageInfo swizzlerDstInfo = dstInfo;
557 if (this->colorXform()) {
558 // The color xform will be expecting RGBA 8888 input.
559 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
560 }
561
562 if (needsCMYKToRGB) {
563 // The swizzler is used to convert to from CMYK.
564 // The swizzler does not use the width or height on SkEncodedInfo.
565 auto swizzlerInfo = SkEncodedInfo::Make(0, 0, SkEncodedInfo::kInvertedCMYK_Color,
566 SkEncodedInfo::kOpaque_Alpha, 8);
567 fSwizzler = SkSwizzler::Make(swizzlerInfo, nullptr, swizzlerDstInfo, swizzlerOptions);
568 } else {
569 int srcBPP = 0;
570 switch (fDecoderMgr->dinfo()->out_color_space) {
571 case JCS_EXT_RGBA:
572 case JCS_EXT_BGRA:
573 case JCS_CMYK:
574 srcBPP = 4;
575 break;
576 case JCS_RGB565:
577 srcBPP = 2;
578 break;
579 case JCS_GRAYSCALE:
580 srcBPP = 1;
581 break;
582 default:
583 SkASSERT(false);
584 break;
585 }
586 fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerDstInfo, swizzlerOptions);
587 }
588 SkASSERT(fSwizzler);
589 }
590
getSampler(bool createIfNecessary)591 SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
592 if (!createIfNecessary || fSwizzler) {
593 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
594 return fSwizzler.get();
595 }
596
597 bool needsCMYKToRGB = needs_swizzler_to_convert_from_cmyk(
598 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
599 this->colorXform());
600 this->initializeSwizzler(this->dstInfo(), this->options(), needsCMYKToRGB);
601 if (!this->allocateStorage(this->dstInfo())) {
602 return nullptr;
603 }
604 return fSwizzler.get();
605 }
606
onStartScanlineDecode(const SkImageInfo & dstInfo,const Options & options)607 SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
608 const Options& options) {
609 // Set the jump location for libjpeg errors
610 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
611 if (setjmp(jmp)) {
612 SkCodecPrintf("setjmp: Error from libjpeg\n");
613 return kInvalidInput;
614 }
615
616 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
617 SkCodecPrintf("start decompress failed\n");
618 return kInvalidInput;
619 }
620
621 bool needsCMYKToRGB = needs_swizzler_to_convert_from_cmyk(
622 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
623 this->colorXform());
624 if (options.fSubset) {
625 uint32_t startX = options.fSubset->x();
626 uint32_t width = options.fSubset->width();
627
628 // libjpeg-turbo may need to align startX to a multiple of the IDCT
629 // block size. If this is the case, it will decrease the value of
630 // startX to the appropriate alignment and also increase the value
631 // of width so that the right edge of the requested subset remains
632 // the same.
633 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width);
634
635 SkASSERT(startX <= (uint32_t) options.fSubset->x());
636 SkASSERT(width >= (uint32_t) options.fSubset->width());
637 SkASSERT(startX + width >= (uint32_t) options.fSubset->right());
638
639 // Instruct the swizzler (if it is necessary) to further subset the
640 // output provided by libjpeg-turbo.
641 //
642 // We set this here (rather than in the if statement below), so that
643 // if (1) we don't need a swizzler for the subset, and (2) we need a
644 // swizzler for CMYK, the swizzler will still use the proper subset
645 // dimensions.
646 //
647 // Note that the swizzler will ignore the y and height parameters of
648 // the subset. Since the scanline decoder (and the swizzler) handle
649 // one row at a time, only the subsetting in the x-dimension matters.
650 fSwizzlerSubset.setXYWH(options.fSubset->x() - startX, 0,
651 options.fSubset->width(), options.fSubset->height());
652
653 // We will need a swizzler if libjpeg-turbo cannot provide the exact
654 // subset that we request.
655 if (startX != (uint32_t) options.fSubset->x() ||
656 width != (uint32_t) options.fSubset->width()) {
657 this->initializeSwizzler(dstInfo, options, needsCMYKToRGB);
658 }
659 }
660
661 // Make sure we have a swizzler if we are converting from CMYK.
662 if (!fSwizzler && needsCMYKToRGB) {
663 this->initializeSwizzler(dstInfo, options, true);
664 }
665
666 if (!this->allocateStorage(dstInfo)) {
667 return kInternalError;
668 }
669
670 return kSuccess;
671 }
672
onGetScanlines(void * dst,int count,size_t dstRowBytes)673 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
674 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options());
675 if (rows < count) {
676 // This allows us to skip calling jpeg_finish_decompress().
677 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
678 }
679
680 return rows;
681 }
682
onSkipScanlines(int count)683 bool SkJpegCodec::onSkipScanlines(int count) {
684 // Set the jump location for libjpeg errors
685 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
686 if (setjmp(jmp)) {
687 return fDecoderMgr->returnFalse("onSkipScanlines");
688 }
689
690 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
691 }
692
is_yuv_supported(const jpeg_decompress_struct * dinfo,const SkJpegCodec & codec,const SkYUVAPixmapInfo::SupportedDataTypes * supportedDataTypes,SkYUVAPixmapInfo * yuvaPixmapInfo)693 static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
694 const SkJpegCodec& codec,
695 const SkYUVAPixmapInfo::SupportedDataTypes* supportedDataTypes,
696 SkYUVAPixmapInfo* yuvaPixmapInfo) {
697 // Scaling is not supported in raw data mode.
698 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
699
700 // I can't imagine that this would ever change, but we do depend on it.
701 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8.");
702
703 if (JCS_YCbCr != dinfo->jpeg_color_space) {
704 return false;
705 }
706
707 SkASSERT(3 == dinfo->num_components);
708 SkASSERT(dinfo->comp_info);
709
710 // It is possible to perform a YUV decode for any combination of
711 // horizontal and vertical sampling that is supported by
712 // libjpeg/libjpeg-turbo. However, we will start by supporting only the
713 // common cases (where U and V have samp_factors of one).
714 //
715 // The definition of samp_factor is kind of the opposite of what SkCodec
716 // thinks of as a sampling factor. samp_factor is essentially a
717 // multiplier, and the larger the samp_factor is, the more samples that
718 // there will be. Ex:
719 // U_plane_width = image_width * (U_h_samp_factor / max_h_samp_factor)
720 //
721 // Supporting cases where the samp_factors for U or V were larger than
722 // that of Y would be an extremely difficult change, given that clients
723 // allocate memory as if the size of the Y plane is always the size of the
724 // image. However, this case is very, very rare.
725 if ((1 != dinfo->comp_info[1].h_samp_factor) ||
726 (1 != dinfo->comp_info[1].v_samp_factor) ||
727 (1 != dinfo->comp_info[2].h_samp_factor) ||
728 (1 != dinfo->comp_info[2].v_samp_factor))
729 {
730 return false;
731 }
732
733 // Support all common cases of Y samp_factors.
734 // TODO (msarett): As mentioned above, it would be possible to support
735 // more combinations of samp_factors. The issues are:
736 // (1) Are there actually any images that are not covered
737 // by these cases?
738 // (2) How much complexity would be added to the
739 // implementation in order to support these rare
740 // cases?
741 int hSampY = dinfo->comp_info[0].h_samp_factor;
742 int vSampY = dinfo->comp_info[0].v_samp_factor;
743 SkASSERT(hSampY == dinfo->max_h_samp_factor);
744 SkASSERT(vSampY == dinfo->max_v_samp_factor);
745
746 SkYUVAInfo::Subsampling tempSubsampling;
747 if (1 == hSampY && 1 == vSampY) {
748 tempSubsampling = SkYUVAInfo::Subsampling::k444;
749 } else if (2 == hSampY && 1 == vSampY) {
750 tempSubsampling = SkYUVAInfo::Subsampling::k422;
751 } else if (2 == hSampY && 2 == vSampY) {
752 tempSubsampling = SkYUVAInfo::Subsampling::k420;
753 } else if (1 == hSampY && 2 == vSampY) {
754 tempSubsampling = SkYUVAInfo::Subsampling::k440;
755 } else if (4 == hSampY && 1 == vSampY) {
756 tempSubsampling = SkYUVAInfo::Subsampling::k411;
757 } else if (4 == hSampY && 2 == vSampY) {
758 tempSubsampling = SkYUVAInfo::Subsampling::k410;
759 } else {
760 return false;
761 }
762 if (supportedDataTypes &&
763 !supportedDataTypes->supported(SkYUVAInfo::PlaneConfig::kY_U_V,
764 SkYUVAPixmapInfo::DataType::kUnorm8)) {
765 return false;
766 }
767 if (yuvaPixmapInfo) {
768 SkColorType colorTypes[SkYUVAPixmapInfo::kMaxPlanes];
769 size_t rowBytes[SkYUVAPixmapInfo::kMaxPlanes];
770 for (int i = 0; i < 3; ++i) {
771 colorTypes[i] = kAlpha_8_SkColorType;
772 rowBytes[i] = dinfo->comp_info[i].width_in_blocks * DCTSIZE;
773 }
774 SkYUVAInfo yuvaInfo(codec.dimensions(),
775 SkYUVAInfo::PlaneConfig::kY_U_V,
776 tempSubsampling,
777 kJPEG_Full_SkYUVColorSpace,
778 codec.getOrigin(),
779 SkYUVAInfo::Siting::kCentered,
780 SkYUVAInfo::Siting::kCentered);
781 *yuvaPixmapInfo = SkYUVAPixmapInfo(yuvaInfo, colorTypes, rowBytes);
782 }
783 return true;
784 }
785
onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes & supportedDataTypes,SkYUVAPixmapInfo * yuvaPixmapInfo) const786 bool SkJpegCodec::onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
787 SkYUVAPixmapInfo* yuvaPixmapInfo) const {
788 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
789 return is_yuv_supported(dinfo, *this, &supportedDataTypes, yuvaPixmapInfo);
790 }
791
onGetYUVAPlanes(const SkYUVAPixmaps & yuvaPixmaps)792 SkCodec::Result SkJpegCodec::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
793 // Get a pointer to the decompress info since we will use it quite frequently
794 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
795 if (!is_yuv_supported(dinfo, *this, nullptr, nullptr)) {
796 return fDecoderMgr->returnFailure("onGetYUVAPlanes", kInvalidInput);
797 }
798 // Set the jump location for libjpeg errors
799 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
800 if (setjmp(jmp)) {
801 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
802 }
803
804 dinfo->raw_data_out = TRUE;
805 if (!jpeg_start_decompress(dinfo)) {
806 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
807 }
808
809 const std::array<SkPixmap, SkYUVAPixmaps::kMaxPlanes>& planes = yuvaPixmaps.planes();
810
811 #ifdef SK_DEBUG
812 {
813 // A previous implementation claims that the return value of is_yuv_supported()
814 // may change after calling jpeg_start_decompress(). It looks to me like this
815 // was caused by a bug in the old code, but we'll be safe and check here.
816 // Also check that pixmap properties agree with expectations.
817 SkYUVAPixmapInfo info;
818 SkASSERT(is_yuv_supported(dinfo, *this, nullptr, &info));
819 SkASSERT(info.yuvaInfo() == yuvaPixmaps.yuvaInfo());
820 for (int i = 0; i < info.numPlanes(); ++i) {
821 SkASSERT(planes[i].colorType() == kAlpha_8_SkColorType);
822 SkASSERT(info.planeInfo(i) == planes[i].info());
823 }
824 }
825 #endif
826
827 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
828 // a 2-D array of pixels for each of the components (Y, U, V) in the image.
829 // Cheat Sheet:
830 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE***
831 JSAMPARRAY yuv[3];
832
833 // Set aside enough space for pointers to rows of Y, U, and V.
834 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
835 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE)
836 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE)
837 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE)
838
839 // Initialize rowptrs.
840 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
841 static_assert(sizeof(JSAMPLE) == 1);
842 for (int i = 0; i < numYRowsPerBlock; i++) {
843 rowptrs[i] = static_cast<JSAMPLE*>(planes[0].writable_addr()) + i* planes[0].rowBytes();
844 }
845 for (int i = 0; i < DCTSIZE; i++) {
846 rowptrs[i + 2 * DCTSIZE] =
847 static_cast<JSAMPLE*>(planes[1].writable_addr()) + i* planes[1].rowBytes();
848 rowptrs[i + 3 * DCTSIZE] =
849 static_cast<JSAMPLE*>(planes[2].writable_addr()) + i* planes[2].rowBytes();
850 }
851
852 // After each loop iteration, we will increment pointers to Y, U, and V.
853 size_t blockIncrementY = numYRowsPerBlock * planes[0].rowBytes();
854 size_t blockIncrementU = DCTSIZE * planes[1].rowBytes();
855 size_t blockIncrementV = DCTSIZE * planes[2].rowBytes();
856
857 uint32_t numRowsPerBlock = numYRowsPerBlock;
858
859 // We intentionally round down here, as this first loop will only handle
860 // full block rows. As a special case at the end, we will handle any
861 // remaining rows that do not make up a full block.
862 const int numIters = dinfo->output_height / numRowsPerBlock;
863 for (int i = 0; i < numIters; i++) {
864 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
865 if (linesRead < numRowsPerBlock) {
866 // FIXME: Handle incomplete YUV decodes without signalling an error.
867 return kInvalidInput;
868 }
869
870 // Update rowptrs.
871 for (int j = 0; j < numYRowsPerBlock; j++) {
872 rowptrs[j] += blockIncrementY;
873 }
874 for (int j = 0; j < DCTSIZE; j++) {
875 rowptrs[j + 2 * DCTSIZE] += blockIncrementU;
876 rowptrs[j + 3 * DCTSIZE] += blockIncrementV;
877 }
878 }
879
880 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
881 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
882 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
883 if (remainingRows > 0) {
884 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill
885 // this requirement using an extra row buffer.
886 // FIXME: Should SkCodec have an extra memory buffer that can be shared among
887 // all of the implementations that use temporary/garbage memory?
888 AutoTMalloc<JSAMPLE> extraRow(planes[0].rowBytes());
889 for (int i = remainingRows; i < numYRowsPerBlock; i++) {
890 rowptrs[i] = extraRow.get();
891 }
892 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
893 for (int i = remainingUVRows; i < DCTSIZE; i++) {
894 rowptrs[i + 2 * DCTSIZE] = extraRow.get();
895 rowptrs[i + 3 * DCTSIZE] = extraRow.get();
896 }
897
898 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
899 if (linesRead < remainingRows) {
900 // FIXME: Handle incomplete YUV decodes without signalling an error.
901 return kInvalidInput;
902 }
903 }
904
905 return kSuccess;
906 }
907
onGetGainmapInfo(SkGainmapInfo * info,std::unique_ptr<SkStream> * gainmapImageStream)908 bool SkJpegCodec::onGetGainmapInfo(SkGainmapInfo* info,
909 std::unique_ptr<SkStream>* gainmapImageStream) {
910 #ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
911 sk_sp<SkData> gainmap_data;
912 SkGainmapInfo gainmap_info;
913
914 auto metadataDecoder =
915 std::make_unique<SkJpegMetadataDecoderImpl>(get_sk_marker_list(fDecoderMgr->dinfo()));
916 if (!metadataDecoder->findGainmapImage(
917 fDecoderMgr->getSourceMgr(), gainmap_data, gainmap_info)) {
918 return false;
919 }
920
921 *info = gainmap_info;
922 *gainmapImageStream = SkMemoryStream::Make(gainmap_data);
923 return true;
924 #else
925 return false;
926 #endif // SK_CODEC_DECODES_JPEG_GAINMAPS
927 }
928
929 namespace SkJpegDecoder {
IsJpeg(const void * data,size_t len)930 bool IsJpeg(const void* data, size_t len) {
931 return SkJpegCodec::IsJpeg(data, len);
932 }
933
Decode(std::unique_ptr<SkStream> stream,SkCodec::Result * outResult,SkCodecs::DecodeContext)934 std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
935 SkCodec::Result* outResult,
936 SkCodecs::DecodeContext) {
937 SkCodec::Result resultStorage;
938 if (!outResult) {
939 outResult = &resultStorage;
940 }
941 return SkJpegCodec::MakeFromStream(std::move(stream), outResult);
942 }
943
Decode(sk_sp<SkData> data,SkCodec::Result * outResult,SkCodecs::DecodeContext)944 std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
945 SkCodec::Result* outResult,
946 SkCodecs::DecodeContext) {
947 if (!data) {
948 if (outResult) {
949 *outResult = SkCodec::kInvalidInput;
950 }
951 return nullptr;
952 }
953 return Decode(SkMemoryStream::Make(std::move(data)), outResult, nullptr);
954 }
955
956 } // namespace SkJpegDecoder
957