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