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