blob: c094d50a3bbac8c7f9239c32c811a95b6b48ebbb [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
8#include "SkCodec.h"
9#include "SkJpegCodec.h"
10#include "SkJpegDecoderMgr.h"
mtklein525e90a2015-06-18 09:58:57 -070011#include "SkJpegUtility_codec.h"
msarette16b04a2015-04-15 07:32:19 -070012#include "SkCodecPriv.h"
13#include "SkColorPriv.h"
emmaleerb1579172015-08-14 05:46:08 -070014#include "SkScaledCodec.h"
scroggoeb602a52015-07-09 08:16:03 -070015#include "SkScanlineDecoder.h"
msarette16b04a2015-04-15 07:32:19 -070016#include "SkStream.h"
17#include "SkTemplates.h"
18#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>
22
23extern "C" {
msarett1c8a5872015-07-07 08:50:01 -070024 #include "jpeglibmangler.h"
msarette16b04a2015-04-15 07:32:19 -070025 #include "jerror.h"
msarette16b04a2015-04-15 07:32:19 -070026 #include "jpegint.h"
27 #include "jpeglib.h"
28}
29
msarette16b04a2015-04-15 07:32:19 -070030/*
msarett1c8a5872015-07-07 08:50:01 -070031 * Convert a row of CMYK samples to RGBA in place.
msarette16b04a2015-04-15 07:32:19 -070032 * Note that this method moves the row pointer.
33 * @param width the number of pixels in the row that is being converted
34 * CMYK is stored as four bytes per pixel
35 */
msarett1c8a5872015-07-07 08:50:01 -070036static void convert_CMYK_to_RGBA(uint8_t* row, uint32_t width) {
msarette16b04a2015-04-15 07:32:19 -070037 // We will implement a crude conversion from CMYK -> RGB using formulas
38 // from easyrgb.com.
39 //
40 // CMYK -> CMY
41 // C = C * (1 - K) + K
42 // M = M * (1 - K) + K
43 // Y = Y * (1 - K) + K
44 //
45 // libjpeg actually gives us inverted CMYK, so we must subtract the
46 // original terms from 1.
47 // CMYK -> CMY
48 // C = (1 - C) * (1 - (1 - K)) + (1 - K)
49 // M = (1 - M) * (1 - (1 - K)) + (1 - K)
50 // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
51 //
52 // Simplifying the above expression.
53 // CMYK -> CMY
54 // C = 1 - CK
55 // M = 1 - MK
56 // Y = 1 - YK
57 //
58 // CMY -> RGB
59 // R = (1 - C) * 255
60 // G = (1 - M) * 255
61 // B = (1 - Y) * 255
62 //
63 // Therefore the full conversion is below. This can be verified at
64 // www.rapidtables.com (assuming inverted CMYK).
65 // CMYK -> RGB
66 // R = C * K * 255
67 // G = M * K * 255
68 // B = Y * K * 255
69 //
70 // As a final note, we have treated the CMYK values as if they were on
71 // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
72 // We must divide each CMYK component by 255 to obtain the true conversion
73 // we should perform.
74 // CMYK -> RGB
75 // R = C * K / 255
76 // G = M * K / 255
77 // B = Y * K / 255
78 for (uint32_t x = 0; x < width; x++, row += 4) {
msarett1c8a5872015-07-07 08:50:01 -070079#if defined(SK_PMCOLOR_IS_RGBA)
msarette16b04a2015-04-15 07:32:19 -070080 row[0] = SkMulDiv255Round(row[0], row[3]);
81 row[1] = SkMulDiv255Round(row[1], row[3]);
82 row[2] = SkMulDiv255Round(row[2], row[3]);
msarett1c8a5872015-07-07 08:50:01 -070083#else
84 uint8_t tmp = row[0];
85 row[0] = SkMulDiv255Round(row[2], row[3]);
86 row[1] = SkMulDiv255Round(row[1], row[3]);
87 row[2] = SkMulDiv255Round(tmp, row[3]);
88#endif
msarette16b04a2015-04-15 07:32:19 -070089 row[3] = 0xFF;
90 }
91}
92
93bool SkJpegCodec::IsJpeg(SkStream* stream) {
94 static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF };
95 char buffer[sizeof(jpegSig)];
96 return stream->read(buffer, sizeof(jpegSig)) == sizeof(jpegSig) &&
97 !memcmp(buffer, jpegSig, sizeof(jpegSig));
98}
99
100bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
101 JpegDecoderMgr** decoderMgrOut) {
102
103 // Create a JpegDecoderMgr to own all of the decompress information
104 SkAutoTDelete<JpegDecoderMgr> decoderMgr(SkNEW_ARGS(JpegDecoderMgr, (stream)));
105
106 // libjpeg errors will be caught and reported here
107 if (setjmp(decoderMgr->getJmpBuf())) {
108 return decoderMgr->returnFalse("setjmp");
109 }
110
111 // Initialize the decompress info and the source manager
112 decoderMgr->init();
113
114 // Read the jpeg header
msarettfcaaade2015-08-11 13:32:54 -0700115 if (JPEG_HEADER_OK != chromium_jpeg_read_header(decoderMgr->dinfo(), true)) {
msarette16b04a2015-04-15 07:32:19 -0700116 return decoderMgr->returnFalse("read_header");
117 }
118
119 if (NULL != codecOut) {
120 // Recommend the color type to decode to
121 const SkColorType colorType = decoderMgr->getColorType();
122
123 // Create image info object and the codec
124 const SkImageInfo& imageInfo = SkImageInfo::Make(decoderMgr->dinfo()->image_width,
125 decoderMgr->dinfo()->image_height, colorType, kOpaque_SkAlphaType);
126 *codecOut = SkNEW_ARGS(SkJpegCodec, (imageInfo, stream, decoderMgr.detach()));
127 } else {
128 SkASSERT(NULL != decoderMgrOut);
129 *decoderMgrOut = decoderMgr.detach();
130 }
131 return true;
132}
133
134SkCodec* SkJpegCodec::NewFromStream(SkStream* stream) {
135 SkAutoTDelete<SkStream> streamDeleter(stream);
136 SkCodec* codec = NULL;
137 if (ReadHeader(stream, &codec, NULL)) {
138 // Codec has taken ownership of the stream, we do not need to delete it
139 SkASSERT(codec);
140 streamDeleter.detach();
141 return codec;
142 }
143 return NULL;
144}
145
146SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream,
147 JpegDecoderMgr* decoderMgr)
148 : INHERITED(srcInfo, stream)
149 , fDecoderMgr(decoderMgr)
150{}
151
152/*
emmaleerb1579172015-08-14 05:46:08 -0700153 * Return the row bytes of a particular image type and width
154 */
155static int get_row_bytes(const j_decompress_ptr dinfo) {
156 int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_color_components;
157 return dinfo->output_width * colorBytes;
158
159}
160/*
msarette16b04a2015-04-15 07:32:19 -0700161 * Return a valid set of output dimensions for this decoder, given an input scale
162 */
163SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
msarett1c8a5872015-07-07 08:50:01 -0700164 // 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
165 // support these as well
166 long num;
167 long denom = 8;
168 if (desiredScale > 0.875f) {
169 num = 8;
170 } else if (desiredScale > 0.75f) {
171 num = 7;
172 } else if (desiredScale > 0.625f) {
173 num = 6;
174 } else if (desiredScale > 0.5f) {
175 num = 5;
msarette16b04a2015-04-15 07:32:19 -0700176 } else if (desiredScale > 0.375f) {
msarett1c8a5872015-07-07 08:50:01 -0700177 num = 4;
178 } else if (desiredScale > 0.25f) {
179 num = 3;
180 } else if (desiredScale > 0.125f) {
181 num = 2;
msarette16b04a2015-04-15 07:32:19 -0700182 } else {
msarett1c8a5872015-07-07 08:50:01 -0700183 num = 1;
msarette16b04a2015-04-15 07:32:19 -0700184 }
185
186 // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
187 jpeg_decompress_struct dinfo;
mtkleinf7aaadb2015-04-16 06:09:27 -0700188 sk_bzero(&dinfo, sizeof(dinfo));
msarette16b04a2015-04-15 07:32:19 -0700189 dinfo.image_width = this->getInfo().width();
190 dinfo.image_height = this->getInfo().height();
191 dinfo.global_state = DSTATE_READY;
192 dinfo.num_components = 0;
msarett1c8a5872015-07-07 08:50:01 -0700193 dinfo.scale_num = num;
194 dinfo.scale_denom = denom;
msarettfcaaade2015-08-11 13:32:54 -0700195 chromium_jpeg_calc_output_dimensions(&dinfo);
msarette16b04a2015-04-15 07:32:19 -0700196
197 // Return the calculated output dimensions for the given scale
198 return SkISize::Make(dinfo.output_width, dinfo.output_height);
199}
200
scroggob427db12015-08-12 07:24:13 -0700201bool SkJpegCodec::onRewind() {
202 JpegDecoderMgr* decoderMgr = NULL;
203 if (!ReadHeader(this->stream(), NULL, &decoderMgr)) {
204 return fDecoderMgr->returnFalse("could not rewind");
msarett97fdea62015-04-29 08:17:15 -0700205 }
scroggob427db12015-08-12 07:24:13 -0700206 SkASSERT(NULL != decoderMgr);
207 fDecoderMgr.reset(decoderMgr);
208 return true;
msarett97fdea62015-04-29 08:17:15 -0700209}
210
211/*
msarett1c8a5872015-07-07 08:50:01 -0700212 * Checks if the conversion between the input image and the requested output
213 * image has been implemented
214 * Sets the output color space
215 */
216bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
217 const SkImageInfo& src = this->getInfo();
218
219 // Ensure that the profile type is unchanged
220 if (dst.profileType() != src.profileType()) {
221 return false;
222 }
223
224 // Ensure that the alpha type is opaque
225 if (kOpaque_SkAlphaType != dst.alphaType()) {
226 return false;
227 }
228
229 // Check if we will decode to CMYK because a conversion to RGBA is not supported
230 J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space;
231 bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace;
232
233 // Check for valid color types and set the output color space
234 switch (dst.colorType()) {
235 case kN32_SkColorType:
236 if (isCMYK) {
237 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
238 } else {
239 // Check the byte ordering of the RGBA color space for the
240 // current platform
241#if defined(SK_PMCOLOR_IS_RGBA)
242 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
243#else
244 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
245#endif
246 }
247 return true;
248 case kRGB_565_SkColorType:
249 if (isCMYK) {
250 return false;
251 } else {
252 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
253 }
254 return true;
255 case kGray_8_SkColorType:
256 if (isCMYK) {
257 return false;
258 } else {
259 // We will enable decodes to gray even if the image is color because this is
260 // much faster than decoding to color and then converting
261 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
262 }
263 return true;
264 default:
265 return false;
266 }
267}
268
269/*
emmaleerb1579172015-08-14 05:46:08 -0700270 * Checks if we can natively scale to the requested dimensions and natively scales the
271 * dimensions if possible
msarett97fdea62015-04-29 08:17:15 -0700272 */
emmaleerb1579172015-08-14 05:46:08 -0700273bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) {
msarett1c8a5872015-07-07 08:50:01 -0700274 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
275 fDecoderMgr->dinfo()->scale_denom = 8;
276 fDecoderMgr->dinfo()->scale_num = 8;
msarettfcaaade2015-08-11 13:32:54 -0700277 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
msarett97fdea62015-04-29 08:17:15 -0700278 while (fDecoderMgr->dinfo()->output_width != dstWidth ||
279 fDecoderMgr->dinfo()->output_height != dstHeight) {
280
281 // Return a failure if we have tried all of the possible scales
msarett1c8a5872015-07-07 08:50:01 -0700282 if (1 == fDecoderMgr->dinfo()->scale_num ||
msarett97fdea62015-04-29 08:17:15 -0700283 dstWidth > fDecoderMgr->dinfo()->output_width ||
284 dstHeight > fDecoderMgr->dinfo()->output_height) {
emmaleerb1579172015-08-14 05:46:08 -0700285 // reset native scale settings on failure because this may be supported by the swizzler
286 this->fDecoderMgr->dinfo()->scale_num = 8;
287 chromium_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
288 return false;
msarett97fdea62015-04-29 08:17:15 -0700289 }
290
291 // Try the next scale
msarett1c8a5872015-07-07 08:50:01 -0700292 fDecoderMgr->dinfo()->scale_num -= 1;
msarettfcaaade2015-08-11 13:32:54 -0700293 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
msarett97fdea62015-04-29 08:17:15 -0700294 }
295 return true;
296}
297
298/*
msarette16b04a2015-04-15 07:32:19 -0700299 * Performs the jpeg decode
300 */
301SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
302 void* dst, size_t dstRowBytes,
303 const Options& options, SkPMColor*, int*) {
304 // Rewind the stream if needed
scroggob427db12015-08-12 07:24:13 -0700305 if (!this->rewindIfNeeded()) {
msarettc0e80c12015-07-01 06:50:35 -0700306 return fDecoderMgr->returnFailure("could not rewind stream", kCouldNotRewind);
msarette16b04a2015-04-15 07:32:19 -0700307 }
308
scroggob636b452015-07-22 07:16:20 -0700309 if (options.fSubset) {
310 // Subsets are not supported.
311 return kUnimplemented;
312 }
313
msarette16b04a2015-04-15 07:32:19 -0700314 // Get a pointer to the decompress info since we will use it quite frequently
315 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
316
317 // Set the jump location for libjpeg errors
318 if (setjmp(fDecoderMgr->getJmpBuf())) {
319 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
320 }
321
msarett1c8a5872015-07-07 08:50:01 -0700322 // Check if we can decode to the requested destination and set the output color space
323 if (!this->setOutputColorSpace(dstInfo)) {
msarette16b04a2015-04-15 07:32:19 -0700324 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion);
325 }
msarette16b04a2015-04-15 07:32:19 -0700326
msarett97fdea62015-04-29 08:17:15 -0700327 // Perform the necessary scaling
emmaleerb1579172015-08-14 05:46:08 -0700328 if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
msarett1c8a5872015-07-07 08:50:01 -0700329 return fDecoderMgr->returnFailure("cannot scale to requested dims", kInvalidScale);
msarette16b04a2015-04-15 07:32:19 -0700330 }
331
332 // Now, given valid output dimensions, we can start the decompress
msarettfcaaade2015-08-11 13:32:54 -0700333 if (!chromium_jpeg_start_decompress(dinfo)) {
msarette16b04a2015-04-15 07:32:19 -0700334 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
335 }
336
msarett1c8a5872015-07-07 08:50:01 -0700337 // The recommended output buffer height should always be 1 in high quality modes.
338 // If it's not, we want to know because it means our strategy is not optimal.
339 SkASSERT(1 == dinfo->rec_outbuf_height);
msarette16b04a2015-04-15 07:32:19 -0700340
msarett1c8a5872015-07-07 08:50:01 -0700341 // Perform the decode a single row at a time
msarett97fdea62015-04-29 08:17:15 -0700342 uint32_t dstHeight = dstInfo.height();
msarett1c8a5872015-07-07 08:50:01 -0700343 JSAMPLE* dstRow = (JSAMPLE*) dst;
344 for (uint32_t y = 0; y < dstHeight; y++) {
msarette16b04a2015-04-15 07:32:19 -0700345 // Read rows of the image
msarettfcaaade2015-08-11 13:32:54 -0700346 uint32_t rowsDecoded = chromium_jpeg_read_scanlines(dinfo, &dstRow, 1);
msarette16b04a2015-04-15 07:32:19 -0700347
348 // If we cannot read enough rows, assume the input is incomplete
msarett1c8a5872015-07-07 08:50:01 -0700349 if (rowsDecoded != 1) {
msarette16b04a2015-04-15 07:32:19 -0700350 // Fill the remainder of the image with black. This error handling
351 // behavior is unspecified but SkCodec consistently uses black as
352 // the fill color for opaque images. If the destination is kGray,
353 // the low 8 bits of SK_ColorBLACK will be used. Conveniently,
354 // these are zeros, which is the representation for black in kGray.
msarettfdb788c2015-07-29 10:37:29 -0700355 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK
356 // will be used. Conveniently, these are zeros, which is the
357 // representation for black in kRGB_565.
358 if (kNo_ZeroInitialized == options.fZeroInitialized ||
359 kN32_SkColorType == dstInfo.colorType()) {
360 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y,
361 SK_ColorBLACK, NULL);
362 }
msarette16b04a2015-04-15 07:32:19 -0700363
364 // Prevent libjpeg from failing on incomplete decode
365 dinfo->output_scanline = dstHeight;
366
367 // Finish the decode and indicate that the input was incomplete.
msarettfcaaade2015-08-11 13:32:54 -0700368 chromium_jpeg_finish_decompress(dinfo);
msarette16b04a2015-04-15 07:32:19 -0700369 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
370 }
msarett1c8a5872015-07-07 08:50:01 -0700371
372 // Convert to RGBA if necessary
373 if (JCS_CMYK == dinfo->out_color_space) {
374 convert_CMYK_to_RGBA(dstRow, dstInfo.width());
375 }
376
377 // Move to the next row
378 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
msarette16b04a2015-04-15 07:32:19 -0700379 }
msarettfcaaade2015-08-11 13:32:54 -0700380 chromium_jpeg_finish_decompress(dinfo);
msarette16b04a2015-04-15 07:32:19 -0700381
382 return kSuccess;
383}
msarett97fdea62015-04-29 08:17:15 -0700384
385/*
386 * Enable scanline decoding for jpegs
387 */
388class SkJpegScanlineDecoder : public SkScanlineDecoder {
389public:
scroggo1c005e42015-08-04 09:24:45 -0700390 SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec)
391 : INHERITED(srcInfo)
msarett97fdea62015-04-29 08:17:15 -0700392 , fCodec(codec)
scroggo1c005e42015-08-04 09:24:45 -0700393 , fOpts()
msarett1c8a5872015-07-07 08:50:01 -0700394 {}
msarett97fdea62015-04-29 08:17:15 -0700395
emmaleerb1579172015-08-14 05:46:08 -0700396 /*
397 * Return a valid set of output dimensions for this decoder, given an input scale
398 */
399 SkISize onGetScaledDimensions(float desiredScale) override {
400 return fCodec->onGetScaledDimensions(desiredScale);
401 }
402
403 /*
404 * Create the swizzler based on the encoded format.
405 * The swizzler is only used for sampling in the x direction.
406 */
407
408 SkCodec::Result initializeSwizzler(const SkImageInfo& info, const SkCodec::Options& options) {
409 SkSwizzler::SrcConfig srcConfig;
410 switch (info.colorType()) {
411 case kGray_8_SkColorType:
412 srcConfig = SkSwizzler::kGray;
413 break;
414 case kRGBA_8888_SkColorType:
415 srcConfig = SkSwizzler::kRGBX;
416 break;
417 case kBGRA_8888_SkColorType:
418 srcConfig = SkSwizzler::kBGRX;
419 break;
420 case kRGB_565_SkColorType:
421 srcConfig = SkSwizzler::kRGB_565;
422 break;
423 default:
424 //would have exited before now if the colorType was supported by jpeg
425 SkASSERT(false);
426 }
427
428 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, NULL, info, options.fZeroInitialized,
429 this->getInfo()));
430 if (!fSwizzler) {
431 // FIXME: CreateSwizzler could fail for another reason.
432 return SkCodec::kUnimplemented;
433 }
434 return SkCodec::kSuccess;
435 }
436
scroggo1c005e42015-08-04 09:24:45 -0700437 SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options,
438 SkPMColor ctable[], int* ctableCount) override {
439
440 // Rewind the stream if needed
scroggob427db12015-08-12 07:24:13 -0700441 if (!fCodec->rewindIfNeeded()) {
scroggo1c005e42015-08-04 09:24:45 -0700442 return SkCodec::kCouldNotRewind;
443 }
444
445 // Set the jump location for libjpeg errors
446 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
447 SkCodecPrintf("setjmp: Error from libjpeg\n");
448 return SkCodec::kInvalidInput;
449 }
450
451 // Check if we can decode to the requested destination and set the output color space
452 if (!fCodec->setOutputColorSpace(dstInfo)) {
453 return SkCodec::kInvalidConversion;
454 }
455
456 // Perform the necessary scaling
emmaleerb1579172015-08-14 05:46:08 -0700457 if (!fCodec->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
458 // full native scaling to dstInfo dimensions not supported
459
460 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
461 return SkCodec::kInvalidScale;
462 }
463 // create swizzler for sampling
464 SkCodec::Result result = this->initializeSwizzler(dstInfo, options);
465 if (SkCodec::kSuccess != result) {
466 SkCodecPrintf("failed to initialize the swizzler.\n");
467 return result;
468 }
469 fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo()));
470 fSrcRow = static_cast<uint8_t*>(fStorage.get());
471 } else {
472 fSrcRow = NULL;
473 fSwizzler.reset(NULL);
scroggo1c005e42015-08-04 09:24:45 -0700474 }
475
476 // Now, given valid output dimensions, we can start the decompress
msarettfcaaade2015-08-11 13:32:54 -0700477 if (!chromium_jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) {
scroggo1c005e42015-08-04 09:24:45 -0700478 SkCodecPrintf("start decompress failed\n");
479 return SkCodec::kInvalidInput;
480 }
481
482 fOpts = options;
483
484 return SkCodec::kSuccess;
485 }
486
scroggo9b2cdbf42015-07-10 12:07:02 -0700487 virtual ~SkJpegScanlineDecoder() {
488 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
489 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n");
490 return;
491 }
492
493 // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a
494 // partial decode.
495 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height();
msarettfcaaade2015-08-11 13:32:54 -0700496 chromium_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo());
scroggo9b2cdbf42015-07-10 12:07:02 -0700497 }
498
scroggoeb602a52015-07-09 08:16:03 -0700499 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) override {
msarett97fdea62015-04-29 08:17:15 -0700500 // Set the jump location for libjpeg errors
501 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
scroggoeb602a52015-07-09 08:16:03 -0700502 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput);
msarett97fdea62015-04-29 08:17:15 -0700503 }
emmaleerc7993d72015-08-13 13:59:21 -0700504 // Read rows one at a time
emmaleerb1579172015-08-14 05:46:08 -0700505 JSAMPLE* dstRow;
506 if (fSwizzler) {
507 // write data to storage row, then sample using swizzler
508 dstRow = fSrcRow;
509 } else {
510 // write data directly to dst
511 dstRow = (JSAMPLE*) dst;
512 }
513
msarett97fdea62015-04-29 08:17:15 -0700514 for (int y = 0; y < count; y++) {
515 // Read row of the image
msarett1c8a5872015-07-07 08:50:01 -0700516 uint32_t rowsDecoded =
msarettfcaaade2015-08-11 13:32:54 -0700517 chromium_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dstRow, 1);
msarett97fdea62015-04-29 08:17:15 -0700518 if (rowsDecoded != 1) {
msarettfdb788c2015-07-29 10:37:29 -0700519 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized ||
520 kN32_SkColorType == this->dstInfo().colorType()) {
521 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes,
522 count - y, SK_ColorBLACK, NULL);
523 }
msarett1c8a5872015-07-07 08:50:01 -0700524 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
scroggoeb602a52015-07-09 08:16:03 -0700525 return SkCodec::kIncompleteInput;
msarett97fdea62015-04-29 08:17:15 -0700526 }
527
msarett1c8a5872015-07-07 08:50:01 -0700528 // Convert to RGBA if necessary
msarett97fdea62015-04-29 08:17:15 -0700529 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) {
emmaleerb1579172015-08-14 05:46:08 -0700530 convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->output_width);
msarett97fdea62015-04-29 08:17:15 -0700531 }
532
emmaleerb1579172015-08-14 05:46:08 -0700533 if(fSwizzler) {
534 // use swizzler to sample row
535 fSwizzler->swizzle(dst, dstRow);
536 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
537 } else {
538 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
539 }
msarett97fdea62015-04-29 08:17:15 -0700540 }
scroggoeb602a52015-07-09 08:16:03 -0700541 return SkCodec::kSuccess;
msarett97fdea62015-04-29 08:17:15 -0700542 }
543
msarett1c8a5872015-07-07 08:50:01 -0700544#ifndef TURBO_HAS_SKIP
msarettfcaaade2015-08-11 13:32:54 -0700545// TODO (msarett): Make this a member function and avoid reallocating the
546// memory buffer on each call to skip.
547#define chromium_jpeg_skip_scanlines(dinfo, count) \
emmaleerb1579172015-08-14 05:46:08 -0700548 SkAutoMalloc storage(get_row_bytes(dinfo)); \
msarett1c8a5872015-07-07 08:50:01 -0700549 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \
550 for (int y = 0; y < count; y++) { \
msarettfcaaade2015-08-11 13:32:54 -0700551 chromium_jpeg_read_scanlines(dinfo, &storagePtr, 1); \
msarett1c8a5872015-07-07 08:50:01 -0700552 }
553#endif
554
scroggoeb602a52015-07-09 08:16:03 -0700555 SkCodec::Result onSkipScanlines(int count) override {
msarett97fdea62015-04-29 08:17:15 -0700556 // Set the jump location for libjpeg errors
557 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
scroggoeb602a52015-07-09 08:16:03 -0700558 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput);
msarett97fdea62015-04-29 08:17:15 -0700559 }
560
msarettfcaaade2015-08-11 13:32:54 -0700561 chromium_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count);
msarett97fdea62015-04-29 08:17:15 -0700562
scroggoeb602a52015-07-09 08:16:03 -0700563 return SkCodec::kSuccess;
msarett97fdea62015-04-29 08:17:15 -0700564 }
565
emmaleerb1579172015-08-14 05:46:08 -0700566 SkEncodedFormat onGetEncodedFormat() const override {
567 return kJPEG_SkEncodedFormat;
568 }
msarettfcaaade2015-08-11 13:32:54 -0700569
msarett97fdea62015-04-29 08:17:15 -0700570private:
scroggo9b2cdbf42015-07-10 12:07:02 -0700571 SkAutoTDelete<SkJpegCodec> fCodec;
emmaleerb1579172015-08-14 05:46:08 -0700572 SkAutoMalloc fStorage; // Only used if sampling is needed
573 uint8_t* fSrcRow; // Only used if sampling is needed
scroggo1c005e42015-08-04 09:24:45 -0700574 SkCodec::Options fOpts;
emmaleerb1579172015-08-14 05:46:08 -0700575 SkAutoTDelete<SkSwizzler> fSwizzler;
msarett97fdea62015-04-29 08:17:15 -0700576
577 typedef SkScanlineDecoder INHERITED;
578};
579
scroggo1c005e42015-08-04 09:24:45 -0700580SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) {
scroggo9b2cdbf42015-07-10 12:07:02 -0700581 SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewFromStream(stream)));
582 if (!codec) {
583 return NULL;
584 }
585
scroggo1c005e42015-08-04 09:24:45 -0700586 const SkImageInfo& srcInfo = codec->getInfo();
emmaleerb1579172015-08-14 05:46:08 -0700587
msarett97fdea62015-04-29 08:17:15 -0700588 // Return the new scanline decoder
scroggo1c005e42015-08-04 09:24:45 -0700589 return SkNEW_ARGS(SkJpegScanlineDecoder, (srcInfo, codec.detach()));
msarett97fdea62015-04-29 08:17:15 -0700590}