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