1 /*
2 * Copyright 2007 The Android Open Source Project
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
9 #include "SkImageDecoder.h"
10 #include "SkImageEncoder.h"
11 #include "SkJpegUtility.h"
12 #include "SkColorPriv.h"
13 #include "SkDither.h"
14 #include "SkMSAN.h"
15 #include "SkScaledBitmapSampler.h"
16 #include "SkStream.h"
17 #include "SkTemplates.h"
18 #include "SkTime.h"
19 #include "SkUtils.h"
20 #include "SkRTConf.h"
21 #include "SkRect.h"
22 #include "SkCanvas.h"
23
24
25 #include <stdio.h>
26 extern "C" {
27 #include "jpeglib.h"
28 #include "jerror.h"
29 }
30
31 // These enable timing code that report milliseconds for an encoding/decoding
32 //#define TIME_ENCODE
33 //#define TIME_DECODE
34
35 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
36 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
37
38 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
39 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
40 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
41 "images.jpeg.suppressDecoderWarnings",
42 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
43 "Suppress most JPG warnings when calling decode functions.");
44 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
45 "images.jpeg.suppressDecoderErrors",
46 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
47 "Suppress most JPG error messages when decode "
48 "function fails.");
49
50 //////////////////////////////////////////////////////////////////////////
51 //////////////////////////////////////////////////////////////////////////
52
do_nothing_emit_message(jpeg_common_struct *,int)53 static void do_nothing_emit_message(jpeg_common_struct*, int) {
54 /* do nothing */
55 }
do_nothing_output_message(j_common_ptr)56 static void do_nothing_output_message(j_common_ptr) {
57 /* do nothing */
58 }
59
initialize_info(jpeg_decompress_struct * cinfo,skjpeg_source_mgr * src_mgr)60 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
61 SkASSERT(cinfo != nullptr);
62 SkASSERT(src_mgr != nullptr);
63 jpeg_create_decompress(cinfo);
64 cinfo->src = src_mgr;
65 /* To suppress warnings with a SK_DEBUG binary, set the
66 * environment variable "skia_images_jpeg_suppressDecoderWarnings"
67 * to "true". Inside a program that links to skia:
68 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
69 if (c_suppressJPEGImageDecoderWarnings) {
70 cinfo->err->emit_message = &do_nothing_emit_message;
71 }
72 /* To suppress error messages with a SK_DEBUG binary, set the
73 * environment variable "skia_images_jpeg_suppressDecoderErrors"
74 * to "true". Inside a program that links to skia:
75 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
76 if (c_suppressJPEGImageDecoderErrors) {
77 cinfo->err->output_message = &do_nothing_output_message;
78 }
79 }
80
81 class SkJPEGImageDecoder : public SkImageDecoder {
82 public:
83
getFormat() const84 Format getFormat() const override {
85 return kJPEG_Format;
86 }
87
88 protected:
89 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
90 bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
91 void* planes[3], size_t rowBytes[3],
92 SkYUVColorSpace* colorSpace) override;
93
94 private:
95
96 /**
97 * Determine the appropriate bitmap colortype and out_color_space based on
98 * both the preference of the caller and the jpeg_color_space on the
99 * jpeg_decompress_struct passed in.
100 * Must be called after jpeg_read_header.
101 */
102 SkColorType getBitmapColorType(jpeg_decompress_struct*);
103
104 typedef SkImageDecoder INHERITED;
105 };
106
107 //////////////////////////////////////////////////////////////////////////
108
109 /* Automatically clean up after throwing an exception */
110 class JPEGAutoClean {
111 public:
JPEGAutoClean()112 JPEGAutoClean(): cinfo_ptr(nullptr) {}
~JPEGAutoClean()113 ~JPEGAutoClean() {
114 if (cinfo_ptr) {
115 jpeg_destroy_decompress(cinfo_ptr);
116 }
117 }
set(jpeg_decompress_struct * info)118 void set(jpeg_decompress_struct* info) {
119 cinfo_ptr = info;
120 }
121 private:
122 jpeg_decompress_struct* cinfo_ptr;
123 };
124
125 ///////////////////////////////////////////////////////////////////////////////
126
127 /* If we need to better match the request, we might examine the image and
128 output dimensions, and determine if the downsampling jpeg provided is
129 not sufficient. If so, we can recompute a modified sampleSize value to
130 make up the difference.
131
132 To skip this additional scaling, just set sampleSize = 1; below.
133 */
recompute_sampleSize(int sampleSize,const jpeg_decompress_struct & cinfo)134 static int recompute_sampleSize(int sampleSize,
135 const jpeg_decompress_struct& cinfo) {
136 return sampleSize * cinfo.output_width / cinfo.image_width;
137 }
138
valid_output_dimensions(const jpeg_decompress_struct & cinfo)139 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
140 /* These are initialized to 0, so if they have non-zero values, we assume
141 they are "valid" (i.e. have been computed by libjpeg)
142 */
143 return 0 != cinfo.output_width && 0 != cinfo.output_height;
144 }
145
skip_src_rows(jpeg_decompress_struct * cinfo,void * buffer,int count)146 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
147 for (int i = 0; i < count; i++) {
148 JSAMPLE* rowptr = (JSAMPLE*)buffer;
149 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
150 if (1 != row_count) {
151 return false;
152 }
153 }
154 return true;
155 }
156
157 ///////////////////////////////////////////////////////////////////////////////
158
159 // This guy exists just to aid in debugging, as it allows debuggers to just
160 // set a break-point in one place to see all error exists.
print_jpeg_decoder_errors(const jpeg_decompress_struct & cinfo,int width,int height,const char caller[])161 static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo,
162 int width, int height, const char caller[]) {
163 if (!(c_suppressJPEGImageDecoderErrors)) {
164 char buffer[JMSG_LENGTH_MAX];
165 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
166 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
167 cinfo.err->msg_code, buffer, caller, width, height);
168 }
169 }
170
return_false(const jpeg_decompress_struct & cinfo,const char caller[])171 static bool return_false(const jpeg_decompress_struct& cinfo,
172 const char caller[]) {
173 print_jpeg_decoder_errors(cinfo, 0, 0, caller);
174 return false;
175 }
176
return_failure(const jpeg_decompress_struct & cinfo,const SkBitmap & bm,const char caller[])177 static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo,
178 const SkBitmap& bm, const char caller[]) {
179 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
180 return SkImageDecoder::kFailure;
181 }
182
183 ///////////////////////////////////////////////////////////////////////////////
184
185 // Convert a scanline of CMYK samples to RGBX in place. Note that this
186 // method moves the "scanline" pointer in its processing
convert_CMYK_to_RGB(uint8_t * scanline,unsigned int width)187 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
188 // At this point we've received CMYK pixels from libjpeg. We
189 // perform a crude conversion to RGB (based on the formulae
190 // from easyrgb.com):
191 // CMYK -> CMY
192 // C = ( C * (1 - K) + K ) // for each CMY component
193 // CMY -> RGB
194 // R = ( 1 - C ) * 255 // for each RGB component
195 // Unfortunately we are seeing inverted CMYK so all the original terms
196 // are 1-. This yields:
197 // CMYK -> CMY
198 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
199 // The conversion from CMY->RGB remains the same
200 for (unsigned int x = 0; x < width; ++x, scanline += 4) {
201 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
202 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
203 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
204 scanline[3] = 255;
205 }
206 }
207
208 /**
209 * Common code for setting the error manager.
210 */
set_error_mgr(jpeg_decompress_struct * cinfo,skjpeg_error_mgr * errorManager)211 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
212 SkASSERT(cinfo != nullptr);
213 SkASSERT(errorManager != nullptr);
214 cinfo->err = jpeg_std_error(errorManager);
215 errorManager->error_exit = skjpeg_error_exit;
216 }
217
218 /**
219 * Common code for setting the dct method.
220 */
set_dct_method(const SkImageDecoder & decoder,jpeg_decompress_struct * cinfo)221 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
222 SkASSERT(cinfo != nullptr);
223 cinfo->dct_method = JDCT_ISLOW;
224 }
225
getBitmapColorType(jpeg_decompress_struct * cinfo)226 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
227 SkASSERT(cinfo != nullptr);
228
229 SrcDepth srcDepth = k32Bit_SrcDepth;
230 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
231 srcDepth = k8BitGray_SrcDepth;
232 }
233
234 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
235 switch (colorType) {
236 case kAlpha_8_SkColorType:
237 // Only respect A8 colortype if the original is grayscale,
238 // in which case we will treat the grayscale as alpha
239 // values.
240 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
241 colorType = kN32_SkColorType;
242 }
243 break;
244 case kN32_SkColorType:
245 // Fall through.
246 case kARGB_4444_SkColorType:
247 // Fall through.
248 case kRGB_565_SkColorType:
249 // These are acceptable destination colortypes.
250 break;
251 default:
252 // Force all other colortypes to 8888.
253 colorType = kN32_SkColorType;
254 break;
255 }
256
257 switch (cinfo->jpeg_color_space) {
258 case JCS_CMYK:
259 // Fall through.
260 case JCS_YCCK:
261 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
262 // so libjpeg will give us CMYK samples back and we will later
263 // manually convert them to RGB
264 cinfo->out_color_space = JCS_CMYK;
265 break;
266 case JCS_GRAYSCALE:
267 if (kAlpha_8_SkColorType == colorType) {
268 cinfo->out_color_space = JCS_GRAYSCALE;
269 break;
270 }
271 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
272 // colortype. Fall through to set to the default.
273 default:
274 cinfo->out_color_space = JCS_RGB;
275 break;
276 }
277 return colorType;
278 }
279
280 /**
281 * Based on the colortype and dither mode, adjust out_color_space and
282 * dither_mode of cinfo. Only does work in ANDROID_RGB
283 */
adjust_out_color_space_and_dither(jpeg_decompress_struct * cinfo,SkColorType colorType,const SkImageDecoder & decoder)284 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
285 SkColorType colorType,
286 const SkImageDecoder& decoder) {
287 SkASSERT(cinfo != nullptr);
288 #ifdef ANDROID_RGB
289 cinfo->dither_mode = JDITHER_NONE;
290 if (JCS_CMYK == cinfo->out_color_space) {
291 return;
292 }
293 switch (colorType) {
294 case kN32_SkColorType:
295 cinfo->out_color_space = JCS_RGBA_8888;
296 break;
297 case kRGB_565_SkColorType:
298 cinfo->out_color_space = JCS_RGB_565;
299 if (decoder.getDitherImage()) {
300 cinfo->dither_mode = JDITHER_ORDERED;
301 }
302 break;
303 default:
304 break;
305 }
306 #endif
307 }
308
309 /**
310 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
311 Used when decoding fails partway through reading scanlines to fill
312 remaining lines. */
fill_below_level(int y,SkBitmap * bitmap)313 static void fill_below_level(int y, SkBitmap* bitmap) {
314 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
315 SkCanvas canvas(*bitmap);
316 canvas.clipRect(SkRect::Make(rect));
317 canvas.drawColor(SK_ColorWHITE);
318 }
319
320 /**
321 * Get the config and bytes per pixel of the source data. Return
322 * whether the data is supported.
323 */
get_src_config(const jpeg_decompress_struct & cinfo,SkScaledBitmapSampler::SrcConfig * sc,int * srcBytesPerPixel)324 static bool get_src_config(const jpeg_decompress_struct& cinfo,
325 SkScaledBitmapSampler::SrcConfig* sc,
326 int* srcBytesPerPixel) {
327 SkASSERT(sc != nullptr && srcBytesPerPixel != nullptr);
328 if (JCS_CMYK == cinfo.out_color_space) {
329 // In this case we will manually convert the CMYK values to RGB
330 *sc = SkScaledBitmapSampler::kRGBX;
331 // The CMYK work-around relies on 4 components per pixel here
332 *srcBytesPerPixel = 4;
333 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
334 *sc = SkScaledBitmapSampler::kRGB;
335 *srcBytesPerPixel = 3;
336 #ifdef ANDROID_RGB
337 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
338 *sc = SkScaledBitmapSampler::kRGBX;
339 *srcBytesPerPixel = 4;
340 } else if (JCS_RGB_565 == cinfo.out_color_space) {
341 *sc = SkScaledBitmapSampler::kRGB_565;
342 *srcBytesPerPixel = 2;
343 #endif
344 } else if (1 == cinfo.out_color_components &&
345 JCS_GRAYSCALE == cinfo.out_color_space) {
346 *sc = SkScaledBitmapSampler::kGray;
347 *srcBytesPerPixel = 1;
348 } else {
349 return false;
350 }
351 return true;
352 }
353
onDecode(SkStream * stream,SkBitmap * bm,Mode mode)354 SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
355 #ifdef TIME_DECODE
356 SkAutoTime atm("JPEG Decode");
357 #endif
358
359 JPEGAutoClean autoClean;
360
361 jpeg_decompress_struct cinfo;
362 skjpeg_source_mgr srcManager(stream, this);
363
364 skjpeg_error_mgr errorManager;
365 set_error_mgr(&cinfo, &errorManager);
366
367 // All objects need to be instantiated before this setjmp call so that
368 // they will be cleaned up properly if an error occurs.
369 if (setjmp(errorManager.fJmpBuf)) {
370 return return_failure(cinfo, *bm, "setjmp");
371 }
372
373 initialize_info(&cinfo, &srcManager);
374 autoClean.set(&cinfo);
375
376 int status = jpeg_read_header(&cinfo, true);
377 if (status != JPEG_HEADER_OK) {
378 return return_failure(cinfo, *bm, "read_header");
379 }
380
381 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it
382 can) much faster that we, just use their num/denom api to approximate
383 the size.
384 */
385 int sampleSize = this->getSampleSize();
386
387 set_dct_method(*this, &cinfo);
388
389 SkASSERT(1 == cinfo.scale_num);
390 cinfo.scale_denom = sampleSize;
391
392 const SkColorType colorType = this->getBitmapColorType(&cinfo);
393 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
394 kPremul_SkAlphaType : kOpaque_SkAlphaType;
395
396 adjust_out_color_space_and_dither(&cinfo, colorType, *this);
397
398 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
399 // Assume an A8 bitmap is not opaque to avoid the check of each
400 // individual pixel. It is very unlikely to be opaque, since
401 // an opaque A8 bitmap would not be very interesting.
402 // Otherwise, a jpeg image is opaque.
403 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
404 colorType, alphaType));
405 return success ? kSuccess : kFailure;
406 }
407
408 /* image_width and image_height are the original dimensions, available
409 after jpeg_read_header(). To see the scaled dimensions, we have to call
410 jpeg_start_decompress(), and then read output_width and output_height.
411 */
412 if (!jpeg_start_decompress(&cinfo)) {
413 /* If we failed here, we may still have enough information to return
414 to the caller if they just wanted (subsampled bounds). If sampleSize
415 was 1, then we would have already returned. Thus we just check if
416 we're in kDecodeBounds_Mode, and that we have valid output sizes.
417
418 One reason to fail here is that we have insufficient stream data
419 to complete the setup. However, output dimensions seem to get
420 computed very early, which is why this special check can pay off.
421 */
422 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
423 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
424 recompute_sampleSize(sampleSize, cinfo));
425 // Assume an A8 bitmap is not opaque to avoid the check of each
426 // individual pixel. It is very unlikely to be opaque, since
427 // an opaque A8 bitmap would not be very interesting.
428 // Otherwise, a jpeg image is opaque.
429 bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
430 colorType, alphaType));
431 return success ? kSuccess : kFailure;
432 } else {
433 return return_failure(cinfo, *bm, "start_decompress");
434 }
435 }
436 sampleSize = recompute_sampleSize(sampleSize, cinfo);
437
438 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
439 // Assume an A8 bitmap is not opaque to avoid the check of each
440 // individual pixel. It is very unlikely to be opaque, since
441 // an opaque A8 bitmap would not be very interesting.
442 // Otherwise, a jpeg image is opaque.
443 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
444 colorType, alphaType));
445 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
446 return kSuccess;
447 }
448 if (!this->allocPixelRef(bm, nullptr)) {
449 return return_failure(cinfo, *bm, "allocPixelRef");
450 }
451
452 SkAutoLockPixels alp(*bm);
453
454 #ifdef ANDROID_RGB
455 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
456 a significant performance boost.
457 */
458 if (sampleSize == 1 &&
459 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
460 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
461 {
462 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
463 INT32 const bpr = bm->rowBytes();
464
465 while (cinfo.output_scanline < cinfo.output_height) {
466 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
467 if (0 == row_count) {
468 // if row_count == 0, then we didn't get a scanline,
469 // so return early. We will return a partial image.
470 fill_below_level(cinfo.output_scanline, bm);
471 cinfo.output_scanline = cinfo.output_height;
472 jpeg_finish_decompress(&cinfo);
473 return kPartialSuccess;
474 }
475 if (this->shouldCancelDecode()) {
476 return return_failure(cinfo, *bm, "shouldCancelDecode");
477 }
478 rowptr += bpr;
479 }
480 jpeg_finish_decompress(&cinfo);
481 return kSuccess;
482 }
483 #endif
484
485 // check for supported formats
486 SkScaledBitmapSampler::SrcConfig sc;
487 int srcBytesPerPixel;
488
489 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
490 return return_failure(cinfo, *bm, "jpeg colorspace");
491 }
492
493 if (!sampler.begin(bm, sc, *this)) {
494 return return_failure(cinfo, *bm, "sampler.begin");
495 }
496
497 SkAutoTMalloc<uint8_t> srcStorage(cinfo.output_width * srcBytesPerPixel);
498 uint8_t* srcRow = srcStorage.get();
499
500 // Possibly skip initial rows [sampler.srcY0]
501 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
502 return return_failure(cinfo, *bm, "skip rows");
503 }
504
505 // now loop through scanlines until y == bm->height() - 1
506 for (int y = 0;; y++) {
507 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
508 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
509 sk_msan_mark_initialized(srcRow, srcRow + cinfo.output_width * srcBytesPerPixel,
510 "skbug.com/4550");
511 if (0 == row_count) {
512 // if row_count == 0, then we didn't get a scanline,
513 // so return early. We will return a partial image.
514 fill_below_level(y, bm);
515 cinfo.output_scanline = cinfo.output_height;
516 jpeg_finish_decompress(&cinfo);
517 return kPartialSuccess;
518 }
519 if (this->shouldCancelDecode()) {
520 return return_failure(cinfo, *bm, "shouldCancelDecode");
521 }
522
523 if (JCS_CMYK == cinfo.out_color_space) {
524 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
525 }
526
527
528 sampler.next(srcRow);
529 if (bm->height() - 1 == y) {
530 // we're done
531 break;
532 }
533
534 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
535 return return_failure(cinfo, *bm, "skip rows");
536 }
537 }
538
539 // we formally skip the rest, so we don't get a complaint from libjpeg
540 if (!skip_src_rows(&cinfo, srcRow,
541 cinfo.output_height - cinfo.output_scanline)) {
542 return return_failure(cinfo, *bm, "skip rows");
543 }
544 jpeg_finish_decompress(&cinfo);
545
546 return kSuccess;
547 }
548
549 ///////////////////////////////////////////////////////////////////////////////
550
551 enum SizeType {
552 kSizeForMemoryAllocation_SizeType,
553 kActualSize_SizeType
554 };
555
compute_yuv_size(const jpeg_decompress_struct & info,int component,SizeType sizeType)556 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component,
557 SizeType sizeType) {
558 if (sizeType == kSizeForMemoryAllocation_SizeType) {
559 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE,
560 info.cur_comp_info[component]->height_in_blocks * DCTSIZE);
561 }
562 return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
563 info.cur_comp_info[component]->downsampled_height);
564 }
565
appears_to_be_yuv(const jpeg_decompress_struct & info)566 static bool appears_to_be_yuv(const jpeg_decompress_struct& info) {
567 return (info.jpeg_color_space == JCS_YCbCr)
568 && (DCTSIZE == 8)
569 && (info.num_components == 3)
570 && (info.comps_in_scan >= info.num_components)
571 && (info.scale_denom <= 8)
572 && (info.cur_comp_info[0])
573 && (info.cur_comp_info[1])
574 && (info.cur_comp_info[2])
575 && (info.cur_comp_info[1]->h_samp_factor == 1)
576 && (info.cur_comp_info[1]->v_samp_factor == 1)
577 && (info.cur_comp_info[2]->h_samp_factor == 1)
578 && (info.cur_comp_info[2]->v_samp_factor == 1);
579 }
580
update_components_sizes(const jpeg_decompress_struct & cinfo,SkISize componentSizes[3],SizeType sizeType)581 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
582 SizeType sizeType) {
583 SkASSERT(appears_to_be_yuv(cinfo));
584 for (int i = 0; i < 3; ++i) {
585 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
586 }
587 }
588
output_raw_data(jpeg_decompress_struct & cinfo,void * planes[3],size_t rowBytes[3])589 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) {
590 SkASSERT(appears_to_be_yuv(cinfo));
591 // U size and V size have to be the same if we're calling output_raw_data()
592 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType);
593 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType));
594
595 JSAMPARRAY bufferraw[3];
596 JSAMPROW bufferraw2[32];
597 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
598 bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
599 bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
600 int yWidth = cinfo.output_width;
601 int yHeight = cinfo.output_height;
602 int yMaxH = yHeight - 1;
603 int v = cinfo.cur_comp_info[0]->v_samp_factor;
604 int uvMaxH = uvSize.height() - 1;
605 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
606 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
607 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
608 size_t rowBytesY = rowBytes[0];
609 size_t rowBytesU = rowBytes[1];
610 size_t rowBytesV = rowBytes[2];
611
612 int yScanlinesToRead = DCTSIZE * v;
613 SkAutoMalloc lastRowStorage(rowBytesY * 4);
614 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
615 JSAMPROW uLastRow = yLastRow + rowBytesY;
616 JSAMPROW vLastRow = uLastRow + rowBytesY;
617 JSAMPROW dummyRow = vLastRow + rowBytesY;
618
619 while (cinfo.output_scanline < cinfo.output_height) {
620 // Request 8 or 16 scanlines: returns 0 or more scanlines.
621 bool hasYLastRow(false), hasUVLastRow(false);
622 // Assign 8 or 16 rows of memory to read the Y channel.
623 for (int i = 0; i < yScanlinesToRead; ++i) {
624 int scanline = (cinfo.output_scanline + i);
625 if (scanline < yMaxH) {
626 bufferraw2[i] = &outputY[scanline * rowBytesY];
627 } else if (scanline == yMaxH) {
628 bufferraw2[i] = yLastRow;
629 hasYLastRow = true;
630 } else {
631 bufferraw2[i] = dummyRow;
632 }
633 }
634 int scaledScanline = cinfo.output_scanline / v;
635 // Assign 8 rows of memory to read the U and V channels.
636 for (int i = 0; i < 8; ++i) {
637 int scanline = (scaledScanline + i);
638 if (scanline < uvMaxH) {
639 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
640 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
641 } else if (scanline == uvMaxH) {
642 bufferraw2[16 + i] = uLastRow;
643 bufferraw2[24 + i] = vLastRow;
644 hasUVLastRow = true;
645 } else {
646 bufferraw2[16 + i] = dummyRow;
647 bufferraw2[24 + i] = dummyRow;
648 }
649 }
650 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead);
651
652 if (scanlinesRead == 0) {
653 return false;
654 }
655
656 if (hasYLastRow) {
657 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
658 }
659 if (hasUVLastRow) {
660 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
661 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
662 }
663 }
664
665 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
666
667 return true;
668 }
669
onDecodeYUV8Planes(SkStream * stream,SkISize componentSizes[3],void * planes[3],size_t rowBytes[3],SkYUVColorSpace * colorSpace)670 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
671 void* planes[3], size_t rowBytes[3],
672 SkYUVColorSpace* colorSpace) {
673 #ifdef TIME_DECODE
674 SkAutoTime atm("JPEG YUV8 Decode");
675 #endif
676 if (this->getSampleSize() != 1) {
677 return false; // Resizing not supported
678 }
679
680 JPEGAutoClean autoClean;
681
682 jpeg_decompress_struct cinfo;
683 skjpeg_source_mgr srcManager(stream, this);
684
685 skjpeg_error_mgr errorManager;
686 set_error_mgr(&cinfo, &errorManager);
687
688 // All objects need to be instantiated before this setjmp call so that
689 // they will be cleaned up properly if an error occurs.
690 if (setjmp(errorManager.fJmpBuf)) {
691 return return_false(cinfo, "setjmp YUV8");
692 }
693
694 initialize_info(&cinfo, &srcManager);
695 autoClean.set(&cinfo);
696
697 int status = jpeg_read_header(&cinfo, true);
698 if (status != JPEG_HEADER_OK) {
699 return return_false(cinfo, "read_header YUV8");
700 }
701
702 if (!appears_to_be_yuv(cinfo)) {
703 // It's not an error to not be encoded in YUV, so no need to use return_false()
704 return false;
705 }
706
707 cinfo.out_color_space = JCS_YCbCr;
708 cinfo.raw_data_out = TRUE;
709
710 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only
711 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType);
712 return true;
713 }
714
715 set_dct_method(*this, &cinfo);
716
717 SkASSERT(1 == cinfo.scale_num);
718 cinfo.scale_denom = 1;
719
720 #ifdef ANDROID_RGB
721 cinfo.dither_mode = JDITHER_NONE;
722 #endif
723
724 /* image_width and image_height are the original dimensions, available
725 after jpeg_read_header(). To see the scaled dimensions, we have to call
726 jpeg_start_decompress(), and then read output_width and output_height.
727 */
728 if (!jpeg_start_decompress(&cinfo)) {
729 return return_false(cinfo, "start_decompress YUV8");
730 }
731
732 // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV.
733 // Again, not really an error.
734 if (!appears_to_be_yuv(cinfo)) {
735 return false;
736 }
737
738 if (!output_raw_data(cinfo, planes, rowBytes)) {
739 return return_false(cinfo, "output_raw_data");
740 }
741
742 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
743 jpeg_finish_decompress(&cinfo);
744
745 if (nullptr != colorSpace) {
746 *colorSpace = kJPEG_SkYUVColorSpace;
747 }
748
749 return true;
750 }
751
752 ///////////////////////////////////////////////////////////////////////////////
753
754 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
755 const void* SK_RESTRICT src, int width,
756 const SkPMColor* SK_RESTRICT ctable);
757
Write_32_RGB(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor *)758 static void Write_32_RGB(uint8_t* SK_RESTRICT dst,
759 const void* SK_RESTRICT srcRow, int width,
760 const SkPMColor*) {
761 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
762 while (--width >= 0) {
763 uint32_t c = *src++;
764 dst[0] = SkGetPackedR32(c);
765 dst[1] = SkGetPackedG32(c);
766 dst[2] = SkGetPackedB32(c);
767 dst += 3;
768 }
769 }
770
Write_4444_RGB(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor *)771 static void Write_4444_RGB(uint8_t* SK_RESTRICT dst,
772 const void* SK_RESTRICT srcRow, int width,
773 const SkPMColor*) {
774 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
775 while (--width >= 0) {
776 SkPMColor16 c = *src++;
777 dst[0] = SkPacked4444ToR32(c);
778 dst[1] = SkPacked4444ToG32(c);
779 dst[2] = SkPacked4444ToB32(c);
780 dst += 3;
781 }
782 }
783
Write_16_RGB(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor *)784 static void Write_16_RGB(uint8_t* SK_RESTRICT dst,
785 const void* SK_RESTRICT srcRow, int width,
786 const SkPMColor*) {
787 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
788 while (--width >= 0) {
789 uint16_t c = *src++;
790 dst[0] = SkPacked16ToR32(c);
791 dst[1] = SkPacked16ToG32(c);
792 dst[2] = SkPacked16ToB32(c);
793 dst += 3;
794 }
795 }
796
Write_Index_RGB(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor * SK_RESTRICT ctable)797 static void Write_Index_RGB(uint8_t* SK_RESTRICT dst,
798 const void* SK_RESTRICT srcRow, int width,
799 const SkPMColor* SK_RESTRICT ctable) {
800 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
801 while (--width >= 0) {
802 uint32_t c = ctable[*src++];
803 dst[0] = SkGetPackedR32(c);
804 dst[1] = SkGetPackedG32(c);
805 dst[2] = SkGetPackedB32(c);
806 dst += 3;
807 }
808 }
809
ChooseWriter(const SkBitmap & bm)810 static WriteScanline ChooseWriter(const SkBitmap& bm) {
811 switch (bm.colorType()) {
812 case kN32_SkColorType:
813 return Write_32_RGB;
814 case kRGB_565_SkColorType:
815 return Write_16_RGB;
816 case kARGB_4444_SkColorType:
817 return Write_4444_RGB;
818 case kIndex_8_SkColorType:
819 return Write_Index_RGB;
820 default:
821 return nullptr;
822 }
823 }
824
825 class SkJPEGImageEncoder : public SkImageEncoder {
826 protected:
onEncode(SkWStream * stream,const SkBitmap & bm,int quality)827 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
828 #ifdef TIME_ENCODE
829 SkAutoTime atm("JPEG Encode");
830 #endif
831
832 SkAutoLockPixels alp(bm);
833 if (nullptr == bm.getPixels()) {
834 return false;
835 }
836
837 jpeg_compress_struct cinfo;
838 skjpeg_error_mgr sk_err;
839 skjpeg_destination_mgr sk_wstream(stream);
840
841 // allocate these before set call setjmp
842 SkAutoTMalloc<uint8_t> oneRow;
843
844 cinfo.err = jpeg_std_error(&sk_err);
845 sk_err.error_exit = skjpeg_error_exit;
846 if (setjmp(sk_err.fJmpBuf)) {
847 return false;
848 }
849
850 // Keep after setjmp or mark volatile.
851 const WriteScanline writer = ChooseWriter(bm);
852 if (nullptr == writer) {
853 return false;
854 }
855
856 jpeg_create_compress(&cinfo);
857 cinfo.dest = &sk_wstream;
858 cinfo.image_width = bm.width();
859 cinfo.image_height = bm.height();
860 cinfo.input_components = 3;
861 // FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo?
862 cinfo.in_color_space = JCS_RGB;
863
864 // The gamma value is ignored by libjpeg-turbo.
865 cinfo.input_gamma = 1;
866
867 jpeg_set_defaults(&cinfo);
868
869 // Tells libjpeg-turbo to compute optimal Huffman coding tables
870 // for the image. This improves compression at the cost of
871 // slower encode performance.
872 cinfo.optimize_coding = TRUE;
873 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
874
875 jpeg_start_compress(&cinfo, TRUE);
876
877 const int width = bm.width();
878 uint8_t* oneRowP = oneRow.reset(width * 3);
879
880 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : nullptr;
881 const void* srcRow = bm.getPixels();
882
883 while (cinfo.next_scanline < cinfo.image_height) {
884 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
885
886 writer(oneRowP, srcRow, width, colors);
887 row_pointer[0] = oneRowP;
888 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
889 srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
890 }
891
892 jpeg_finish_compress(&cinfo);
893 jpeg_destroy_compress(&cinfo);
894
895 return true;
896 }
897 };
898
899 ///////////////////////////////////////////////////////////////////////////////
900 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
901 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
902 ///////////////////////////////////////////////////////////////////////////////
903
is_jpeg(SkStreamRewindable * stream)904 static bool is_jpeg(SkStreamRewindable* stream) {
905 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
906 static const size_t HEADER_SIZE = sizeof(gHeader);
907
908 char buffer[HEADER_SIZE];
909 size_t len = stream->read(buffer, HEADER_SIZE);
910
911 if (len != HEADER_SIZE) {
912 return false; // can't read enough
913 }
914 if (memcmp(buffer, gHeader, HEADER_SIZE)) {
915 return false;
916 }
917 return true;
918 }
919
920
sk_libjpeg_dfactory(SkStreamRewindable * stream)921 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
922 if (is_jpeg(stream)) {
923 return new SkJPEGImageDecoder;
924 }
925 return nullptr;
926 }
927
get_format_jpeg(SkStreamRewindable * stream)928 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
929 if (is_jpeg(stream)) {
930 return SkImageDecoder::kJPEG_Format;
931 }
932 return SkImageDecoder::kUnknown_Format;
933 }
934
sk_libjpeg_efactory(SkImageEncoder::Type t)935 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
936 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr;
937 }
938
939 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
940 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
941 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
942