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/core/SkTypes.h"
11
12 #ifdef SK_CODEC_DECODES_JPEG
13 #include "include/codec/SkCodec.h"
14 #include "include/core/SkAlphaType.h"
15 #include "include/core/SkColorType.h"
16 #include "include/core/SkData.h"
17 #include "include/core/SkImageInfo.h"
18 #include "include/core/SkPixmap.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkStream.h"
21 #include "include/core/SkYUVAInfo.h"
22 #include "include/private/base/SkAlign.h"
23 #include "include/private/base/SkMalloc.h"
24 #include "include/private/base/SkTemplates.h"
25 #include "include/private/base/SkTo.h"
26 #include "modules/skcms/skcms.h"
27 #include "src/codec/SkCodecPriv.h"
28 #include "src/codec/SkJpegConstants.h"
29 #include "src/codec/SkJpegDecoderMgr.h"
30 #include "src/codec/SkJpegPriv.h"
31 #include "src/codec/SkParseEncodedOrigin.h"
32 #include "src/codec/SkSwizzler.h"
33
34 #ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
35 #include "include/private/SkGainmapInfo.h"
36 #include "src/codec/SkJpegMultiPicture.h"
37 #include "src/codec/SkJpegSegmentScan.h"
38 #include "src/codec/SkJpegXmp.h"
39 #endif // SK_CODEC_DECODES_JPEG_GAINMAPS
40
41 #include <array>
42 #include <csetjmp>
43 #include <cstring>
44 #include <utility>
45 #include <vector>
46
47 using namespace skia_private;
48
49 class SkSampler;
50 struct SkGainmapInfo;
51
52 // This warning triggers false postives way too often in here.
53 #if defined(__GNUC__) && !defined(__clang__)
54 #pragma GCC diagnostic ignored "-Wclobbered"
55 #endif
56
57 extern "C" {
58 #include "jpeglib.h"
59 #include "jmorecfg.h"
60 }
61
IsJpeg(const void * buffer,size_t bytesRead)62 bool SkJpegCodec::IsJpeg(const void* buffer, size_t bytesRead) {
63 return bytesRead >= sizeof(kJpegSig) && !memcmp(buffer, kJpegSig, sizeof(kJpegSig));
64 }
65
is_orientation_marker(jpeg_marker_struct * marker,SkEncodedOrigin * orientation)66 static bool is_orientation_marker(jpeg_marker_struct* marker, SkEncodedOrigin* orientation) {
67 if (kExifMarker != marker->marker || marker->data_length < kExifHeaderSize) {
68 return false;
69 }
70
71 if (0 != memcmp(marker->data, kExifSig, sizeof(kExifSig))) {
72 return false;
73 }
74
75 // Account for 'E', 'x', 'i', 'f', '\0', '<fill byte>'.
76 constexpr size_t kOffset = 6;
77 return SkParseEncodedOrigin(marker->data + kOffset, marker->data_length - kOffset,
78 orientation);
79 }
80
get_exif_orientation(jpeg_decompress_struct * dinfo)81 static SkEncodedOrigin get_exif_orientation(jpeg_decompress_struct* dinfo) {
82 SkEncodedOrigin orientation;
83 for (jpeg_marker_struct* marker = dinfo->marker_list; marker; marker = marker->next) {
84 if (is_orientation_marker(marker, &orientation)) {
85 return orientation;
86 }
87 }
88
89 return kDefault_SkEncodedOrigin;
90 }
91
92 /*
93 * Return metadata with a specific marker and signature.
94 *
95 * Search for segments that start with the specified targetMarker, followed by the specified
96 * signature.
97 *
98 * Some types of metadata (e.g, ICC profiles) are too big to fit into a single segment's data (which
99 * is limited to 64k), and come in multiple parts. For this type of data, bytesInIndex is >0. After
100 * the signature comes bytesInIndex bytes (big endian) for the index of the segment's part, followed
101 * by bytesInIndex bytes (big endian) for the total number of parts. If all parts are present,
102 * stitch them together and return the combined result. Return failure if parts are absent, there
103 * are duplicate parts, or parts disagree on the total number of parts.
104 *
105 * If alwaysCopyData is true, then return a copy of the data. If alwaysCopyData is false, then
106 * return a direct reference to the data pointed to by dinfo, if possible.
107 */
read_metadata(jpeg_decompress_struct * dinfo,const uint32_t targetMarker,const uint8_t * signature,size_t signatureSize,size_t bytesInIndex=0,bool alwaysCopyData=false)108 static sk_sp<SkData> read_metadata(jpeg_decompress_struct* dinfo,
109 const uint32_t targetMarker,
110 const uint8_t* signature,
111 size_t signatureSize,
112 size_t bytesInIndex = 0,
113 bool alwaysCopyData = false) {
114 // Compute the total size of the entire header (signature plus index plus count), since we'll
115 // use it often.
116 const size_t headerSize = signatureSize + 2 * bytesInIndex;
117
118 // A map from part index to the data in each part.
119 std::vector<sk_sp<SkData>> parts;
120
121 // Running total of number of data in all parts.
122 size_t partsTotalSize = 0;
123
124 // Running total number of parts found.
125 uint32_t foundPartCount = 0;
126
127 // The expected number of parts (initialized at the first part we encounter).
128 uint32_t expectedPartCount = 0;
129
130 // Iterate through the image's segments.
131 for (jpeg_marker_struct* marker = dinfo->marker_list; marker; marker = marker->next) {
132 // Skip segments that don't have the right marker, signature, or are too small.
133 if (targetMarker != marker->marker || marker->data_length <= headerSize ||
134 memcmp(marker->data, signature, signatureSize) != 0) {
135 continue;
136 }
137
138 // Read this part's index and count as big-endian (if they are present, otherwise hard-code
139 // them to 1).
140 uint32_t partIndex = 0;
141 uint32_t partCount = 0;
142 if (bytesInIndex == 0) {
143 partIndex = 1;
144 partCount = 1;
145 } else {
146 for (size_t i = 0; i < bytesInIndex; ++i) {
147 partIndex = (partIndex << 8) + marker->data[signatureSize + i];
148 partCount = (partCount << 8) + marker->data[signatureSize + bytesInIndex + i];
149 }
150 }
151
152 // A part count of 0 is invalid.
153 if (!partCount) {
154 SkCodecPrintf("Invalid marker part count zero\n");
155 return nullptr;
156 }
157
158 // The indices must in the range 1, ..., count.
159 if (partIndex <= 0 || partIndex > partCount) {
160 SkCodecPrintf("Invalid marker index %u for count %u\n", partIndex, partCount);
161 return nullptr;
162 }
163
164 // If this is the first marker we've encountered set the expected part count to its count.
165 if (expectedPartCount == 0) {
166 expectedPartCount = partCount;
167 parts.resize(expectedPartCount);
168 }
169
170 // If this does not match the expected part count, then fail.
171 if (partCount != expectedPartCount) {
172 SkCodecPrintf("Conflicting marker counts %u vs %u\n", partCount, expectedPartCount);
173 return nullptr;
174 }
175
176 // Make an SkData directly referencing the decoder's data for this part.
177 auto partData = SkData::MakeWithoutCopy(marker->data + headerSize,
178 marker->data_length - headerSize);
179
180 // Fail if duplicates are found.
181 if (parts[partIndex-1]) {
182 SkCodecPrintf("Duplicate parts for index %u of %u\n", partIndex, expectedPartCount);
183 return nullptr;
184 }
185
186 // Save part in the map.
187 partsTotalSize += partData->size();
188 parts[partIndex-1] = std::move(partData);
189 foundPartCount += 1;
190
191 // Stop as soon as we find all of the parts.
192 if (foundPartCount == expectedPartCount) {
193 break;
194 }
195 }
196
197 // Return nullptr if we don't find the data (this is not an error).
198 if (expectedPartCount == 0) {
199 return nullptr;
200 }
201
202 // Fail if we don't have all of the parts.
203 if (foundPartCount != expectedPartCount) {
204 SkCodecPrintf("Incomplete set of markers (expected %u got %u)\n",
205 expectedPartCount,
206 foundPartCount);
207 return nullptr;
208 }
209
210 // Return a direct reference to the data if there is only one part and we're allowed to.
211 if (!alwaysCopyData && expectedPartCount == 1) {
212 return std::move(parts[0]);
213 }
214
215 // Copy all of the markers and stitch them together.
216 auto result = SkData::MakeUninitialized(partsTotalSize);
217 void* copyDest = result->writable_data();
218 for (const auto& part : parts) {
219 memcpy(copyDest, part->data(), part->size());
220 copyDest = SkTAddOffset<void>(copyDest, part->size());
221 }
222 return result;
223 }
224
read_color_profile(jpeg_decompress_struct * dinfo)225 static std::unique_ptr<SkEncodedInfo::ICCProfile> read_color_profile(
226 jpeg_decompress_struct* dinfo) {
227 auto iccData = read_metadata(dinfo,
228 kICCMarker,
229 kICCSig,
230 sizeof(kICCSig),
231 kICCMarkerIndexSize,
232 /*alwaysCopyData=*/true);
233 if (!iccData) {
234 return nullptr;
235 }
236 return SkEncodedInfo::ICCProfile::Make(std::move(iccData));
237 }
238
ReadHeader(SkStream * stream,SkCodec ** codecOut,JpegDecoderMgr ** decoderMgrOut,std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile)239 SkCodec::Result SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
240 JpegDecoderMgr** decoderMgrOut,
241 std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
242
243 // Create a JpegDecoderMgr to own all of the decompress information
244 std::unique_ptr<JpegDecoderMgr> decoderMgr(new JpegDecoderMgr(stream));
245
246 // libjpeg errors will be caught and reported here
247 skjpeg_error_mgr::AutoPushJmpBuf jmp(decoderMgr->errorMgr());
248 if (setjmp(jmp)) {
249 return decoderMgr->returnFailure("ReadHeader", kInvalidInput);
250 }
251
252 // Initialize the decompress info and the source manager
253 decoderMgr->init();
254 auto* dinfo = decoderMgr->dinfo();
255
256 // Instruct jpeg library to save the markers that we care about. Since
257 // the orientation and color profile will not change, we can skip this
258 // step on rewinds.
259 if (codecOut) {
260 jpeg_save_markers(dinfo, kExifMarker, 0xFFFF);
261 jpeg_save_markers(dinfo, kICCMarker, 0xFFFF);
262 jpeg_save_markers(dinfo, kMpfMarker, 0xFFFF);
263 jpeg_save_markers(dinfo, kGainmapMarker, 0xFFFF);
264 }
265
266 // Read the jpeg header
267 switch (jpeg_read_header(dinfo, true)) {
268 case JPEG_HEADER_OK:
269 break;
270 case JPEG_SUSPENDED:
271 return decoderMgr->returnFailure("ReadHeader", kIncompleteInput);
272 default:
273 return decoderMgr->returnFailure("ReadHeader", kInvalidInput);
274 }
275
276 if (codecOut) {
277 // Get the encoded color type
278 SkEncodedInfo::Color color;
279 if (!decoderMgr->getEncodedColor(&color)) {
280 return kInvalidInput;
281 }
282
283 SkEncodedOrigin orientation = get_exif_orientation(dinfo);
284 auto profile = read_color_profile(dinfo);
285 if (profile) {
286 auto type = profile->profile()->data_color_space;
287 switch (decoderMgr->dinfo()->jpeg_color_space) {
288 case JCS_CMYK:
289 case JCS_YCCK:
290 if (type != skcms_Signature_CMYK) {
291 profile = nullptr;
292 }
293 break;
294 case JCS_GRAYSCALE:
295 if (type != skcms_Signature_Gray &&
296 type != skcms_Signature_RGB)
297 {
298 profile = nullptr;
299 }
300 break;
301 default:
302 if (type != skcms_Signature_RGB) {
303 profile = nullptr;
304 }
305 break;
306 }
307 }
308 if (!profile) {
309 profile = std::move(defaultColorProfile);
310 }
311
312 SkEncodedInfo info = SkEncodedInfo::Make(dinfo->image_width, dinfo->image_height,
313 color, SkEncodedInfo::kOpaque_Alpha, 8,
314 std::move(profile));
315
316 SkJpegCodec* codec = new SkJpegCodec(std::move(info),
317 std::unique_ptr<SkStream>(stream),
318 decoderMgr.release(),
319 orientation);
320 *codecOut = codec;
321 } else {
322 SkASSERT(nullptr != decoderMgrOut);
323 *decoderMgrOut = decoderMgr.release();
324 }
325 return kSuccess;
326 }
327
MakeFromStream(std::unique_ptr<SkStream> stream,Result * result)328 std::unique_ptr<SkCodec> SkJpegCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
329 Result* result) {
330 return SkJpegCodec::MakeFromStream(std::move(stream), result, nullptr);
331 }
332
MakeFromStream(std::unique_ptr<SkStream> stream,Result * result,std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile)333 std::unique_ptr<SkCodec> SkJpegCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
334 Result* result, std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
335 SkCodec* codec = nullptr;
336 *result = ReadHeader(stream.get(), &codec, nullptr, std::move(defaultColorProfile));
337 if (kSuccess == *result) {
338 // Codec has taken ownership of the stream, we do not need to delete it
339 SkASSERT(codec);
340 stream.release();
341 return std::unique_ptr<SkCodec>(codec);
342 }
343 return nullptr;
344 }
345
SkJpegCodec(SkEncodedInfo && info,std::unique_ptr<SkStream> stream,JpegDecoderMgr * decoderMgr,SkEncodedOrigin origin)346 SkJpegCodec::SkJpegCodec(SkEncodedInfo&& info,
347 std::unique_ptr<SkStream> stream,
348 JpegDecoderMgr* decoderMgr,
349 SkEncodedOrigin origin)
350 : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, std::move(stream), origin)
351 , fDecoderMgr(decoderMgr)
352 , fReadyState(decoderMgr->dinfo()->global_state) {}
353 SkJpegCodec::~SkJpegCodec() = default;
354
355 /*
356 * Return the row bytes of a particular image type and width
357 */
get_row_bytes(const j_decompress_ptr dinfo)358 static size_t get_row_bytes(const j_decompress_ptr dinfo) {
359 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
360 dinfo->out_color_components;
361 return dinfo->output_width * colorBytes;
362
363 }
364
365 /*
366 * Calculate output dimensions based on the provided factors.
367 *
368 * Not to be used on the actual jpeg_decompress_struct used for decoding, since it will
369 * incorrectly modify num_components.
370 */
calc_output_dimensions(jpeg_decompress_struct * dinfo,unsigned int num,unsigned int denom)371 void calc_output_dimensions(jpeg_decompress_struct* dinfo, unsigned int num, unsigned int denom) {
372 dinfo->num_components = 0;
373 dinfo->scale_num = num;
374 dinfo->scale_denom = denom;
375 jpeg_calc_output_dimensions(dinfo);
376 }
377
378 /*
379 * Return a valid set of output dimensions for this decoder, given an input scale
380 */
onGetScaledDimensions(float desiredScale) const381 SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
382 // 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
383 // support these as well
384 unsigned int num;
385 unsigned int denom = 8;
386 if (desiredScale >= 0.9375) {
387 num = 8;
388 } else if (desiredScale >= 0.8125) {
389 num = 7;
390 } else if (desiredScale >= 0.6875f) {
391 num = 6;
392 } else if (desiredScale >= 0.5625f) {
393 num = 5;
394 } else if (desiredScale >= 0.4375f) {
395 num = 4;
396 } else if (desiredScale >= 0.3125f) {
397 num = 3;
398 } else if (desiredScale >= 0.1875f) {
399 num = 2;
400 } else {
401 num = 1;
402 }
403
404 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
405 jpeg_decompress_struct dinfo;
406 sk_bzero(&dinfo, sizeof(dinfo));
407 dinfo.image_width = this->dimensions().width();
408 dinfo.image_height = this->dimensions().height();
409 dinfo.global_state = fReadyState;
410 calc_output_dimensions(&dinfo, num, denom);
411
412 // Return the calculated output dimensions for the given scale
413 return SkISize::Make(dinfo.output_width, dinfo.output_height);
414 }
415
onRewind()416 bool SkJpegCodec::onRewind() {
417 JpegDecoderMgr* decoderMgr = nullptr;
418 if (kSuccess != ReadHeader(this->stream(), nullptr, &decoderMgr, nullptr)) {
419 return fDecoderMgr->returnFalse("onRewind");
420 }
421 SkASSERT(nullptr != decoderMgr);
422 fDecoderMgr.reset(decoderMgr);
423
424 fSwizzler.reset(nullptr);
425 fSwizzleSrcRow = nullptr;
426 fColorXformSrcRow = nullptr;
427 fStorage.reset();
428
429 return true;
430 }
431
conversionSupported(const SkImageInfo & dstInfo,bool srcIsOpaque,bool needsColorXform)432 bool SkJpegCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
433 bool needsColorXform) {
434 SkASSERT(srcIsOpaque);
435
436 if (kUnknown_SkAlphaType == dstInfo.alphaType()) {
437 return false;
438 }
439
440 if (kOpaque_SkAlphaType != dstInfo.alphaType()) {
441 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
442 "- it is being decoded as non-opaque, which will draw slower\n");
443 }
444
445 J_COLOR_SPACE encodedColorType = fDecoderMgr->dinfo()->jpeg_color_space;
446
447 // Check for valid color types and set the output color space
448 switch (dstInfo.colorType()) {
449 case kRGBA_8888_SkColorType:
450 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
451 break;
452 case kBGRA_8888_SkColorType:
453 if (needsColorXform) {
454 // Always using RGBA as the input format for color xforms makes the
455 // implementation a little simpler.
456 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
457 } else {
458 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
459 }
460 break;
461 case kRGB_565_SkColorType:
462 if (needsColorXform) {
463 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
464 } else {
465 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
466 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
467 }
468 break;
469 case kGray_8_SkColorType:
470 if (JCS_GRAYSCALE != encodedColorType) {
471 return false;
472 }
473
474 if (needsColorXform) {
475 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
476 } else {
477 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
478 }
479 break;
480 case kBGR_101010x_XR_SkColorType:
481 case kRGBA_F16_SkColorType:
482 SkASSERT(needsColorXform);
483 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
484 break;
485 default:
486 return false;
487 }
488
489 // Check if we will decode to CMYK. libjpeg-turbo does not convert CMYK to RGBA, so
490 // we must do it ourselves.
491 if (JCS_CMYK == encodedColorType || JCS_YCCK == encodedColorType) {
492 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
493 }
494
495 return true;
496 }
497
498 /*
499 * Checks if we can natively scale to the requested dimensions and natively scales the
500 * dimensions if possible
501 */
onDimensionsSupported(const SkISize & size)502 bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
503 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
504 if (setjmp(jmp)) {
505 return fDecoderMgr->returnFalse("onDimensionsSupported");
506 }
507
508 const unsigned int dstWidth = size.width();
509 const unsigned int dstHeight = size.height();
510
511 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
512 // FIXME: Why is this necessary?
513 jpeg_decompress_struct dinfo;
514 sk_bzero(&dinfo, sizeof(dinfo));
515 dinfo.image_width = this->dimensions().width();
516 dinfo.image_height = this->dimensions().height();
517 dinfo.global_state = fReadyState;
518
519 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
520 unsigned int num = 8;
521 const unsigned int denom = 8;
522 calc_output_dimensions(&dinfo, num, denom);
523 while (dinfo.output_width != dstWidth || dinfo.output_height != dstHeight) {
524
525 // Return a failure if we have tried all of the possible scales
526 if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
527 return false;
528 }
529
530 // Try the next scale
531 num -= 1;
532 calc_output_dimensions(&dinfo, num, denom);
533 }
534
535 fDecoderMgr->dinfo()->scale_num = num;
536 fDecoderMgr->dinfo()->scale_denom = denom;
537 return true;
538 }
539
readRows(const SkImageInfo & dstInfo,void * dst,size_t rowBytes,int count,const Options & opts)540 int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
541 const Options& opts) {
542 // Set the jump location for libjpeg-turbo errors
543 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
544 if (setjmp(jmp)) {
545 return 0;
546 }
547
548 // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case,
549 // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer.
550 // We can never swizzle "in place" because the swizzler may perform sampling and/or
551 // subsetting.
552 // When fColorXformSrcRow is non-null, it means that we need to color xform and that
553 // we cannot color xform "in place" (many times we can, but not when the src and dst
554 // are different sizes).
555 // In this case, we will color xform from fColorXformSrcRow into the dst.
556 JSAMPLE* decodeDst = (JSAMPLE*) dst;
557 uint32_t* swizzleDst = (uint32_t*) dst;
558 size_t decodeDstRowBytes = rowBytes;
559 size_t swizzleDstRowBytes = rowBytes;
560 int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width();
561 if (fSwizzleSrcRow && fColorXformSrcRow) {
562 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
563 swizzleDst = fColorXformSrcRow;
564 decodeDstRowBytes = 0;
565 swizzleDstRowBytes = 0;
566 dstWidth = fSwizzler->swizzleWidth();
567 } else if (fColorXformSrcRow) {
568 decodeDst = (JSAMPLE*) fColorXformSrcRow;
569 swizzleDst = fColorXformSrcRow;
570 decodeDstRowBytes = 0;
571 swizzleDstRowBytes = 0;
572 } else if (fSwizzleSrcRow) {
573 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
574 decodeDstRowBytes = 0;
575 dstWidth = fSwizzler->swizzleWidth();
576 }
577
578 for (int y = 0; y < count; y++) {
579 uint32_t lines = jpeg_read_scanlines(fDecoderMgr->dinfo(), &decodeDst, 1);
580 if (0 == lines) {
581 return y;
582 }
583
584 if (fSwizzler) {
585 fSwizzler->swizzle(swizzleDst, decodeDst);
586 }
587
588 if (this->colorXform()) {
589 this->applyColorXform(dst, swizzleDst, dstWidth);
590 dst = SkTAddOffset<void>(dst, rowBytes);
591 }
592
593 decodeDst = SkTAddOffset<JSAMPLE>(decodeDst, decodeDstRowBytes);
594 swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
595 }
596
597 return count;
598 }
599
600 /*
601 * This is a bit tricky. We only need the swizzler to do format conversion if the jpeg is
602 * encoded as CMYK.
603 * And even then we still may not need it. If the jpeg has a CMYK color profile and a color
604 * xform, the color xform will handle the CMYK->RGB conversion.
605 */
needs_swizzler_to_convert_from_cmyk(J_COLOR_SPACE jpegColorType,const skcms_ICCProfile * srcProfile,bool hasColorSpaceXform)606 static inline bool needs_swizzler_to_convert_from_cmyk(J_COLOR_SPACE jpegColorType,
607 const skcms_ICCProfile* srcProfile,
608 bool hasColorSpaceXform) {
609 if (JCS_CMYK != jpegColorType) {
610 return false;
611 }
612
613 bool hasCMYKColorSpace = srcProfile && srcProfile->data_color_space == skcms_Signature_CMYK;
614 return !hasCMYKColorSpace || !hasColorSpaceXform;
615 }
616
617 /*
618 * Performs the jpeg decode
619 */
onGetPixels(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & options,int * rowsDecoded)620 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
621 void* dst, size_t dstRowBytes,
622 const Options& options,
623 int* rowsDecoded) {
624 if (options.fSubset) {
625 // Subsets are not supported.
626 return kUnimplemented;
627 }
628
629 // Get a pointer to the decompress info since we will use it quite frequently
630 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
631
632 // Set the jump location for libjpeg errors
633 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
634 if (setjmp(jmp)) {
635 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
636 }
637
638 if (!jpeg_start_decompress(dinfo)) {
639 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
640 }
641
642 // The recommended output buffer height should always be 1 in high quality modes.
643 // If it's not, we want to know because it means our strategy is not optimal.
644 SkASSERT(1 == dinfo->rec_outbuf_height);
645
646 if (needs_swizzler_to_convert_from_cmyk(dinfo->out_color_space,
647 this->getEncodedInfo().profile(), this->colorXform())) {
648 this->initializeSwizzler(dstInfo, options, true);
649 }
650
651 if (!this->allocateStorage(dstInfo)) {
652 return kInternalError;
653 }
654
655 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options);
656 if (rows < dstInfo.height()) {
657 *rowsDecoded = rows;
658 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
659 }
660
661 return kSuccess;
662 }
663
allocateStorage(const SkImageInfo & dstInfo)664 bool SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) {
665 int dstWidth = dstInfo.width();
666
667 size_t swizzleBytes = 0;
668 if (fSwizzler) {
669 swizzleBytes = get_row_bytes(fDecoderMgr->dinfo());
670 dstWidth = fSwizzler->swizzleWidth();
671 SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes));
672 }
673
674 size_t xformBytes = 0;
675
676 if (this->colorXform() && sizeof(uint32_t) != dstInfo.bytesPerPixel()) {
677 xformBytes = dstWidth * sizeof(uint32_t);
678 }
679
680 size_t totalBytes = swizzleBytes + xformBytes;
681 if (totalBytes > 0) {
682 if (!fStorage.reset(totalBytes)) {
683 return false;
684 }
685 fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
686 fColorXformSrcRow = (xformBytes > 0) ?
687 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
688 }
689 return true;
690 }
691
initializeSwizzler(const SkImageInfo & dstInfo,const Options & options,bool needsCMYKToRGB)692 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
693 bool needsCMYKToRGB) {
694 Options swizzlerOptions = options;
695 if (options.fSubset) {
696 // Use fSwizzlerSubset if this is a subset decode. This is necessary in the case
697 // where libjpeg-turbo provides a subset and then we need to subset it further.
698 // Also, verify that fSwizzlerSubset is initialized and valid.
699 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
700 fSwizzlerSubset.width() == options.fSubset->width());
701 swizzlerOptions.fSubset = &fSwizzlerSubset;
702 }
703
704 SkImageInfo swizzlerDstInfo = dstInfo;
705 if (this->colorXform()) {
706 // The color xform will be expecting RGBA 8888 input.
707 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
708 }
709
710 if (needsCMYKToRGB) {
711 // The swizzler is used to convert to from CMYK.
712 // The swizzler does not use the width or height on SkEncodedInfo.
713 auto swizzlerInfo = SkEncodedInfo::Make(0, 0, SkEncodedInfo::kInvertedCMYK_Color,
714 SkEncodedInfo::kOpaque_Alpha, 8);
715 fSwizzler = SkSwizzler::Make(swizzlerInfo, nullptr, swizzlerDstInfo, swizzlerOptions);
716 } else {
717 int srcBPP = 0;
718 switch (fDecoderMgr->dinfo()->out_color_space) {
719 case JCS_EXT_RGBA:
720 case JCS_EXT_BGRA:
721 case JCS_CMYK:
722 srcBPP = 4;
723 break;
724 case JCS_RGB565:
725 srcBPP = 2;
726 break;
727 case JCS_GRAYSCALE:
728 srcBPP = 1;
729 break;
730 default:
731 SkASSERT(false);
732 break;
733 }
734 fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerDstInfo, swizzlerOptions);
735 }
736 SkASSERT(fSwizzler);
737 }
738
getSampler(bool createIfNecessary)739 SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
740 if (!createIfNecessary || fSwizzler) {
741 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
742 return fSwizzler.get();
743 }
744
745 bool needsCMYKToRGB = needs_swizzler_to_convert_from_cmyk(
746 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
747 this->colorXform());
748 this->initializeSwizzler(this->dstInfo(), this->options(), needsCMYKToRGB);
749 if (!this->allocateStorage(this->dstInfo())) {
750 return nullptr;
751 }
752 return fSwizzler.get();
753 }
754
onStartScanlineDecode(const SkImageInfo & dstInfo,const Options & options)755 SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
756 const Options& options) {
757 // Set the jump location for libjpeg errors
758 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
759 if (setjmp(jmp)) {
760 SkCodecPrintf("setjmp: Error from libjpeg\n");
761 return kInvalidInput;
762 }
763
764 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
765 SkCodecPrintf("start decompress failed\n");
766 return kInvalidInput;
767 }
768
769 bool needsCMYKToRGB = needs_swizzler_to_convert_from_cmyk(
770 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
771 this->colorXform());
772 if (options.fSubset) {
773 uint32_t startX = options.fSubset->x();
774 uint32_t width = options.fSubset->width();
775
776 // libjpeg-turbo may need to align startX to a multiple of the IDCT
777 // block size. If this is the case, it will decrease the value of
778 // startX to the appropriate alignment and also increase the value
779 // of width so that the right edge of the requested subset remains
780 // the same.
781 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width);
782
783 SkASSERT(startX <= (uint32_t) options.fSubset->x());
784 SkASSERT(width >= (uint32_t) options.fSubset->width());
785 SkASSERT(startX + width >= (uint32_t) options.fSubset->right());
786
787 // Instruct the swizzler (if it is necessary) to further subset the
788 // output provided by libjpeg-turbo.
789 //
790 // We set this here (rather than in the if statement below), so that
791 // if (1) we don't need a swizzler for the subset, and (2) we need a
792 // swizzler for CMYK, the swizzler will still use the proper subset
793 // dimensions.
794 //
795 // Note that the swizzler will ignore the y and height parameters of
796 // the subset. Since the scanline decoder (and the swizzler) handle
797 // one row at a time, only the subsetting in the x-dimension matters.
798 fSwizzlerSubset.setXYWH(options.fSubset->x() - startX, 0,
799 options.fSubset->width(), options.fSubset->height());
800
801 // We will need a swizzler if libjpeg-turbo cannot provide the exact
802 // subset that we request.
803 if (startX != (uint32_t) options.fSubset->x() ||
804 width != (uint32_t) options.fSubset->width()) {
805 this->initializeSwizzler(dstInfo, options, needsCMYKToRGB);
806 }
807 }
808
809 // Make sure we have a swizzler if we are converting from CMYK.
810 if (!fSwizzler && needsCMYKToRGB) {
811 this->initializeSwizzler(dstInfo, options, true);
812 }
813
814 if (!this->allocateStorage(dstInfo)) {
815 return kInternalError;
816 }
817
818 return kSuccess;
819 }
820
onGetScanlines(void * dst,int count,size_t dstRowBytes)821 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
822 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options());
823 if (rows < count) {
824 // This allows us to skip calling jpeg_finish_decompress().
825 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
826 }
827
828 return rows;
829 }
830
onSkipScanlines(int count)831 bool SkJpegCodec::onSkipScanlines(int count) {
832 // Set the jump location for libjpeg errors
833 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
834 if (setjmp(jmp)) {
835 return fDecoderMgr->returnFalse("onSkipScanlines");
836 }
837
838 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
839 }
840
is_yuv_supported(const jpeg_decompress_struct * dinfo,const SkJpegCodec & codec,const SkYUVAPixmapInfo::SupportedDataTypes * supportedDataTypes,SkYUVAPixmapInfo * yuvaPixmapInfo)841 static bool is_yuv_supported(const jpeg_decompress_struct* dinfo,
842 const SkJpegCodec& codec,
843 const SkYUVAPixmapInfo::SupportedDataTypes* supportedDataTypes,
844 SkYUVAPixmapInfo* yuvaPixmapInfo) {
845 // Scaling is not supported in raw data mode.
846 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
847
848 // I can't imagine that this would ever change, but we do depend on it.
849 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8.");
850
851 if (JCS_YCbCr != dinfo->jpeg_color_space) {
852 return false;
853 }
854
855 SkASSERT(3 == dinfo->num_components);
856 SkASSERT(dinfo->comp_info);
857
858 // It is possible to perform a YUV decode for any combination of
859 // horizontal and vertical sampling that is supported by
860 // libjpeg/libjpeg-turbo. However, we will start by supporting only the
861 // common cases (where U and V have samp_factors of one).
862 //
863 // The definition of samp_factor is kind of the opposite of what SkCodec
864 // thinks of as a sampling factor. samp_factor is essentially a
865 // multiplier, and the larger the samp_factor is, the more samples that
866 // there will be. Ex:
867 // U_plane_width = image_width * (U_h_samp_factor / max_h_samp_factor)
868 //
869 // Supporting cases where the samp_factors for U or V were larger than
870 // that of Y would be an extremely difficult change, given that clients
871 // allocate memory as if the size of the Y plane is always the size of the
872 // image. However, this case is very, very rare.
873 if ((1 != dinfo->comp_info[1].h_samp_factor) ||
874 (1 != dinfo->comp_info[1].v_samp_factor) ||
875 (1 != dinfo->comp_info[2].h_samp_factor) ||
876 (1 != dinfo->comp_info[2].v_samp_factor))
877 {
878 return false;
879 }
880
881 // Support all common cases of Y samp_factors.
882 // TODO (msarett): As mentioned above, it would be possible to support
883 // more combinations of samp_factors. The issues are:
884 // (1) Are there actually any images that are not covered
885 // by these cases?
886 // (2) How much complexity would be added to the
887 // implementation in order to support these rare
888 // cases?
889 int hSampY = dinfo->comp_info[0].h_samp_factor;
890 int vSampY = dinfo->comp_info[0].v_samp_factor;
891 SkASSERT(hSampY == dinfo->max_h_samp_factor);
892 SkASSERT(vSampY == dinfo->max_v_samp_factor);
893
894 SkYUVAInfo::Subsampling tempSubsampling;
895 if (1 == hSampY && 1 == vSampY) {
896 tempSubsampling = SkYUVAInfo::Subsampling::k444;
897 } else if (2 == hSampY && 1 == vSampY) {
898 tempSubsampling = SkYUVAInfo::Subsampling::k422;
899 } else if (2 == hSampY && 2 == vSampY) {
900 tempSubsampling = SkYUVAInfo::Subsampling::k420;
901 } else if (1 == hSampY && 2 == vSampY) {
902 tempSubsampling = SkYUVAInfo::Subsampling::k440;
903 } else if (4 == hSampY && 1 == vSampY) {
904 tempSubsampling = SkYUVAInfo::Subsampling::k411;
905 } else if (4 == hSampY && 2 == vSampY) {
906 tempSubsampling = SkYUVAInfo::Subsampling::k410;
907 } else {
908 return false;
909 }
910 if (supportedDataTypes &&
911 !supportedDataTypes->supported(SkYUVAInfo::PlaneConfig::kY_U_V,
912 SkYUVAPixmapInfo::DataType::kUnorm8)) {
913 return false;
914 }
915 if (yuvaPixmapInfo) {
916 SkColorType colorTypes[SkYUVAPixmapInfo::kMaxPlanes];
917 size_t rowBytes[SkYUVAPixmapInfo::kMaxPlanes];
918 for (int i = 0; i < 3; ++i) {
919 colorTypes[i] = kAlpha_8_SkColorType;
920 rowBytes[i] = dinfo->comp_info[i].width_in_blocks * DCTSIZE;
921 }
922 SkYUVAInfo yuvaInfo(codec.dimensions(),
923 SkYUVAInfo::PlaneConfig::kY_U_V,
924 tempSubsampling,
925 kJPEG_Full_SkYUVColorSpace,
926 codec.getOrigin(),
927 SkYUVAInfo::Siting::kCentered,
928 SkYUVAInfo::Siting::kCentered);
929 *yuvaPixmapInfo = SkYUVAPixmapInfo(yuvaInfo, colorTypes, rowBytes);
930 }
931 return true;
932 }
933
onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes & supportedDataTypes,SkYUVAPixmapInfo * yuvaPixmapInfo) const934 bool SkJpegCodec::onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
935 SkYUVAPixmapInfo* yuvaPixmapInfo) const {
936 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
937 return is_yuv_supported(dinfo, *this, &supportedDataTypes, yuvaPixmapInfo);
938 }
939
onGetYUVAPlanes(const SkYUVAPixmaps & yuvaPixmaps)940 SkCodec::Result SkJpegCodec::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
941 // Get a pointer to the decompress info since we will use it quite frequently
942 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
943 if (!is_yuv_supported(dinfo, *this, nullptr, nullptr)) {
944 return fDecoderMgr->returnFailure("onGetYUVAPlanes", kInvalidInput);
945 }
946 // Set the jump location for libjpeg errors
947 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
948 if (setjmp(jmp)) {
949 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
950 }
951
952 dinfo->raw_data_out = TRUE;
953 if (!jpeg_start_decompress(dinfo)) {
954 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
955 }
956
957 const std::array<SkPixmap, SkYUVAPixmaps::kMaxPlanes>& planes = yuvaPixmaps.planes();
958
959 #ifdef SK_DEBUG
960 {
961 // A previous implementation claims that the return value of is_yuv_supported()
962 // may change after calling jpeg_start_decompress(). It looks to me like this
963 // was caused by a bug in the old code, but we'll be safe and check here.
964 // Also check that pixmap properties agree with expectations.
965 SkYUVAPixmapInfo info;
966 SkASSERT(is_yuv_supported(dinfo, *this, nullptr, &info));
967 SkASSERT(info.yuvaInfo() == yuvaPixmaps.yuvaInfo());
968 for (int i = 0; i < info.numPlanes(); ++i) {
969 SkASSERT(planes[i].colorType() == kAlpha_8_SkColorType);
970 SkASSERT(info.planeInfo(i) == planes[i].info());
971 }
972 }
973 #endif
974
975 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
976 // a 2-D array of pixels for each of the components (Y, U, V) in the image.
977 // Cheat Sheet:
978 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE***
979 JSAMPARRAY yuv[3];
980
981 // Set aside enough space for pointers to rows of Y, U, and V.
982 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
983 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE)
984 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE)
985 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE)
986
987 // Initialize rowptrs.
988 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
989 static_assert(sizeof(JSAMPLE) == 1);
990 for (int i = 0; i < numYRowsPerBlock; i++) {
991 rowptrs[i] = static_cast<JSAMPLE*>(planes[0].writable_addr()) + i* planes[0].rowBytes();
992 }
993 for (int i = 0; i < DCTSIZE; i++) {
994 rowptrs[i + 2 * DCTSIZE] =
995 static_cast<JSAMPLE*>(planes[1].writable_addr()) + i* planes[1].rowBytes();
996 rowptrs[i + 3 * DCTSIZE] =
997 static_cast<JSAMPLE*>(planes[2].writable_addr()) + i* planes[2].rowBytes();
998 }
999
1000 // After each loop iteration, we will increment pointers to Y, U, and V.
1001 size_t blockIncrementY = numYRowsPerBlock * planes[0].rowBytes();
1002 size_t blockIncrementU = DCTSIZE * planes[1].rowBytes();
1003 size_t blockIncrementV = DCTSIZE * planes[2].rowBytes();
1004
1005 uint32_t numRowsPerBlock = numYRowsPerBlock;
1006
1007 // We intentionally round down here, as this first loop will only handle
1008 // full block rows. As a special case at the end, we will handle any
1009 // remaining rows that do not make up a full block.
1010 const int numIters = dinfo->output_height / numRowsPerBlock;
1011 for (int i = 0; i < numIters; i++) {
1012 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
1013 if (linesRead < numRowsPerBlock) {
1014 // FIXME: Handle incomplete YUV decodes without signalling an error.
1015 return kInvalidInput;
1016 }
1017
1018 // Update rowptrs.
1019 for (int j = 0; j < numYRowsPerBlock; j++) {
1020 rowptrs[j] += blockIncrementY;
1021 }
1022 for (int j = 0; j < DCTSIZE; j++) {
1023 rowptrs[j + 2 * DCTSIZE] += blockIncrementU;
1024 rowptrs[j + 3 * DCTSIZE] += blockIncrementV;
1025 }
1026 }
1027
1028 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
1029 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
1030 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
1031 if (remainingRows > 0) {
1032 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill
1033 // this requirement using an extra row buffer.
1034 // FIXME: Should SkCodec have an extra memory buffer that can be shared among
1035 // all of the implementations that use temporary/garbage memory?
1036 AutoTMalloc<JSAMPLE> extraRow(planes[0].rowBytes());
1037 for (int i = remainingRows; i < numYRowsPerBlock; i++) {
1038 rowptrs[i] = extraRow.get();
1039 }
1040 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
1041 for (int i = remainingUVRows; i < DCTSIZE; i++) {
1042 rowptrs[i + 2 * DCTSIZE] = extraRow.get();
1043 rowptrs[i + 3 * DCTSIZE] = extraRow.get();
1044 }
1045
1046 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
1047 if (linesRead < remainingRows) {
1048 // FIXME: Handle incomplete YUV decodes without signalling an error.
1049 return kInvalidInput;
1050 }
1051 }
1052
1053 return kSuccess;
1054 }
1055
1056 // This function is declared in SkJpegInfo.h, used by SkPDF.
SkGetJpegInfo(const void * data,size_t len,SkISize * size,SkEncodedInfo::Color * colorType,SkEncodedOrigin * orientation)1057 bool SkGetJpegInfo(const void* data, size_t len,
1058 SkISize* size,
1059 SkEncodedInfo::Color* colorType,
1060 SkEncodedOrigin* orientation) {
1061 if (!SkJpegCodec::IsJpeg(data, len)) {
1062 return false;
1063 }
1064
1065 SkMemoryStream stream(data, len);
1066 JpegDecoderMgr decoderMgr(&stream);
1067 // libjpeg errors will be caught and reported here
1068 skjpeg_error_mgr::AutoPushJmpBuf jmp(decoderMgr.errorMgr());
1069 if (setjmp(jmp)) {
1070 return false;
1071 }
1072 decoderMgr.init();
1073 jpeg_decompress_struct* dinfo = decoderMgr.dinfo();
1074 jpeg_save_markers(dinfo, kExifMarker, 0xFFFF);
1075 jpeg_save_markers(dinfo, kICCMarker, 0xFFFF);
1076 jpeg_save_markers(dinfo, kMpfMarker, 0xFFFF);
1077 jpeg_save_markers(dinfo, kGainmapMarker, 0xFFFF);
1078 if (JPEG_HEADER_OK != jpeg_read_header(dinfo, true)) {
1079 return false;
1080 }
1081 SkEncodedInfo::Color encodedColorType;
1082 if (!decoderMgr.getEncodedColor(&encodedColorType)) {
1083 return false; // Unable to interpret the color channels as colors.
1084 }
1085 if (colorType) {
1086 *colorType = encodedColorType;
1087 }
1088 if (orientation) {
1089 *orientation = get_exif_orientation(dinfo);
1090 }
1091 if (size) {
1092 *size = {SkToS32(dinfo->image_width), SkToS32(dinfo->image_height)};
1093 }
1094 return true;
1095 }
1096
1097 #ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
1098 // Collect and parse the primary and extended XMP metadata.
get_xmp_metadata(JpegDecoderMgr * decoderMgr)1099 static std::unique_ptr<SkJpegXmp> get_xmp_metadata(JpegDecoderMgr* decoderMgr) {
1100 std::vector<sk_sp<SkData>> decoderApp1Params;
1101 for (jpeg_marker_struct* marker = decoderMgr->dinfo()->marker_list; marker;
1102 marker = marker->next) {
1103 if (marker->marker != kXMPMarker) {
1104 continue;
1105 }
1106 auto data = SkData::MakeWithoutCopy(marker->data, marker->data_length);
1107 decoderApp1Params.push_back(std::move(data));
1108 }
1109 return SkJpegXmp::Make(decoderApp1Params);
1110 }
1111
1112 // Extract the SkJpegMultiPictureParameters from this image (if they exist) along with the segment
1113 // that the parameters came from.
find_mp_params(JpegDecoderMgr * decoderMgr,SkJpegSegment * outMpParamsSegment)1114 static std::unique_ptr<SkJpegMultiPictureParameters> find_mp_params(
1115 JpegDecoderMgr* decoderMgr, SkJpegSegment* outMpParamsSegment) {
1116 std::unique_ptr<SkJpegMultiPictureParameters> mpParams;
1117 size_t skippedSegmentCount = 0;
1118
1119 // Search though the libjpeg segments until we find a segment that parses as MP parameters. Keep
1120 // track of how many segments with the MPF marker we skipped over to get there.
1121 for (jpeg_marker_struct* marker = decoderMgr->dinfo()->marker_list; marker;
1122 marker = marker->next) {
1123 if (marker->marker != kMpfMarker) {
1124 continue;
1125 }
1126 mpParams = SkJpegMultiPictureParameters::Make(
1127 SkData::MakeWithoutCopy(marker->data, marker->data_length));
1128 if (mpParams) {
1129 break;
1130 }
1131 ++skippedSegmentCount;
1132 }
1133
1134 // Now, find the segment for that corresponds to the libjpeg marker.
1135 // TODO(ccameron): It may be preferable to make SkJpegSourceMgr save segments with certain
1136 // markers to avoid this strangeness.
1137 for (const auto& segment : decoderMgr->getSourceMgr()->getAllSegments()) {
1138 if (segment.marker != kMpfMarker) {
1139 continue;
1140 }
1141 if (skippedSegmentCount == 0) {
1142 *outMpParamsSegment = segment;
1143 return mpParams;
1144 }
1145 skippedSegmentCount--;
1146 }
1147 return nullptr;
1148 }
1149
1150 // Attempt to extract a gainmap image from a specified offset and size within the decoder's stream.
1151 // Returns true only if the extracted gainmap image includes XMP metadata that specifies HDR gainmap
1152 // rendering parameters.
extract_gainmap(SkJpegSourceMgr * decoderSource,size_t offset,size_t size,bool base_image_has_hdrgm,SkGainmapInfo * outInfo,std::unique_ptr<SkStream> * outGainmapImageStream)1153 static bool extract_gainmap(SkJpegSourceMgr* decoderSource,
1154 size_t offset,
1155 size_t size,
1156 bool base_image_has_hdrgm,
1157 SkGainmapInfo* outInfo,
1158 std::unique_ptr<SkStream>* outGainmapImageStream) {
1159 // Extract the SkData for this image.
1160 bool imageDataWasCopied = false;
1161 auto imageData = decoderSource->getSubsetData(offset, size, &imageDataWasCopied);
1162 if (!imageData) {
1163 SkCodecPrintf("Failed to extract MP image.\n");
1164 return false;
1165 }
1166
1167 // Scan through the image up to the StartOfScan. We'll be searching for the XMP metadata.
1168 SkJpegSegmentScanner scan(kJpegMarkerStartOfScan);
1169 scan.onBytes(imageData->data(), imageData->size());
1170 if (scan.hadError() || !scan.isDone()) {
1171 SkCodecPrintf("Failed to scan header of MP image.\n");
1172 return false;
1173 }
1174
1175 // Collect the potential XMP segments and build the XMP.
1176 std::vector<sk_sp<SkData>> app1Params;
1177 for (const auto& segment : scan.getSegments()) {
1178 if (segment.marker != kXMPMarker) {
1179 continue;
1180 }
1181 auto parameters = SkJpegSegmentScanner::GetParameters(imageData.get(), segment);
1182 if (!parameters) {
1183 continue;
1184 }
1185 app1Params.push_back(std::move(parameters));
1186 }
1187 auto xmp = SkJpegXmp::Make(app1Params);
1188 if (!xmp) {
1189 return false;
1190 }
1191
1192 // Check if this image identifies itself as a gainmap.
1193 bool did_populate_info = false;
1194 SkGainmapInfo info;
1195
1196 // Check for HDRGM only if the base image specified hdrgm:Version="1.0".
1197 did_populate_info = base_image_has_hdrgm && xmp->getGainmapInfoHDRGM(&info);
1198
1199 // Next, check HDRGainMap. This does not require anything specific from the base image.
1200 if (!did_populate_info) {
1201 did_populate_info = xmp->getGainmapInfoHDRGainMap(&info);
1202 }
1203
1204 // If none of the formats identified itself as a gainmap and populated |info| then fail.
1205 if (!did_populate_info) {
1206 return false;
1207 }
1208
1209 // This image is a gainmap. Populate its stream.
1210 if (outGainmapImageStream) {
1211 if (imageDataWasCopied) {
1212 *outGainmapImageStream = SkMemoryStream::Make(imageData);
1213 } else {
1214 *outGainmapImageStream = SkMemoryStream::MakeCopy(imageData->data(), imageData->size());
1215 }
1216 }
1217 *outInfo = info;
1218 return true;
1219 }
1220
onGetGainmapInfo(SkGainmapInfo * info,std::unique_ptr<SkStream> * gainmapImageStream)1221 bool SkJpegCodec::onGetGainmapInfo(SkGainmapInfo* info,
1222 std::unique_ptr<SkStream>* gainmapImageStream) {
1223 // The GContainer and APP15-based HDRGM formats require XMP metadata. Extract it now.
1224 std::unique_ptr<SkJpegXmp> xmp = get_xmp_metadata(fDecoderMgr.get());
1225
1226 // Set |base_image_has_hdrgm| to be true if the base image has HDRGM XMP metadata that includes
1227 // the a Version 1.0 attribute.
1228 const bool base_image_has_hdrgm = xmp && xmp->getGainmapInfoHDRGM(nullptr);
1229
1230 // Attempt to locate the gainmap from the container XMP.
1231 size_t containerGainmapOffset = 0;
1232 size_t containerGainmapSize = 0;
1233 if (xmp && xmp->getContainerGainmapLocation(&containerGainmapOffset, &containerGainmapSize)) {
1234 const auto& segments = fDecoderMgr->getSourceMgr()->getAllSegments();
1235 if (!segments.empty()) {
1236 const auto& lastSegment = segments.back();
1237 if (lastSegment.marker == kJpegMarkerEndOfImage) {
1238 containerGainmapOffset += lastSegment.offset + kJpegMarkerCodeSize;
1239 }
1240 }
1241 }
1242
1243 // Attempt to find MultiPicture parameters.
1244 SkJpegSegment mpParamsSegment;
1245 auto mpParams = find_mp_params(fDecoderMgr.get(), &mpParamsSegment);
1246
1247 // First, search through the Multi-Picture images.
1248 if (mpParams) {
1249 for (size_t mpImageIndex = 1; mpImageIndex < mpParams->images.size(); ++mpImageIndex) {
1250 size_t mpImageOffset = SkJpegMultiPictureParameters::GetAbsoluteOffset(
1251 mpParams->images[mpImageIndex].dataOffset, mpParamsSegment.offset);
1252 size_t mpImageSize = mpParams->images[mpImageIndex].size;
1253
1254 if (extract_gainmap(fDecoderMgr->getSourceMgr(),
1255 mpImageOffset,
1256 mpImageSize,
1257 base_image_has_hdrgm,
1258 info,
1259 gainmapImageStream)) {
1260 // If the GContainer also suggested an offset and size, assert that we found the
1261 // image that the GContainer suggested.
1262 if (containerGainmapOffset) {
1263 SkASSERT(containerGainmapOffset == mpImageOffset);
1264 SkASSERT(containerGainmapSize == mpImageSize);
1265 }
1266 return true;
1267 }
1268 }
1269 }
1270
1271 // Next, try the location suggested by the container XMP.
1272 if (containerGainmapOffset) {
1273 if (extract_gainmap(fDecoderMgr->getSourceMgr(),
1274 containerGainmapOffset,
1275 containerGainmapSize,
1276 base_image_has_hdrgm,
1277 info,
1278 gainmapImageStream)) {
1279 return true;
1280 }
1281 SkCodecPrintf("Failed to extract container-specified gainmap.\n");
1282 }
1283
1284 // Finally, attempt to extract SkGainmapInfo from the primary image's XMP and extract the
1285 // gainmap from APP15 segments.
1286 if (xmp && xmp->getGainmapInfoHDRGM(info)) {
1287 auto gainmapData = read_metadata(fDecoderMgr->dinfo(),
1288 kGainmapMarker,
1289 kGainmapSig,
1290 sizeof(kGainmapSig),
1291 kGainmapMarkerIndexSize,
1292 /*alwaysCopyData=*/true);
1293 if (gainmapData) {
1294 *gainmapImageStream = SkMemoryStream::Make(std::move(gainmapData));
1295 if (*gainmapImageStream) {
1296 return true;
1297 }
1298 } else {
1299 SkCodecPrintf("Parsed HDRGM metadata but did not find image\n");
1300 }
1301 }
1302 return false;
1303 }
1304 #else
onGetGainmapInfo(SkGainmapInfo * info,std::unique_ptr<SkStream> * gainmapImageStream)1305 bool SkJpegCodec::onGetGainmapInfo(SkGainmapInfo* info,
1306 std::unique_ptr<SkStream>* gainmapImageStream) {
1307 return false;
1308 }
1309 #endif // SK_CODEC_DECODES_JPEG_GAINMAPS
1310
1311 #endif // SK_CODEC_DECODES_JPEG
1312