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