blob: 7888b8a9fcd394b8793700244bd8e21cb1b9741e [file] [log] [blame]
msarette16b04a2015-04-15 07:32:19 -07001/*
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
msarette16b04a2015-04-15 07:32:19 -07008#include "SkJpegCodec.h"
Hal Canary83e0f1b2018-04-05 16:58:41 -04009
10#include "SkCodec.h"
msarette16b04a2015-04-15 07:32:19 -070011#include "SkCodecPriv.h"
Cary Clarka4083c92017-09-15 11:59:23 -040012#include "SkColorData.h"
Hal Canary83e0f1b2018-04-05 16:58:41 -040013#include "SkJpegDecoderMgr.h"
14#include "SkJpegInfo.h"
msarette16b04a2015-04-15 07:32:19 -070015#include "SkStream.h"
16#include "SkTemplates.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040017#include "SkTo.h"
msarette16b04a2015-04-15 07:32:19 -070018#include "SkTypes.h"
19
msarett1c8a5872015-07-07 08:50:01 -070020// stdio is needed for libjpeg-turbo
msarette16b04a2015-04-15 07:32:19 -070021#include <stdio.h>
msarettc1d03122016-03-25 08:58:55 -070022#include "SkJpegUtility.h"
msarette16b04a2015-04-15 07:32:19 -070023
mtkleindc90b532016-07-28 14:45:28 -070024// 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
msarette16b04a2015-04-15 07:32:19 -070029extern "C" {
30 #include "jerror.h"
msarette16b04a2015-04-15 07:32:19 -070031 #include "jpeglib.h"
32}
33
scroggodb30be22015-12-08 18:54:13 -080034bool SkJpegCodec::IsJpeg(const void* buffer, size_t bytesRead) {
Leon Scroggins III862c1962017-10-02 16:28:49 -040035 constexpr uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF };
scroggodb30be22015-12-08 18:54:13 -080036 return bytesRead >= 3 && !memcmp(buffer, jpegSig, sizeof(jpegSig));
msarette16b04a2015-04-15 07:32:19 -070037}
38
msarett0e6274f2016-03-21 08:04:40 -070039static 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
47const uint32_t kExifHeaderSize = 14;
msarett0e6274f2016-03-21 08:04:40 -070048const uint32_t kExifMarker = JPEG_APP0 + 1;
msarett0e6274f2016-03-21 08:04:40 -070049
Leon Scroggins IIIb6ab10f2017-10-18 14:42:43 -040050static bool is_orientation_marker(jpeg_marker_struct* marker, SkEncodedOrigin* orientation) {
msarett0e6274f2016-03-21 08:04:40 -070051 if (kExifMarker != marker->marker || marker->data_length < kExifHeaderSize) {
52 return false;
53 }
54
Leon Scroggins III862c1962017-10-02 16:28:49 -040055 constexpr uint8_t kExifSig[] { 'E', 'x', 'i', 'f', '\0' };
Leon Scroggins IIIda3e9ad2018-01-26 15:48:26 -050056 if (memcmp(marker->data, kExifSig, sizeof(kExifSig))) {
msarett0e6274f2016-03-21 08:04:40 -070057 return false;
58 }
59
Leon Scroggins IIIda3e9ad2018-01-26 15:48:26 -050060 // 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
66bool is_orientation_marker(const uint8_t* data, size_t data_length, SkEncodedOrigin* orientation) {
msarett0e6274f2016-03-21 08:04:40 -070067 bool littleEndian;
Leon Scroggins IIIfee7cba2018-02-13 16:41:03 -050068 // We need eight bytes to read the endian marker and the offset, below.
69 if (data_length < 8 || !is_valid_endian_marker(data, &littleEndian)) {
msarett0e6274f2016-03-21 08:04:40 -070070 return false;
71 }
72
73 // Get the offset from the start of the marker.
Leon Scroggins III71d8a572017-12-19 10:14:43 -050074 // Though this only reads four bytes, use a larger int in case it overflows.
Leon Scroggins IIIda3e9ad2018-01-26 15:48:26 -050075 uint64_t offset = get_endian_int(data + 4, littleEndian);
msarett0e6274f2016-03-21 08:04:40 -070076
77 // Require that the marker is at least large enough to contain the number of entries.
Leon Scroggins IIIda3e9ad2018-01-26 15:48:26 -050078 if (data_length < offset + 2) {
msarett0e6274f2016-03-21 08:04:40 -070079 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;
Leon Scroggins IIIda3e9ad2018-01-26 15:48:26 -050085 const auto max = SkTo<uint32_t>((data_length - offset - 2) / kEntrySize);
Leon Scroggins III71d8a572017-12-19 10:14:43 -050086 numEntries = SkTMin(numEntries, max);
msarett0e6274f2016-03-21 08:04:40 -070087
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);
Leon Scroggins IIIb6ab10f2017-10-18 14:42:43 -040099 if (0 < val && val <= kLast_SkEncodedOrigin) {
100 *orientation = (SkEncodedOrigin) val;
msarett0e6274f2016-03-21 08:04:40 -0700101 return true;
102 }
103 }
104 }
105
106 return false;
107}
108
Leon Scroggins IIIb6ab10f2017-10-18 14:42:43 -0400109static SkEncodedOrigin get_exif_orientation(jpeg_decompress_struct* dinfo) {
110 SkEncodedOrigin orientation;
msarett0e6274f2016-03-21 08:04:40 -0700111 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
Leon Scroggins IIIb6ab10f2017-10-18 14:42:43 -0400117 return kDefault_SkEncodedOrigin;
msarett0e6274f2016-03-21 08:04:40 -0700118}
119
120static bool is_icc_marker(jpeg_marker_struct* marker) {
Matt Sarett5df93de2017-03-22 21:52:47 +0000121 if (kICCMarker != marker->marker || marker->data_length < kICCMarkerHeaderSize) {
msarett0e6274f2016-03-21 08:04:40 -0700122 return false;
123 }
124
msarett0e6274f2016-03-21 08:04:40 -0700125 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 */
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400134static std::unique_ptr<SkEncodedInfo::ICCProfile> read_color_profile(jpeg_decompress_struct* dinfo)
135{
msarett0e6274f2016-03-21 08:04:40 -0700136 // 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;
Matt Sarett5df93de2017-03-22 21:52:47 +0000169 SkASSERT(marker->data_length >= kICCMarkerHeaderSize);
170 totalBytes += marker->data_length - kICCMarkerHeaderSize;
msarett0e6274f2016-03-21 08:04:40 -0700171 }
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.
msarett9876ac52016-06-01 14:47:18 -0700180 sk_sp<SkData> iccData = SkData::MakeUninitialized(totalBytes);
181 void* dst = iccData->writable_data();
msarett0e6274f2016-03-21 08:04:40 -0700182 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
Matt Sarett5df93de2017-03-22 21:52:47 +0000189 void* src = SkTAddOffset<void>(marker->data, kICCMarkerHeaderSize);
190 size_t bytes = marker->data_length - kICCMarkerHeaderSize;
msarett0e6274f2016-03-21 08:04:40 -0700191 memcpy(dst, src, bytes);
192 dst = SkTAddOffset<void>(dst, bytes);
193 }
194
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400195 return SkEncodedInfo::ICCProfile::Make(std::move(iccData));
msarett0e6274f2016-03-21 08:04:40 -0700196}
197
Leon Scroggins III588fb042017-07-14 16:32:31 -0400198SkCodec::Result SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400199 JpegDecoderMgr** decoderMgrOut,
200 std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
msarette16b04a2015-04-15 07:32:19 -0700201
202 // Create a JpegDecoderMgr to own all of the decompress information
Ben Wagner145dbcd2016-11-03 14:40:50 -0400203 std::unique_ptr<JpegDecoderMgr> decoderMgr(new JpegDecoderMgr(stream));
msarette16b04a2015-04-15 07:32:19 -0700204
205 // libjpeg errors will be caught and reported here
Chris Dalton3e794592017-12-01 13:11:09 -0700206 skjpeg_error_mgr::AutoPushJmpBuf jmp(decoderMgr->errorMgr());
207 if (setjmp(jmp)) {
Leon Scroggins III588fb042017-07-14 16:32:31 -0400208 return decoderMgr->returnFailure("ReadHeader", kInvalidInput);
msarette16b04a2015-04-15 07:32:19 -0700209 }
210
211 // Initialize the decompress info and the source manager
212 decoderMgr->init();
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400213 auto* dinfo = decoderMgr->dinfo();
msarette16b04a2015-04-15 07:32:19 -0700214
msarett0e6274f2016-03-21 08:04:40 -0700215 // 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) {
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400219 jpeg_save_markers(dinfo, kExifMarker, 0xFFFF);
220 jpeg_save_markers(dinfo, kICCMarker, 0xFFFF);
msarett0e6274f2016-03-21 08:04:40 -0700221 }
222
msarette16b04a2015-04-15 07:32:19 -0700223 // Read the jpeg header
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400224 switch (jpeg_read_header(dinfo, true)) {
Leon Scroggins III588fb042017-07-14 16:32:31 -0400225 case JPEG_HEADER_OK:
226 break;
227 case JPEG_SUSPENDED:
228 return decoderMgr->returnFailure("ReadHeader", kIncompleteInput);
229 default:
230 return decoderMgr->returnFailure("ReadHeader", kInvalidInput);
msarette16b04a2015-04-15 07:32:19 -0700231 }
232
msarett0e6274f2016-03-21 08:04:40 -0700233 if (codecOut) {
msarettc30c4182016-04-20 11:53:35 -0700234 // Get the encoded color type
msarettac6c7502016-04-25 09:30:24 -0700235 SkEncodedInfo::Color color;
236 if (!decoderMgr->getEncodedColor(&color)) {
Leon Scroggins III588fb042017-07-14 16:32:31 -0400237 return kInvalidInput;
msarettc30c4182016-04-20 11:53:35 -0700238 }
msarette16b04a2015-04-15 07:32:19 -0700239
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400240 SkEncodedOrigin orientation = get_exif_orientation(dinfo);
241 auto profile = read_color_profile(dinfo);
242 if (profile) {
243 auto type = profile->profile()->data_color_space;
raftias54761282016-12-01 13:44:07 -0500244 switch (decoderMgr->dinfo()->jpeg_color_space) {
245 case JCS_CMYK:
246 case JCS_YCCK:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400247 if (type != skcms_Signature_CMYK) {
248 profile = nullptr;
Leon Scroggins IIIf78b55c2017-10-31 13:49:14 -0400249 }
raftias54761282016-12-01 13:44:07 -0500250 break;
raftias91db12d2016-12-02 11:56:59 -0500251 case JCS_GRAYSCALE:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400252 if (type != skcms_Signature_Gray &&
253 type != skcms_Signature_RGB)
Leon Scroggins IIIf78b55c2017-10-31 13:49:14 -0400254 {
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400255 profile = nullptr;
Leon Scroggins IIIf78b55c2017-10-31 13:49:14 -0400256 }
Mike Klein503bdcd2017-11-01 08:34:15 -0400257 break;
raftias54761282016-12-01 13:44:07 -0500258 default:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400259 if (type != skcms_Signature_RGB) {
260 profile = nullptr;
Leon Scroggins IIIf78b55c2017-10-31 13:49:14 -0400261 }
raftias54761282016-12-01 13:44:07 -0500262 break;
263 }
msarett9876ac52016-06-01 14:47:18 -0700264 }
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400265 if (!profile) {
266 profile = std::move(defaultColorProfile);
msarettf34cd632016-05-25 10:13:53 -0700267 }
msarett0e6274f2016-03-21 08:04:40 -0700268
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400269 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);
raftiasd737bee2016-12-08 10:53:24 -0500275 *codecOut = codec;
msarette16b04a2015-04-15 07:32:19 -0700276 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700277 SkASSERT(nullptr != decoderMgrOut);
mtklein18300a32016-03-16 13:53:35 -0700278 *decoderMgrOut = decoderMgr.release();
msarette16b04a2015-04-15 07:32:19 -0700279 }
Leon Scroggins III588fb042017-07-14 16:32:31 -0400280 return kSuccess;
msarette16b04a2015-04-15 07:32:19 -0700281}
282
Mike Reedede7bac2017-07-23 15:30:02 -0400283std::unique_ptr<SkCodec> SkJpegCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
284 Result* result) {
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400285 return SkJpegCodec::MakeFromStream(std::move(stream), result,
286 // FIXME: This may not be used. Can we skip creating it?
287 SkEncodedInfo::ICCProfile::MakeSRGB());
Matt Sarettc5eabe72017-02-24 14:51:08 -0500288}
289
Mike Reedede7bac2017-07-23 15:30:02 -0400290std::unique_ptr<SkCodec> SkJpegCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400291 Result* result, std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
halcanary96fcdcc2015-08-27 07:41:13 -0700292 SkCodec* codec = nullptr;
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400293 *result = ReadHeader(stream.get(), &codec, nullptr, std::move(defaultColorProfile));
Leon Scroggins III588fb042017-07-14 16:32:31 -0400294 if (kSuccess == *result) {
msarette16b04a2015-04-15 07:32:19 -0700295 // Codec has taken ownership of the stream, we do not need to delete it
296 SkASSERT(codec);
Mike Reedede7bac2017-07-23 15:30:02 -0400297 stream.release();
298 return std::unique_ptr<SkCodec>(codec);
msarette16b04a2015-04-15 07:32:19 -0700299 }
halcanary96fcdcc2015-08-27 07:41:13 -0700300 return nullptr;
msarette16b04a2015-04-15 07:32:19 -0700301}
302
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400303SkJpegCodec::SkJpegCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream,
304 JpegDecoderMgr* decoderMgr, SkEncodedOrigin origin)
Brian Osmancc956f22018-09-04 19:55:15 +0000305 : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, std::move(stream),
306 origin)
msarette16b04a2015-04-15 07:32:19 -0700307 , fDecoderMgr(decoderMgr)
msarettfbccb592015-09-01 06:43:41 -0700308 , fReadyState(decoderMgr->dinfo()->global_state)
msarett50ce1f22016-07-29 06:23:33 -0700309 , fSwizzleSrcRow(nullptr)
310 , fColorXformSrcRow(nullptr)
msarett91c22b22016-02-22 12:27:46 -0800311 , fSwizzlerSubset(SkIRect::MakeEmpty())
msarette16b04a2015-04-15 07:32:19 -0700312{}
313
314/*
emmaleer8f4ba762015-08-14 07:44:46 -0700315 * Return the row bytes of a particular image type and width
316 */
msarett23e78d32016-02-06 15:58:50 -0800317static size_t get_row_bytes(const j_decompress_ptr dinfo) {
msarett70e418b2016-02-12 12:35:48 -0800318 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
319 dinfo->out_color_components;
emmaleer8f4ba762015-08-14 07:44:46 -0700320 return dinfo->output_width * colorBytes;
321
322}
scroggoe7fc14b2015-10-02 13:14:46 -0700323
324/*
325 * Calculate output dimensions based on the provided factors.
326 *
327 * Not to be used on the actual jpeg_decompress_struct used for decoding, since it will
328 * incorrectly modify num_components.
329 */
330void calc_output_dimensions(jpeg_decompress_struct* dinfo, unsigned int num, unsigned int denom) {
331 dinfo->num_components = 0;
332 dinfo->scale_num = num;
333 dinfo->scale_denom = denom;
334 jpeg_calc_output_dimensions(dinfo);
335}
336
emmaleer8f4ba762015-08-14 07:44:46 -0700337/*
msarette16b04a2015-04-15 07:32:19 -0700338 * Return a valid set of output dimensions for this decoder, given an input scale
339 */
340SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
msarett1c8a5872015-07-07 08:50:01 -0700341 // 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
342 // support these as well
scroggoe7fc14b2015-10-02 13:14:46 -0700343 unsigned int num;
344 unsigned int denom = 8;
msarettfdb47572015-10-13 12:50:14 -0700345 if (desiredScale >= 0.9375) {
msarett1c8a5872015-07-07 08:50:01 -0700346 num = 8;
msarettfdb47572015-10-13 12:50:14 -0700347 } else if (desiredScale >= 0.8125) {
msarett1c8a5872015-07-07 08:50:01 -0700348 num = 7;
msarettfdb47572015-10-13 12:50:14 -0700349 } else if (desiredScale >= 0.6875f) {
msarett1c8a5872015-07-07 08:50:01 -0700350 num = 6;
msarettfdb47572015-10-13 12:50:14 -0700351 } else if (desiredScale >= 0.5625f) {
msarett1c8a5872015-07-07 08:50:01 -0700352 num = 5;
msarettfdb47572015-10-13 12:50:14 -0700353 } else if (desiredScale >= 0.4375f) {
msarett1c8a5872015-07-07 08:50:01 -0700354 num = 4;
msarettfdb47572015-10-13 12:50:14 -0700355 } else if (desiredScale >= 0.3125f) {
msarett1c8a5872015-07-07 08:50:01 -0700356 num = 3;
msarettfdb47572015-10-13 12:50:14 -0700357 } else if (desiredScale >= 0.1875f) {
msarett1c8a5872015-07-07 08:50:01 -0700358 num = 2;
msarette16b04a2015-04-15 07:32:19 -0700359 } else {
msarett1c8a5872015-07-07 08:50:01 -0700360 num = 1;
msarette16b04a2015-04-15 07:32:19 -0700361 }
362
363 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
364 jpeg_decompress_struct dinfo;
mtkleinf7aaadb2015-04-16 06:09:27 -0700365 sk_bzero(&dinfo, sizeof(dinfo));
msarette16b04a2015-04-15 07:32:19 -0700366 dinfo.image_width = this->getInfo().width();
367 dinfo.image_height = this->getInfo().height();
msarettfbccb592015-09-01 06:43:41 -0700368 dinfo.global_state = fReadyState;
scroggoe7fc14b2015-10-02 13:14:46 -0700369 calc_output_dimensions(&dinfo, num, denom);
msarette16b04a2015-04-15 07:32:19 -0700370
371 // Return the calculated output dimensions for the given scale
372 return SkISize::Make(dinfo.output_width, dinfo.output_height);
373}
374
scroggob427db12015-08-12 07:24:13 -0700375bool SkJpegCodec::onRewind() {
halcanary96fcdcc2015-08-27 07:41:13 -0700376 JpegDecoderMgr* decoderMgr = nullptr;
Leon Scroggins III588fb042017-07-14 16:32:31 -0400377 if (kSuccess != ReadHeader(this->stream(), nullptr, &decoderMgr, nullptr)) {
msarett50ce1f22016-07-29 06:23:33 -0700378 return fDecoderMgr->returnFalse("onRewind");
msarett97fdea62015-04-29 08:17:15 -0700379 }
halcanary96fcdcc2015-08-27 07:41:13 -0700380 SkASSERT(nullptr != decoderMgr);
scroggob427db12015-08-12 07:24:13 -0700381 fDecoderMgr.reset(decoderMgr);
msarett2812f032016-07-18 15:56:08 -0700382
383 fSwizzler.reset(nullptr);
msarett50ce1f22016-07-29 06:23:33 -0700384 fSwizzleSrcRow = nullptr;
385 fColorXformSrcRow = nullptr;
msarett2812f032016-07-18 15:56:08 -0700386 fStorage.reset();
387
scroggob427db12015-08-12 07:24:13 -0700388 return true;
msarett97fdea62015-04-29 08:17:15 -0700389}
390
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400391bool SkJpegCodec::conversionSupported(const SkImageInfo& dstInfo, SkColorType srcCT,
392 bool srcIsOpaque, bool needsColorXform) {
393 SkASSERT(srcIsOpaque);
394
msarett50ce1f22016-07-29 06:23:33 -0700395 if (kUnknown_SkAlphaType == dstInfo.alphaType()) {
msarett1c8a5872015-07-07 08:50:01 -0700396 return false;
397 }
398
msarett50ce1f22016-07-29 06:23:33 -0700399 if (kOpaque_SkAlphaType != dstInfo.alphaType()) {
scroggoc5560be2016-02-03 09:42:42 -0800400 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
401 "- it is being decoded as non-opaque, which will draw slower\n");
402 }
403
msarett50ce1f22016-07-29 06:23:33 -0700404 J_COLOR_SPACE encodedColorType = fDecoderMgr->dinfo()->jpeg_color_space;
msarett1c8a5872015-07-07 08:50:01 -0700405
406 // Check for valid color types and set the output color space
msarett50ce1f22016-07-29 06:23:33 -0700407 switch (dstInfo.colorType()) {
msarett34e0ec42016-04-22 16:27:24 -0700408 case kRGBA_8888_SkColorType:
nagarajan.n08cda142017-09-07 20:03:29 +0530409 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
410 break;
msarett34e0ec42016-04-22 16:27:24 -0700411 case kBGRA_8888_SkColorType:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400412 if (needsColorXform) {
Matt Sarett562e6812016-11-08 16:13:43 -0500413 // Always using RGBA as the input format for color xforms makes the
414 // implementation a little simpler.
msarett50ce1f22016-07-29 06:23:33 -0700415 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
msarett34e0ec42016-04-22 16:27:24 -0700416 } else {
msarettf25bff92016-07-21 12:00:24 -0700417 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
msarett1c8a5872015-07-07 08:50:01 -0700418 }
nagarajan.n08cda142017-09-07 20:03:29 +0530419 break;
msarett1c8a5872015-07-07 08:50:01 -0700420 case kRGB_565_SkColorType:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400421 if (needsColorXform) {
Matt Sarett3725f0a2017-03-28 14:34:20 -0400422 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
msarett1c8a5872015-07-07 08:50:01 -0700423 } else {
msarett8ff6ca62015-09-18 12:06:04 -0700424 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
msarett1c8a5872015-07-07 08:50:01 -0700425 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
426 }
nagarajan.n08cda142017-09-07 20:03:29 +0530427 break;
msarett1c8a5872015-07-07 08:50:01 -0700428 case kGray_8_SkColorType:
Brian Osmancc956f22018-09-04 19:55:15 +0000429 SkASSERT(!needsColorXform);
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400430 if (JCS_GRAYSCALE != encodedColorType) {
msarett39979d82016-07-28 17:11:18 -0700431 return false;
msarett50ce1f22016-07-29 06:23:33 -0700432 }
433
Brian Osmancc956f22018-09-04 19:55:15 +0000434 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
nagarajan.n08cda142017-09-07 20:03:29 +0530435 break;
msarett50ce1f22016-07-29 06:23:33 -0700436 case kRGBA_F16_SkColorType:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400437 SkASSERT(needsColorXform);
nagarajan.n08cda142017-09-07 20:03:29 +0530438 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
439 break;
msarett1c8a5872015-07-07 08:50:01 -0700440 default:
441 return false;
442 }
nagarajan.n08cda142017-09-07 20:03:29 +0530443
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;
msarett1c8a5872015-07-07 08:50:01 -0700451}
452
453/*
mtkleine721a8e2016-02-06 19:12:23 -0800454 * Checks if we can natively scale to the requested dimensions and natively scales the
emmaleer8f4ba762015-08-14 07:44:46 -0700455 * dimensions if possible
msarett97fdea62015-04-29 08:17:15 -0700456 */
scroggoe7fc14b2015-10-02 13:14:46 -0700457bool SkJpegCodec::onDimensionsSupported(const SkISize& size) {
Chris Dalton3e794592017-12-01 13:11:09 -0700458 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
459 if (setjmp(jmp)) {
msarett50ce1f22016-07-29 06:23:33 -0700460 return fDecoderMgr->returnFalse("onDimensionsSupported");
scroggoe7fc14b2015-10-02 13:14:46 -0700461 }
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
msarett1c8a5872015-07-07 08:50:01 -0700474 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
scroggoe7fc14b2015-10-02 13:14:46 -0700475 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) {
msarett97fdea62015-04-29 08:17:15 -0700479
480 // Return a failure if we have tried all of the possible scales
scroggoe7fc14b2015-10-02 13:14:46 -0700481 if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
emmaleer8f4ba762015-08-14 07:44:46 -0700482 return false;
msarett97fdea62015-04-29 08:17:15 -0700483 }
484
485 // Try the next scale
scroggoe7fc14b2015-10-02 13:14:46 -0700486 num -= 1;
487 calc_output_dimensions(&dinfo, num, denom);
msarett97fdea62015-04-29 08:17:15 -0700488 }
scroggoe7fc14b2015-10-02 13:14:46 -0700489
490 fDecoderMgr->dinfo()->scale_num = num;
491 fDecoderMgr->dinfo()->scale_denom = denom;
msarett97fdea62015-04-29 08:17:15 -0700492 return true;
493}
494
Matt Sarettc8c901f2017-01-24 16:16:33 -0500495int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
496 const Options& opts) {
msarett50ce1f22016-07-29 06:23:33 -0700497 // Set the jump location for libjpeg-turbo errors
Chris Dalton3e794592017-12-01 13:11:09 -0700498 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
499 if (setjmp(jmp)) {
msarett50ce1f22016-07-29 06:23:33 -0700500 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
Brian Osmancc956f22018-09-04 19:55:15 +0000508 // we cannot color xform "in place" (many times we can, but not when the dst is F16).
Matt Sarett313c4632016-10-20 12:35:23 -0400509 // In this case, we will color xform from fColorXformSrcRow into the dst.
msarett50ce1f22016-07-29 06:23:33 -0700510 JSAMPLE* decodeDst = (JSAMPLE*) dst;
511 uint32_t* swizzleDst = (uint32_t*) dst;
512 size_t decodeDstRowBytes = rowBytes;
513 size_t swizzleDstRowBytes = rowBytes;
Matt Sarettc8c901f2017-01-24 16:16:33 -0500514 int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width();
msarett50ce1f22016-07-29 06:23:33 -0700515 if (fSwizzleSrcRow && fColorXformSrcRow) {
516 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
517 swizzleDst = fColorXformSrcRow;
518 decodeDstRowBytes = 0;
519 swizzleDstRowBytes = 0;
msarett35bb74b2016-08-22 07:41:28 -0700520 dstWidth = fSwizzler->swizzleWidth();
msarett50ce1f22016-07-29 06:23:33 -0700521 } 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;
msarett35bb74b2016-08-22 07:41:28 -0700529 dstWidth = fSwizzler->swizzleWidth();
msarett50ce1f22016-07-29 06:23:33 -0700530 }
531
532 for (int y = 0; y < count; y++) {
533 uint32_t lines = jpeg_read_scanlines(fDecoderMgr->dinfo(), &decodeDst, 1);
msarett50ce1f22016-07-29 06:23:33 -0700534 if (0 == lines) {
535 return y;
536 }
537
538 if (fSwizzler) {
539 fSwizzler->swizzle(swizzleDst, decodeDst);
540 }
541
Matt Sarett313c4632016-10-20 12:35:23 -0400542 if (this->colorXform()) {
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400543 this->applyColorXform(dst, swizzleDst, dstWidth);
msarett50ce1f22016-07-29 06:23:33 -0700544 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
msarett97fdea62015-04-29 08:17:15 -0700554/*
Matt Sarett7f15b682017-02-24 17:22:09 -0500555 * This is a bit tricky. We only need the swizzler to do format conversion if the jpeg is
556 * encoded as CMYK.
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400557 * And even then we still may not need it. If the jpeg has a CMYK color profile and a color
Matt Sarett7f15b682017-02-24 17:22:09 -0500558 * xform, the color xform will handle the CMYK->RGB conversion.
559 */
560static inline bool needs_swizzler_to_convert_from_cmyk(J_COLOR_SPACE jpegColorType,
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400561 const skcms_ICCProfile* srcProfile,
562 bool hasColorSpaceXform) {
Matt Sarett7f15b682017-02-24 17:22:09 -0500563 if (JCS_CMYK != jpegColorType) {
564 return false;
565 }
566
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400567 bool hasCMYKColorSpace = srcProfile && srcProfile->data_color_space == skcms_Signature_CMYK;
Matt Sarett7f15b682017-02-24 17:22:09 -0500568 return !hasCMYKColorSpace || !hasColorSpaceXform;
569}
570
571/*
msarette16b04a2015-04-15 07:32:19 -0700572 * Performs the jpeg decode
573 */
574SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
575 void* dst, size_t dstRowBytes,
Leon Scroggins571b30f2017-07-11 17:35:31 +0000576 const Options& options,
msarette6dd0042015-10-09 11:07:34 -0700577 int* rowsDecoded) {
scroggob636b452015-07-22 07:16:20 -0700578 if (options.fSubset) {
579 // Subsets are not supported.
580 return kUnimplemented;
581 }
582
msarette16b04a2015-04-15 07:32:19 -0700583 // Get a pointer to the decompress info since we will use it quite frequently
584 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
585
586 // Set the jump location for libjpeg errors
Chris Dalton3e794592017-12-01 13:11:09 -0700587 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
588 if (setjmp(jmp)) {
msarette16b04a2015-04-15 07:32:19 -0700589 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
590 }
591
msarettfbccb592015-09-01 06:43:41 -0700592 if (!jpeg_start_decompress(dinfo)) {
msarette16b04a2015-04-15 07:32:19 -0700593 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
594 }
595
msarett1c8a5872015-07-07 08:50:01 -0700596 // The recommended output buffer height should always be 1 in high quality modes.
597 // If it's not, we want to know because it means our strategy is not optimal.
598 SkASSERT(1 == dinfo->rec_outbuf_height);
msarette16b04a2015-04-15 07:32:19 -0700599
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400600 if (needs_swizzler_to_convert_from_cmyk(dinfo->out_color_space,
601 this->getEncodedInfo().profile(), this->colorXform())) {
Matt Sarett7f15b682017-02-24 17:22:09 -0500602 this->initializeSwizzler(dstInfo, options, true);
scroggoef27d892015-10-23 09:29:22 -0700603 }
604
msarett50ce1f22016-07-29 06:23:33 -0700605 this->allocateStorage(dstInfo);
scroggoef27d892015-10-23 09:29:22 -0700606
Matt Sarettc8c901f2017-01-24 16:16:33 -0500607 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options);
msarett50ce1f22016-07-29 06:23:33 -0700608 if (rows < dstInfo.height()) {
609 *rowsDecoded = rows;
610 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
msarette16b04a2015-04-15 07:32:19 -0700611 }
msarette16b04a2015-04-15 07:32:19 -0700612
613 return kSuccess;
614}
msarett97fdea62015-04-29 08:17:15 -0700615
msarett50ce1f22016-07-29 06:23:33 -0700616void SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) {
msarett35bb74b2016-08-22 07:41:28 -0700617 int dstWidth = dstInfo.width();
618
msarett50ce1f22016-07-29 06:23:33 -0700619 size_t swizzleBytes = 0;
620 if (fSwizzler) {
621 swizzleBytes = get_row_bytes(fDecoderMgr->dinfo());
msarett35bb74b2016-08-22 07:41:28 -0700622 dstWidth = fSwizzler->swizzleWidth();
Matt Sarett313c4632016-10-20 12:35:23 -0400623 SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes));
msarett50ce1f22016-07-29 06:23:33 -0700624 }
625
626 size_t xformBytes = 0;
Brian Osmancc956f22018-09-04 19:55:15 +0000627 if (this->colorXform() && (kRGBA_F16_SkColorType == dstInfo.colorType() ||
628 kRGB_565_SkColorType == dstInfo.colorType())) {
msarett35bb74b2016-08-22 07:41:28 -0700629 xformBytes = dstWidth * sizeof(uint32_t);
msarett50ce1f22016-07-29 06:23:33 -0700630 }
631
632 size_t totalBytes = swizzleBytes + xformBytes;
633 if (totalBytes > 0) {
634 fStorage.reset(totalBytes);
635 fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
636 fColorXformSrcRow = (xformBytes > 0) ?
637 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
638 }
639}
640
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400641static SkEncodedInfo make_info(const SkEncodedInfo& orig, bool needsCMYKToRGB) {
642 auto color = needsCMYKToRGB ? SkEncodedInfo::kInvertedCMYK_Color
643 : orig.color();
644 // The swizzler does not need the width or height
645 return SkEncodedInfo::Make(0, 0, color, orig.alpha(), orig.bitsPerComponent());
646}
647
Matt Sarett7f15b682017-02-24 17:22:09 -0500648void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
649 bool needsCMYKToRGB) {
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400650 SkEncodedInfo swizzlerInfo = make_info(this->getEncodedInfo(), needsCMYKToRGB);
msarett70e418b2016-02-12 12:35:48 -0800651
msarett91c22b22016-02-22 12:27:46 -0800652 Options swizzlerOptions = options;
653 if (options.fSubset) {
654 // Use fSwizzlerSubset if this is a subset decode. This is necessary in the case
655 // where libjpeg-turbo provides a subset and then we need to subset it further.
656 // Also, verify that fSwizzlerSubset is initialized and valid.
657 SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
658 fSwizzlerSubset.width() == options.fSubset->width());
659 swizzlerOptions.fSubset = &fSwizzlerSubset;
660 }
Matt Sarett09a1c082017-02-01 15:34:22 -0800661
662 SkImageInfo swizzlerDstInfo = dstInfo;
Matt Sarett7f15b682017-02-24 17:22:09 -0500663 if (this->colorXform()) {
664 // The color xform will be expecting RGBA 8888 input.
Matt Sarett09a1c082017-02-01 15:34:22 -0800665 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
666 }
667
668 fSwizzler.reset(SkSwizzler::CreateSwizzler(swizzlerInfo, nullptr, swizzlerDstInfo,
Matt Sarett7f15b682017-02-24 17:22:09 -0500669 swizzlerOptions, nullptr, !needsCMYKToRGB));
msarettb30d6982016-02-15 10:18:45 -0800670 SkASSERT(fSwizzler);
msarett50ce1f22016-07-29 06:23:33 -0700671}
672
msarettfdb47572015-10-13 12:50:14 -0700673SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
674 if (!createIfNecessary || fSwizzler) {
msarett50ce1f22016-07-29 06:23:33 -0700675 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
Ben Wagner145dbcd2016-11-03 14:40:50 -0400676 return fSwizzler.get();
msarettfdb47572015-10-13 12:50:14 -0700677 }
678
Matt Sarett7f15b682017-02-24 17:22:09 -0500679 bool needsCMYKToRGB = needs_swizzler_to_convert_from_cmyk(
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400680 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
681 this->colorXform());
Matt Sarett7f15b682017-02-24 17:22:09 -0500682 this->initializeSwizzler(this->dstInfo(), this->options(), needsCMYKToRGB);
msarett50ce1f22016-07-29 06:23:33 -0700683 this->allocateStorage(this->dstInfo());
Ben Wagner145dbcd2016-11-03 14:40:50 -0400684 return fSwizzler.get();
scroggo46c57472015-09-30 08:57:13 -0700685}
scroggo1c005e42015-08-04 09:24:45 -0700686
scroggo46c57472015-09-30 08:57:13 -0700687SkCodec::Result SkJpegCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
Leon Scroggins571b30f2017-07-11 17:35:31 +0000688 const Options& options) {
scroggo46c57472015-09-30 08:57:13 -0700689 // Set the jump location for libjpeg errors
Chris Dalton3e794592017-12-01 13:11:09 -0700690 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
691 if (setjmp(jmp)) {
scroggo46c57472015-09-30 08:57:13 -0700692 SkCodecPrintf("setjmp: Error from libjpeg\n");
693 return kInvalidInput;
694 }
695
scroggo46c57472015-09-30 08:57:13 -0700696 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
697 SkCodecPrintf("start decompress failed\n");
698 return kInvalidInput;
699 }
700
Matt Sarett7f15b682017-02-24 17:22:09 -0500701 bool needsCMYKToRGB = needs_swizzler_to_convert_from_cmyk(
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400702 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
703 this->colorXform());
msarett91c22b22016-02-22 12:27:46 -0800704 if (options.fSubset) {
705 uint32_t startX = options.fSubset->x();
706 uint32_t width = options.fSubset->width();
707
708 // libjpeg-turbo may need to align startX to a multiple of the IDCT
709 // block size. If this is the case, it will decrease the value of
710 // startX to the appropriate alignment and also increase the value
711 // of width so that the right edge of the requested subset remains
712 // the same.
713 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &width);
714
715 SkASSERT(startX <= (uint32_t) options.fSubset->x());
716 SkASSERT(width >= (uint32_t) options.fSubset->width());
717 SkASSERT(startX + width >= (uint32_t) options.fSubset->right());
718
719 // Instruct the swizzler (if it is necessary) to further subset the
720 // output provided by libjpeg-turbo.
721 //
722 // We set this here (rather than in the if statement below), so that
723 // if (1) we don't need a swizzler for the subset, and (2) we need a
724 // swizzler for CMYK, the swizzler will still use the proper subset
725 // dimensions.
726 //
727 // Note that the swizzler will ignore the y and height parameters of
728 // the subset. Since the scanline decoder (and the swizzler) handle
729 // one row at a time, only the subsetting in the x-dimension matters.
730 fSwizzlerSubset.setXYWH(options.fSubset->x() - startX, 0,
731 options.fSubset->width(), options.fSubset->height());
732
733 // We will need a swizzler if libjpeg-turbo cannot provide the exact
734 // subset that we request.
735 if (startX != (uint32_t) options.fSubset->x() ||
736 width != (uint32_t) options.fSubset->width()) {
Matt Sarett7f15b682017-02-24 17:22:09 -0500737 this->initializeSwizzler(dstInfo, options, needsCMYKToRGB);
msarett91c22b22016-02-22 12:27:46 -0800738 }
739 }
740
741 // Make sure we have a swizzler if we are converting from CMYK.
Matt Sarett7f15b682017-02-24 17:22:09 -0500742 if (!fSwizzler && needsCMYKToRGB) {
743 this->initializeSwizzler(dstInfo, options, true);
msarett91c22b22016-02-22 12:27:46 -0800744 }
msarettfdb47572015-10-13 12:50:14 -0700745
msarett50ce1f22016-07-29 06:23:33 -0700746 this->allocateStorage(dstInfo);
747
scroggo46c57472015-09-30 08:57:13 -0700748 return kSuccess;
749}
750
mtkleine721a8e2016-02-06 19:12:23 -0800751int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
Matt Sarettc8c901f2017-01-24 16:16:33 -0500752 int rows = this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options());
msarett50ce1f22016-07-29 06:23:33 -0700753 if (rows < count) {
754 // This allows us to skip calling jpeg_finish_decompress().
755 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
scroggo46c57472015-09-30 08:57:13 -0700756 }
757
msarett50ce1f22016-07-29 06:23:33 -0700758 return rows;
scroggo46c57472015-09-30 08:57:13 -0700759}
msarett97fdea62015-04-29 08:17:15 -0700760
msarette6dd0042015-10-09 11:07:34 -0700761bool SkJpegCodec::onSkipScanlines(int count) {
scroggo46c57472015-09-30 08:57:13 -0700762 // Set the jump location for libjpeg errors
Chris Dalton3e794592017-12-01 13:11:09 -0700763 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
764 if (setjmp(jmp)) {
msarett50ce1f22016-07-29 06:23:33 -0700765 return fDecoderMgr->returnFalse("onSkipScanlines");
msarett97fdea62015-04-29 08:17:15 -0700766 }
767
msarettf724b992015-10-15 06:41:06 -0700768 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
msarett97fdea62015-04-29 08:17:15 -0700769}
msarettb714fb02016-01-22 14:46:42 -0800770
771static bool is_yuv_supported(jpeg_decompress_struct* dinfo) {
772 // Scaling is not supported in raw data mode.
773 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
774
775 // I can't imagine that this would ever change, but we do depend on it.
776 static_assert(8 == DCTSIZE, "DCTSIZE (defined in jpeg library) should always be 8.");
777
778 if (JCS_YCbCr != dinfo->jpeg_color_space) {
779 return false;
780 }
781
782 SkASSERT(3 == dinfo->num_components);
783 SkASSERT(dinfo->comp_info);
784
785 // It is possible to perform a YUV decode for any combination of
786 // horizontal and vertical sampling that is supported by
787 // libjpeg/libjpeg-turbo. However, we will start by supporting only the
788 // common cases (where U and V have samp_factors of one).
789 //
790 // The definition of samp_factor is kind of the opposite of what SkCodec
791 // thinks of as a sampling factor. samp_factor is essentially a
792 // multiplier, and the larger the samp_factor is, the more samples that
793 // there will be. Ex:
794 // U_plane_width = image_width * (U_h_samp_factor / max_h_samp_factor)
795 //
796 // Supporting cases where the samp_factors for U or V were larger than
797 // that of Y would be an extremely difficult change, given that clients
798 // allocate memory as if the size of the Y plane is always the size of the
799 // image. However, this case is very, very rare.
msarett7c87cf42016-03-04 06:23:20 -0800800 if ((1 != dinfo->comp_info[1].h_samp_factor) ||
801 (1 != dinfo->comp_info[1].v_samp_factor) ||
802 (1 != dinfo->comp_info[2].h_samp_factor) ||
803 (1 != dinfo->comp_info[2].v_samp_factor))
804 {
msarettb714fb02016-01-22 14:46:42 -0800805 return false;
806 }
807
808 // Support all common cases of Y samp_factors.
809 // TODO (msarett): As mentioned above, it would be possible to support
810 // more combinations of samp_factors. The issues are:
811 // (1) Are there actually any images that are not covered
812 // by these cases?
813 // (2) How much complexity would be added to the
814 // implementation in order to support these rare
815 // cases?
816 int hSampY = dinfo->comp_info[0].h_samp_factor;
817 int vSampY = dinfo->comp_info[0].v_samp_factor;
818 return (1 == hSampY && 1 == vSampY) ||
819 (2 == hSampY && 1 == vSampY) ||
820 (2 == hSampY && 2 == vSampY) ||
821 (1 == hSampY && 2 == vSampY) ||
822 (4 == hSampY && 1 == vSampY) ||
823 (4 == hSampY && 2 == vSampY);
824}
825
msarett4984c3c2016-03-10 05:44:43 -0800826bool SkJpegCodec::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
msarettb714fb02016-01-22 14:46:42 -0800827 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
828 if (!is_yuv_supported(dinfo)) {
829 return false;
830 }
831
nagarajan.nb1854fa2017-07-19 19:53:21 +0530832 jpeg_component_info * comp_info = dinfo->comp_info;
833 for (auto i : { SkYUVSizeInfo::kY, SkYUVSizeInfo::kU, SkYUVSizeInfo::kV }) {
834 sizeInfo->fSizes[i].set(comp_info[i].downsampled_width, comp_info[i].downsampled_height);
835 sizeInfo->fWidthBytes[i] = comp_info[i].width_in_blocks * DCTSIZE;
836 }
msarettb714fb02016-01-22 14:46:42 -0800837
838 if (colorSpace) {
839 *colorSpace = kJPEG_SkYUVColorSpace;
840 }
841
842 return true;
843}
844
msarett4984c3c2016-03-10 05:44:43 -0800845SkCodec::Result SkJpegCodec::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
846 SkYUVSizeInfo defaultInfo;
msarettb714fb02016-01-22 14:46:42 -0800847
848 // This will check is_yuv_supported(), so we don't need to here.
849 bool supportsYUV = this->onQueryYUV8(&defaultInfo, nullptr);
msarett4984c3c2016-03-10 05:44:43 -0800850 if (!supportsYUV ||
851 sizeInfo.fSizes[SkYUVSizeInfo::kY] != defaultInfo.fSizes[SkYUVSizeInfo::kY] ||
852 sizeInfo.fSizes[SkYUVSizeInfo::kU] != defaultInfo.fSizes[SkYUVSizeInfo::kU] ||
853 sizeInfo.fSizes[SkYUVSizeInfo::kV] != defaultInfo.fSizes[SkYUVSizeInfo::kV] ||
854 sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] < defaultInfo.fWidthBytes[SkYUVSizeInfo::kY] ||
855 sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] < defaultInfo.fWidthBytes[SkYUVSizeInfo::kU] ||
856 sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] < defaultInfo.fWidthBytes[SkYUVSizeInfo::kV]) {
msarettb714fb02016-01-22 14:46:42 -0800857 return fDecoderMgr->returnFailure("onGetYUV8Planes", kInvalidInput);
858 }
859
860 // Set the jump location for libjpeg errors
Chris Dalton3e794592017-12-01 13:11:09 -0700861 skjpeg_error_mgr::AutoPushJmpBuf jmp(fDecoderMgr->errorMgr());
862 if (setjmp(jmp)) {
msarettb714fb02016-01-22 14:46:42 -0800863 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
864 }
865
866 // Get a pointer to the decompress info since we will use it quite frequently
867 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
868
869 dinfo->raw_data_out = TRUE;
870 if (!jpeg_start_decompress(dinfo)) {
871 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
872 }
873
874 // A previous implementation claims that the return value of is_yuv_supported()
875 // may change after calling jpeg_start_decompress(). It looks to me like this
876 // was caused by a bug in the old code, but we'll be safe and check here.
877 SkASSERT(is_yuv_supported(dinfo));
878
879 // Currently, we require that the Y plane dimensions match the image dimensions
880 // and that the U and V planes are the same dimensions.
msarett4984c3c2016-03-10 05:44:43 -0800881 SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU] == sizeInfo.fSizes[SkYUVSizeInfo::kV]);
882 SkASSERT((uint32_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].width() == dinfo->output_width &&
883 (uint32_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].height() == dinfo->output_height);
msarettb714fb02016-01-22 14:46:42 -0800884
885 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has
886 // a 2-D array of pixels for each of the components (Y, U, V) in the image.
887 // Cheat Sheet:
888 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE***
889 JSAMPARRAY yuv[3];
890
891 // Set aside enough space for pointers to rows of Y, U, and V.
892 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
893 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE)
894 yuv[1] = &rowptrs[2 * DCTSIZE]; // U rows (DCTSIZE)
895 yuv[2] = &rowptrs[3 * DCTSIZE]; // V rows (DCTSIZE)
896
897 // Initialize rowptrs.
898 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
899 for (int i = 0; i < numYRowsPerBlock; i++) {
msarett4984c3c2016-03-10 05:44:43 -0800900 rowptrs[i] = SkTAddOffset<JSAMPLE>(planes[SkYUVSizeInfo::kY],
901 i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kY]);
msarettb714fb02016-01-22 14:46:42 -0800902 }
903 for (int i = 0; i < DCTSIZE; i++) {
msarett4984c3c2016-03-10 05:44:43 -0800904 rowptrs[i + 2 * DCTSIZE] = SkTAddOffset<JSAMPLE>(planes[SkYUVSizeInfo::kU],
905 i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kU]);
906 rowptrs[i + 3 * DCTSIZE] = SkTAddOffset<JSAMPLE>(planes[SkYUVSizeInfo::kV],
907 i * sizeInfo.fWidthBytes[SkYUVSizeInfo::kV]);
msarettb714fb02016-01-22 14:46:42 -0800908 }
909
910 // After each loop iteration, we will increment pointers to Y, U, and V.
msarett4984c3c2016-03-10 05:44:43 -0800911 size_t blockIncrementY = numYRowsPerBlock * sizeInfo.fWidthBytes[SkYUVSizeInfo::kY];
912 size_t blockIncrementU = DCTSIZE * sizeInfo.fWidthBytes[SkYUVSizeInfo::kU];
913 size_t blockIncrementV = DCTSIZE * sizeInfo.fWidthBytes[SkYUVSizeInfo::kV];
msarettb714fb02016-01-22 14:46:42 -0800914
915 uint32_t numRowsPerBlock = numYRowsPerBlock;
916
917 // We intentionally round down here, as this first loop will only handle
918 // full block rows. As a special case at the end, we will handle any
919 // remaining rows that do not make up a full block.
920 const int numIters = dinfo->output_height / numRowsPerBlock;
921 for (int i = 0; i < numIters; i++) {
922 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
923 if (linesRead < numRowsPerBlock) {
924 // FIXME: Handle incomplete YUV decodes without signalling an error.
925 return kInvalidInput;
926 }
927
928 // Update rowptrs.
929 for (int i = 0; i < numYRowsPerBlock; i++) {
930 rowptrs[i] += blockIncrementY;
931 }
932 for (int i = 0; i < DCTSIZE; i++) {
933 rowptrs[i + 2 * DCTSIZE] += blockIncrementU;
934 rowptrs[i + 3 * DCTSIZE] += blockIncrementV;
935 }
936 }
937
938 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
939 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
940 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
941 if (remainingRows > 0) {
942 // libjpeg-turbo needs memory to be padded by the block sizes. We will fulfill
943 // this requirement using a dummy row buffer.
944 // FIXME: Should SkCodec have an extra memory buffer that can be shared among
945 // all of the implementations that use temporary/garbage memory?
msarett4984c3c2016-03-10 05:44:43 -0800946 SkAutoTMalloc<JSAMPLE> dummyRow(sizeInfo.fWidthBytes[SkYUVSizeInfo::kY]);
msarettb714fb02016-01-22 14:46:42 -0800947 for (int i = remainingRows; i < numYRowsPerBlock; i++) {
948 rowptrs[i] = dummyRow.get();
949 }
950 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
951 for (int i = remainingUVRows; i < DCTSIZE; i++) {
952 rowptrs[i + 2 * DCTSIZE] = dummyRow.get();
953 rowptrs[i + 3 * DCTSIZE] = dummyRow.get();
954 }
955
956 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
957 if (linesRead < remainingRows) {
958 // FIXME: Handle incomplete YUV decodes without signalling an error.
959 return kInvalidInput;
960 }
961 }
962
963 return kSuccess;
964}
Hal Canary83e0f1b2018-04-05 16:58:41 -0400965
966// This function is declared in SkJpegInfo.h, used by SkPDF.
967bool SkGetJpegInfo(const void* data, size_t len,
968 SkISize* size,
969 SkEncodedInfo::Color* colorType,
970 SkEncodedOrigin* orientation) {
971 if (!SkJpegCodec::IsJpeg(data, len)) {
972 return false;
973 }
974
975 SkMemoryStream stream(data, len);
976 JpegDecoderMgr decoderMgr(&stream);
977 // libjpeg errors will be caught and reported here
978 skjpeg_error_mgr::AutoPushJmpBuf jmp(decoderMgr.errorMgr());
979 if (setjmp(jmp)) {
980 return false;
981 }
982 decoderMgr.init();
983 jpeg_decompress_struct* dinfo = decoderMgr.dinfo();
984 jpeg_save_markers(dinfo, kExifMarker, 0xFFFF);
985 jpeg_save_markers(dinfo, kICCMarker, 0xFFFF);
986 if (JPEG_HEADER_OK != jpeg_read_header(dinfo, true)) {
987 return false;
988 }
989 SkEncodedInfo::Color encodedColorType;
990 if (!decoderMgr.getEncodedColor(&encodedColorType)) {
991 return false; // Unable to interpret the color channels as colors.
992 }
993 if (colorType) {
994 *colorType = encodedColorType;
995 }
996 if (orientation) {
997 *orientation = get_exif_orientation(dinfo);
998 }
999 if (size) {
1000 *size = {SkToS32(dinfo->image_width), SkToS32(dinfo->image_height)};
1001 }
1002 return true;
1003}