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