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