• 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/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