2 * Copyright 2007 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkImageDecoder.h"
10 #include "SkImageEncoder.h"
11 #include "SkJpegUtility.h"
12 #include "SkColorPriv.h"
14 #include "SkScaledBitmapSampler.h"
16 #include "SkTemplates.h"
30 // These enable timing code that report milliseconds for an encoding/decoding
34 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
35 #define WE_CONVERT_TO_YUV
37 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
38 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
41 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS false
42 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS false
43 #else // !defined(SK_DEBUG)
44 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
45 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
46 #endif // defined(SK_DEBUG)
47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
48 "images.jpeg.suppressDecoderWarnings",
49 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
50 "Suppress most JPG warnings when calling decode functions.");
51 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
52 "images.jpeg.suppressDecoderErrors",
53 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
54 "Suppress most JPG error messages when decode "
57 //////////////////////////////////////////////////////////////////////////
58 //////////////////////////////////////////////////////////////////////////
60 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
61 #ifdef SK_BUILD_FOR_ANDROID
62 /* Check if the device indicates that it has a large amount of system memory
63 * if so, increase the memory allocation to 30MB instead of the default 5MB.
65 #ifdef ANDROID_LARGE_MEMORY_DEVICE
66 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
68 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
70 #endif // SK_BUILD_FOR_ANDROID
73 //////////////////////////////////////////////////////////////////////////
74 //////////////////////////////////////////////////////////////////////////
76 static void do_nothing_emit_message(jpeg_common_struct*, int) {
79 static void do_nothing_output_message(j_common_ptr) {
83 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
84 SkASSERT(cinfo != NULL);
85 SkASSERT(src_mgr != NULL);
86 jpeg_create_decompress(cinfo);
87 overwrite_mem_buffer_size(cinfo);
89 /* To suppress warnings with a SK_DEBUG binary, set the
90 * environment variable "skia_images_jpeg_suppressDecoderWarnings"
91 * to "true". Inside a program that links to skia:
92 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
93 if (c_suppressJPEGImageDecoderWarnings) {
94 cinfo->err->emit_message = &do_nothing_emit_message;
96 /* To suppress error messages with a SK_DEBUG binary, set the
97 * environment variable "skia_images_jpeg_suppressDecoderErrors"
98 * to "true". Inside a program that links to skia:
99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
100 if (c_suppressJPEGImageDecoderErrors) {
101 cinfo->err->output_message = &do_nothing_output_message;
105 #ifdef SK_BUILD_FOR_ANDROID
106 class SkJPEGImageIndex {
108 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
109 : fSrcMgr(stream, decoder)
110 , fInfoInitialized(false)
111 , fHuffmanCreated(false)
112 , fDecompressStarted(false)
114 SkDEBUGCODE(fReadHeaderSucceeded = false;)
117 ~SkJPEGImageIndex() {
118 if (fHuffmanCreated) {
119 // Set to false before calling the libjpeg function, in case
120 // the libjpeg function calls longjmp. Our setjmp handler may
121 // attempt to delete this SkJPEGImageIndex, thus entering this
122 // destructor again. Setting fHuffmanCreated to false first
123 // prevents an infinite loop.
124 fHuffmanCreated = false;
125 jpeg_destroy_huffman_index(&fHuffmanIndex);
127 if (fDecompressStarted) {
128 // Like fHuffmanCreated, set to false before calling libjpeg
129 // function to prevent potential infinite loop.
130 fDecompressStarted = false;
131 jpeg_finish_decompress(&fCInfo);
133 if (fInfoInitialized) {
139 * Destroy the cinfo struct.
140 * After this call, if a huffman index was already built, it
141 * can be used after calling initializeInfoAndReadHeader
142 * again. Must not be called after startTileDecompress except
146 SkASSERT(fInfoInitialized);
147 SkASSERT(!fDecompressStarted);
148 // Like fHuffmanCreated, set to false before calling libjpeg
149 // function to prevent potential infinite loop.
150 fInfoInitialized = false;
151 jpeg_destroy_decompress(&fCInfo);
152 SkDEBUGCODE(fReadHeaderSucceeded = false;)
156 * Initialize the cinfo struct.
157 * Calls jpeg_create_decompress, makes customizations, and
158 * finally calls jpeg_read_header. Returns true if jpeg_read_header
159 * returns JPEG_HEADER_OK.
160 * If cinfo was already initialized, destroyInfo must be called to
161 * destroy the old one. Must not be called after startTileDecompress.
163 bool initializeInfoAndReadHeader() {
164 SkASSERT(!fInfoInitialized && !fDecompressStarted);
165 initialize_info(&fCInfo, &fSrcMgr);
166 fInfoInitialized = true;
167 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
168 SkDEBUGCODE(fReadHeaderSucceeded = success;)
172 jpeg_decompress_struct* cinfo() { return &fCInfo; }
174 huffman_index* huffmanIndex() { return &fHuffmanIndex; }
177 * Build the index to be used for tile based decoding.
178 * Must only be called after a successful call to
179 * initializeInfoAndReadHeader and must not be called more
182 bool buildHuffmanIndex() {
183 SkASSERT(fReadHeaderSucceeded);
184 SkASSERT(!fHuffmanCreated);
185 jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
186 SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
187 fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
188 return fHuffmanCreated;
192 * Start tile based decoding. Must only be called after a
193 * successful call to buildHuffmanIndex, and must only be
196 bool startTileDecompress() {
197 SkASSERT(fHuffmanCreated);
198 SkASSERT(fReadHeaderSucceeded);
199 SkASSERT(!fDecompressStarted);
200 if (jpeg_start_tile_decompress(&fCInfo)) {
201 fDecompressStarted = true;
208 skjpeg_source_mgr fSrcMgr;
209 jpeg_decompress_struct fCInfo;
210 huffman_index fHuffmanIndex;
211 bool fInfoInitialized;
212 bool fHuffmanCreated;
213 bool fDecompressStarted;
214 SkDEBUGCODE(bool fReadHeaderSucceeded;)
218 class SkJPEGImageDecoder : public SkImageDecoder {
220 #ifdef SK_BUILD_FOR_ANDROID
221 SkJPEGImageDecoder() {
227 virtual ~SkJPEGImageDecoder() {
228 SkDELETE(fImageIndex);
232 virtual Format getFormat() const {
237 #ifdef SK_BUILD_FOR_ANDROID
238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
244 #ifdef SK_BUILD_FOR_ANDROID
245 SkJPEGImageIndex* fImageIndex;
251 * Determine the appropriate bitmap colortype and out_color_space based on
252 * both the preference of the caller and the jpeg_color_space on the
253 * jpeg_decompress_struct passed in.
254 * Must be called after jpeg_read_header.
256 SkColorType getBitmapColorType(jpeg_decompress_struct*);
258 typedef SkImageDecoder INHERITED;
261 //////////////////////////////////////////////////////////////////////////
263 /* Automatically clean up after throwing an exception */
264 class JPEGAutoClean {
266 JPEGAutoClean(): cinfo_ptr(NULL) {}
269 jpeg_destroy_decompress(cinfo_ptr);
272 void set(jpeg_decompress_struct* info) {
276 jpeg_decompress_struct* cinfo_ptr;
279 ///////////////////////////////////////////////////////////////////////////////
281 /* If we need to better match the request, we might examine the image and
282 output dimensions, and determine if the downsampling jpeg provided is
283 not sufficient. If so, we can recompute a modified sampleSize value to
284 make up the difference.
286 To skip this additional scaling, just set sampleSize = 1; below.
288 static int recompute_sampleSize(int sampleSize,
289 const jpeg_decompress_struct& cinfo) {
290 return sampleSize * cinfo.output_width / cinfo.image_width;
293 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
294 /* These are initialized to 0, so if they have non-zero values, we assume
295 they are "valid" (i.e. have been computed by libjpeg)
297 return 0 != cinfo.output_width && 0 != cinfo.output_height;
300 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
301 for (int i = 0; i < count; i++) {
302 JSAMPLE* rowptr = (JSAMPLE*)buffer;
303 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
304 if (1 != row_count) {
311 #ifdef SK_BUILD_FOR_ANDROID
312 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
313 huffman_index *index, void* buffer, int count) {
314 for (int i = 0; i < count; i++) {
315 JSAMPLE* rowptr = (JSAMPLE*)buffer;
316 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
317 if (1 != row_count) {
325 // This guy exists just to aid in debugging, as it allows debuggers to just
326 // set a break-point in one place to see all error exists.
327 static bool return_false(const jpeg_decompress_struct& cinfo,
328 const SkBitmap& bm, const char caller[]) {
329 if (!(c_suppressJPEGImageDecoderErrors)) {
330 char buffer[JMSG_LENGTH_MAX];
331 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
332 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
333 cinfo.err->msg_code, buffer, caller, bm.width(), bm.height());
335 return false; // must always return false
338 // Convert a scanline of CMYK samples to RGBX in place. Note that this
339 // method moves the "scanline" pointer in its processing
340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
341 // At this point we've received CMYK pixels from libjpeg. We
342 // perform a crude conversion to RGB (based on the formulae
343 // from easyrgb.com):
345 // C = ( C * (1 - K) + K ) // for each CMY component
347 // R = ( 1 - C ) * 255 // for each RGB component
348 // Unfortunately we are seeing inverted CMYK so all the original terms
349 // are 1-. This yields:
351 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
352 // The conversion from CMY->RGB remains the same
353 for (unsigned int x = 0; x < width; ++x, scanline += 4) {
354 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
355 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
356 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
362 * Common code for setting the error manager.
364 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
365 SkASSERT(cinfo != NULL);
366 SkASSERT(errorManager != NULL);
367 cinfo->err = jpeg_std_error(errorManager);
368 errorManager->error_exit = skjpeg_error_exit;
372 * Common code for turning off upsampling and smoothing. Turning these
373 * off helps performance without showing noticable differences in the
376 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
377 SkASSERT(cinfo != NULL);
378 /* this gives about 30% performance improvement. In theory it may
379 reduce the visual quality, in practice I'm not seeing a difference
381 cinfo->do_fancy_upsampling = 0;
383 /* this gives another few percents */
384 cinfo->do_block_smoothing = 0;
388 * Common code for setting the dct method.
390 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
391 SkASSERT(cinfo != NULL);
392 #ifdef DCT_IFAST_SUPPORTED
393 if (decoder.getPreferQualityOverSpeed()) {
394 cinfo->dct_method = JDCT_ISLOW;
396 cinfo->dct_method = JDCT_IFAST;
399 cinfo->dct_method = JDCT_ISLOW;
403 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
404 SkASSERT(cinfo != NULL);
406 SrcDepth srcDepth = k32Bit_SrcDepth;
407 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
408 srcDepth = k8BitGray_SrcDepth;
411 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
413 case kAlpha_8_SkColorType:
414 // Only respect A8 colortype if the original is grayscale,
415 // in which case we will treat the grayscale as alpha
417 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
418 colorType = kN32_SkColorType;
421 case kN32_SkColorType:
423 case kARGB_4444_SkColorType:
425 case kRGB_565_SkColorType:
426 // These are acceptable destination colortypes.
429 // Force all other colortypes to 8888.
430 colorType = kN32_SkColorType;
434 switch (cinfo->jpeg_color_space) {
438 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
439 // so libjpeg will give us CMYK samples back and we will later
440 // manually convert them to RGB
441 cinfo->out_color_space = JCS_CMYK;
444 if (kAlpha_8_SkColorType == colorType) {
445 cinfo->out_color_space = JCS_GRAYSCALE;
448 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
449 // colortype. Fall through to set to the default.
451 cinfo->out_color_space = JCS_RGB;
458 * Based on the colortype and dither mode, adjust out_color_space and
459 * dither_mode of cinfo. Only does work in ANDROID_RGB
461 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
462 SkColorType colorType,
463 const SkImageDecoder& decoder) {
464 SkASSERT(cinfo != NULL);
466 cinfo->dither_mode = JDITHER_NONE;
467 if (JCS_CMYK == cinfo->out_color_space) {
471 case kN32_SkColorType:
472 cinfo->out_color_space = JCS_RGBA_8888;
474 case kRGB_565_SkColorType:
475 cinfo->out_color_space = JCS_RGB_565;
476 if (decoder.getDitherImage()) {
477 cinfo->dither_mode = JDITHER_ORDERED;
488 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
489 Used when decoding fails partway through reading scanlines to fill
491 static void fill_below_level(int y, SkBitmap* bitmap) {
492 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
493 SkCanvas canvas(*bitmap);
494 canvas.clipRect(SkRect::Make(rect));
495 canvas.drawColor(SK_ColorWHITE);
499 * Get the config and bytes per pixel of the source data. Return
500 * whether the data is supported.
502 static bool get_src_config(const jpeg_decompress_struct& cinfo,
503 SkScaledBitmapSampler::SrcConfig* sc,
504 int* srcBytesPerPixel) {
505 SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
506 if (JCS_CMYK == cinfo.out_color_space) {
507 // In this case we will manually convert the CMYK values to RGB
508 *sc = SkScaledBitmapSampler::kRGBX;
509 // The CMYK work-around relies on 4 components per pixel here
510 *srcBytesPerPixel = 4;
511 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
512 *sc = SkScaledBitmapSampler::kRGB;
513 *srcBytesPerPixel = 3;
515 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
516 *sc = SkScaledBitmapSampler::kRGBX;
517 *srcBytesPerPixel = 4;
518 } else if (JCS_RGB_565 == cinfo.out_color_space) {
519 *sc = SkScaledBitmapSampler::kRGB_565;
520 *srcBytesPerPixel = 2;
522 } else if (1 == cinfo.out_color_components &&
523 JCS_GRAYSCALE == cinfo.out_color_space) {
524 *sc = SkScaledBitmapSampler::kGray;
525 *srcBytesPerPixel = 1;
532 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
534 SkAutoTime atm("JPEG Decode");
537 JPEGAutoClean autoClean;
539 jpeg_decompress_struct cinfo;
540 skjpeg_source_mgr srcManager(stream, this);
542 skjpeg_error_mgr errorManager;
543 set_error_mgr(&cinfo, &errorManager);
545 // All objects need to be instantiated before this setjmp call so that
546 // they will be cleaned up properly if an error occurs.
547 if (setjmp(errorManager.fJmpBuf)) {
548 return return_false(cinfo, *bm, "setjmp");
551 initialize_info(&cinfo, &srcManager);
552 autoClean.set(&cinfo);
554 int status = jpeg_read_header(&cinfo, true);
555 if (status != JPEG_HEADER_OK) {
556 return return_false(cinfo, *bm, "read_header");
559 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it
560 can) much faster that we, just use their num/denom api to approximate
563 int sampleSize = this->getSampleSize();
565 set_dct_method(*this, &cinfo);
567 SkASSERT(1 == cinfo.scale_num);
568 cinfo.scale_denom = sampleSize;
570 turn_off_visual_optimizations(&cinfo);
572 const SkColorType colorType = this->getBitmapColorType(&cinfo);
573 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
574 kPremul_SkAlphaType : kOpaque_SkAlphaType;
576 adjust_out_color_space_and_dither(&cinfo, colorType, *this);
578 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
579 // Assume an A8 bitmap is not opaque to avoid the check of each
580 // individual pixel. It is very unlikely to be opaque, since
581 // an opaque A8 bitmap would not be very interesting.
582 // Otherwise, a jpeg image is opaque.
583 return bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
584 colorType, alphaType));
587 /* image_width and image_height are the original dimensions, available
588 after jpeg_read_header(). To see the scaled dimensions, we have to call
589 jpeg_start_decompress(), and then read output_width and output_height.
591 if (!jpeg_start_decompress(&cinfo)) {
592 /* If we failed here, we may still have enough information to return
593 to the caller if they just wanted (subsampled bounds). If sampleSize
594 was 1, then we would have already returned. Thus we just check if
595 we're in kDecodeBounds_Mode, and that we have valid output sizes.
597 One reason to fail here is that we have insufficient stream data
598 to complete the setup. However, output dimensions seem to get
599 computed very early, which is why this special check can pay off.
601 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
602 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
603 recompute_sampleSize(sampleSize, cinfo));
604 // Assume an A8 bitmap is not opaque to avoid the check of each
605 // individual pixel. It is very unlikely to be opaque, since
606 // an opaque A8 bitmap would not be very interesting.
607 // Otherwise, a jpeg image is opaque.
608 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
609 colorType, alphaType));
611 return return_false(cinfo, *bm, "start_decompress");
614 sampleSize = recompute_sampleSize(sampleSize, cinfo);
616 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
617 // should we allow the Chooser (if present) to pick a colortype for us???
618 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_height)) {
619 return return_false(cinfo, *bm, "chooseFromOneChoice");
623 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
624 // Assume an A8 bitmap is not opaque to avoid the check of each
625 // individual pixel. It is very unlikely to be opaque, since
626 // an opaque A8 bitmap would not be very interesting.
627 // Otherwise, a jpeg image is opaque.
628 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
629 colorType, alphaType));
630 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
633 if (!this->allocPixelRef(bm, NULL)) {
634 return return_false(cinfo, *bm, "allocPixelRef");
637 SkAutoLockPixels alp(*bm);
640 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
641 a significant performance boost.
643 if (sampleSize == 1 &&
644 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
645 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
647 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
648 INT32 const bpr = bm->rowBytes();
650 while (cinfo.output_scanline < cinfo.output_height) {
651 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
652 if (0 == row_count) {
653 // if row_count == 0, then we didn't get a scanline,
654 // so return early. We will return a partial image.
655 fill_below_level(cinfo.output_scanline, bm);
656 cinfo.output_scanline = cinfo.output_height;
657 break; // Skip to jpeg_finish_decompress()
659 if (this->shouldCancelDecode()) {
660 return return_false(cinfo, *bm, "shouldCancelDecode");
664 jpeg_finish_decompress(&cinfo);
669 // check for supported formats
670 SkScaledBitmapSampler::SrcConfig sc;
671 int srcBytesPerPixel;
673 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
674 return return_false(cinfo, *bm, "jpeg colorspace");
677 if (!sampler.begin(bm, sc, *this)) {
678 return return_false(cinfo, *bm, "sampler.begin");
681 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
682 uint8_t* srcRow = (uint8_t*)srcStorage.get();
684 // Possibly skip initial rows [sampler.srcY0]
685 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
686 return return_false(cinfo, *bm, "skip rows");
689 // now loop through scanlines until y == bm->height() - 1
690 for (int y = 0;; y++) {
691 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
692 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
693 if (0 == row_count) {
694 // if row_count == 0, then we didn't get a scanline,
695 // so return early. We will return a partial image.
696 fill_below_level(y, bm);
697 cinfo.output_scanline = cinfo.output_height;
698 break; // Skip to jpeg_finish_decompress()
700 if (this->shouldCancelDecode()) {
701 return return_false(cinfo, *bm, "shouldCancelDecode");
704 if (JCS_CMYK == cinfo.out_color_space) {
705 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
708 sampler.next(srcRow);
709 if (bm->height() - 1 == y) {
714 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
715 return return_false(cinfo, *bm, "skip rows");
719 // we formally skip the rest, so we don't get a complaint from libjpeg
720 if (!skip_src_rows(&cinfo, srcRow,
721 cinfo.output_height - cinfo.output_scanline)) {
722 return return_false(cinfo, *bm, "skip rows");
724 jpeg_finish_decompress(&cinfo);
729 #ifdef SK_BUILD_FOR_ANDROID
730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
732 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
733 jpeg_decompress_struct* cinfo = imageIndex->cinfo();
735 skjpeg_error_mgr sk_err;
736 set_error_mgr(cinfo, &sk_err);
738 // All objects need to be instantiated before this setjmp call so that
739 // they will be cleaned up properly if an error occurs.
740 if (setjmp(sk_err.fJmpBuf)) {
744 // create the cinfo used to create/build the huffmanIndex
745 if (!imageIndex->initializeInfoAndReadHeader()) {
749 if (!imageIndex->buildHuffmanIndex()) {
753 // destroy the cinfo used to create/build the huffman index
754 imageIndex->destroyInfo();
756 // Init decoder to image decode mode
757 if (!imageIndex->initializeInfoAndReadHeader()) {
761 // FIXME: This sets cinfo->out_color_space, which we may change later
762 // based on the config in onDecodeSubset. This should be fine, since
763 // jpeg_init_read_tile_scanline will check out_color_space again after
764 // that change (when it calls jinit_color_deconverter).
765 (void) this->getBitmapColorType(cinfo);
767 turn_off_visual_optimizations(cinfo);
769 // instead of jpeg_start_decompress() we start a tiled decompress
770 if (!imageIndex->startTileDecompress()) {
774 SkASSERT(1 == cinfo->scale_num);
775 fImageWidth = cinfo->output_width;
776 fImageHeight = cinfo->output_height;
779 *width = fImageWidth;
782 *height = fImageHeight;
785 SkDELETE(fImageIndex);
786 fImageIndex = imageIndex.detach();
791 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
792 if (NULL == fImageIndex) {
795 jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
797 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
798 if (!rect.intersect(region)) {
799 // If the requested region is entirely outside the image return false
804 skjpeg_error_mgr errorManager;
805 set_error_mgr(cinfo, &errorManager);
807 if (setjmp(errorManager.fJmpBuf)) {
811 int requestedSampleSize = this->getSampleSize();
812 cinfo->scale_denom = requestedSampleSize;
814 set_dct_method(*this, cinfo);
816 const SkColorType colorType = this->getBitmapColorType(cinfo);
817 adjust_out_color_space_and_dither(cinfo, colorType, *this);
819 int startX = rect.fLeft;
820 int startY = rect.fTop;
821 int width = rect.width();
822 int height = rect.height();
824 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
825 &startX, &startY, &width, &height);
826 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
827 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
829 SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
832 // Assume an A8 bitmap is not opaque to avoid the check of each
833 // individual pixel. It is very unlikely to be opaque, since
834 // an opaque A8 bitmap would not be very interesting.
835 // Otherwise, a jpeg image is opaque.
836 bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType,
837 kAlpha_8_SkColorType == colorType ?
838 kPremul_SkAlphaType : kOpaque_SkAlphaType));
840 // Check ahead of time if the swap(dest, src) is possible or not.
841 // If yes, then we will stick to AllocPixelRef since it's cheaper with the
842 // swap happening. If no, then we will use alloc to allocate pixels to
843 // prevent garbage collection.
844 int w = rect.width() / actualSampleSize;
845 int h = rect.height() / actualSampleSize;
846 bool swapOnly = (rect == region) && bm->isNull() &&
847 (w == bitmap.width()) && (h == bitmap.height()) &&
848 ((startX - rect.x()) / actualSampleSize == 0) &&
849 ((startY - rect.y()) / actualSampleSize == 0);
851 if (!this->allocPixelRef(&bitmap, NULL)) {
852 return return_false(*cinfo, bitmap, "allocPixelRef");
855 if (!bitmap.tryAllocPixels()) {
856 return return_false(*cinfo, bitmap, "allocPixels");
860 SkAutoLockPixels alp(bitmap);
863 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
864 a significant performance boost.
866 if (skiaSampleSize == 1 &&
867 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) ||
868 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565)))
870 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
871 INT32 const bpr = bitmap.rowBytes();
872 int rowTotalCount = 0;
874 while (rowTotalCount < height) {
875 int rowCount = jpeg_read_tile_scanline(cinfo,
876 fImageIndex->huffmanIndex(),
878 // if rowCount == 0, then we didn't get a scanline, so abort.
879 // onDecodeSubset() relies on onBuildTileIndex(), which
880 // needs a complete image to succeed.
882 return return_false(*cinfo, bitmap, "read_scanlines");
884 if (this->shouldCancelDecode()) {
885 return return_false(*cinfo, bitmap, "shouldCancelDecode");
887 rowTotalCount += rowCount;
894 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
895 region.width(), region.height(), startX, startY);
901 // check for supported formats
902 SkScaledBitmapSampler::SrcConfig sc;
903 int srcBytesPerPixel;
905 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
906 return return_false(*cinfo, *bm, "jpeg colorspace");
909 if (!sampler.begin(&bitmap, sc, *this)) {
910 return return_false(*cinfo, bitmap, "sampler.begin");
913 SkAutoMalloc srcStorage(width * srcBytesPerPixel);
914 uint8_t* srcRow = (uint8_t*)srcStorage.get();
916 // Possibly skip initial rows [sampler.srcY0]
917 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
918 return return_false(*cinfo, bitmap, "skip rows");
921 // now loop through scanlines until y == bitmap->height() - 1
922 for (int y = 0;; y++) {
923 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
924 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
925 // if row_count == 0, then we didn't get a scanline, so abort.
926 // onDecodeSubset() relies on onBuildTileIndex(), which
927 // needs a complete image to succeed.
928 if (0 == row_count) {
929 return return_false(*cinfo, bitmap, "read_scanlines");
931 if (this->shouldCancelDecode()) {
932 return return_false(*cinfo, bitmap, "shouldCancelDecode");
935 if (JCS_CMYK == cinfo->out_color_space) {
936 convert_CMYK_to_RGB(srcRow, width);
939 sampler.next(srcRow);
940 if (bitmap.height() - 1 == y) {
945 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
946 sampler.srcDY() - 1)) {
947 return return_false(*cinfo, bitmap, "skip rows");
953 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
954 region.width(), region.height(), startX, startY);
960 ///////////////////////////////////////////////////////////////////////////////
962 #include "SkColorPriv.h"
964 // taken from jcolor.c in libjpeg
965 #if 0 // 16bit - precise but slow
966 #define CYR 19595 // 0.299
967 #define CYG 38470 // 0.587
968 #define CYB 7471 // 0.114
970 #define CUR -11059 // -0.16874
971 #define CUG -21709 // -0.33126
972 #define CUB 32768 // 0.5
974 #define CVR 32768 // 0.5
975 #define CVG -27439 // -0.41869
976 #define CVB -5329 // -0.08131
979 #else // 8bit - fast, slightly less precise
980 #define CYR 77 // 0.299
981 #define CYG 150 // 0.587
982 #define CYB 29 // 0.114
984 #define CUR -43 // -0.16874
985 #define CUG -85 // -0.33126
986 #define CUB 128 // 0.5
988 #define CVR 128 // 0.5
989 #define CVG -107 // -0.41869
990 #define CVB -21 // -0.08131
995 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
996 int r = SkGetPackedR32(c);
997 int g = SkGetPackedG32(c);
998 int b = SkGetPackedB32(c);
1000 int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
1001 int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
1002 int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
1005 dst[1] = SkToU8(u + 128);
1006 dst[2] = SkToU8(v + 128);
1009 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
1010 int r = SkGetPackedR4444(c);
1011 int g = SkGetPackedG4444(c);
1012 int b = SkGetPackedB4444(c);
1014 int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
1015 int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
1016 int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
1019 dst[1] = SkToU8(u + 128);
1020 dst[2] = SkToU8(v + 128);
1023 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
1024 int r = SkGetPackedR16(c);
1025 int g = SkGetPackedG16(c);
1026 int b = SkGetPackedB16(c);
1028 int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
1029 int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
1030 int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
1033 dst[1] = SkToU8(u + 128);
1034 dst[2] = SkToU8(v + 128);
1037 ///////////////////////////////////////////////////////////////////////////////
1039 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
1040 const void* SK_RESTRICT src, int width,
1041 const SkPMColor* SK_RESTRICT ctable);
1043 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
1044 const void* SK_RESTRICT srcRow, int width,
1046 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
1047 while (--width >= 0) {
1048 #ifdef WE_CONVERT_TO_YUV
1049 rgb2yuv_32(dst, *src++);
1051 uint32_t c = *src++;
1052 dst[0] = SkGetPackedR32(c);
1053 dst[1] = SkGetPackedG32(c);
1054 dst[2] = SkGetPackedB32(c);
1060 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
1061 const void* SK_RESTRICT srcRow, int width,
1063 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
1064 while (--width >= 0) {
1065 #ifdef WE_CONVERT_TO_YUV
1066 rgb2yuv_4444(dst, *src++);
1068 SkPMColor16 c = *src++;
1069 dst[0] = SkPacked4444ToR32(c);
1070 dst[1] = SkPacked4444ToG32(c);
1071 dst[2] = SkPacked4444ToB32(c);
1077 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
1078 const void* SK_RESTRICT srcRow, int width,
1080 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
1081 while (--width >= 0) {
1082 #ifdef WE_CONVERT_TO_YUV
1083 rgb2yuv_16(dst, *src++);
1085 uint16_t c = *src++;
1086 dst[0] = SkPacked16ToR32(c);
1087 dst[1] = SkPacked16ToG32(c);
1088 dst[2] = SkPacked16ToB32(c);
1094 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
1095 const void* SK_RESTRICT srcRow, int width,
1096 const SkPMColor* SK_RESTRICT ctable) {
1097 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
1098 while (--width >= 0) {
1099 #ifdef WE_CONVERT_TO_YUV
1100 rgb2yuv_32(dst, ctable[*src++]);
1102 uint32_t c = ctable[*src++];
1103 dst[0] = SkGetPackedR32(c);
1104 dst[1] = SkGetPackedG32(c);
1105 dst[2] = SkGetPackedB32(c);
1111 static WriteScanline ChooseWriter(const SkBitmap& bm) {
1112 switch (bm.colorType()) {
1113 case kN32_SkColorType:
1114 return Write_32_YUV;
1115 case kRGB_565_SkColorType:
1116 return Write_16_YUV;
1117 case kARGB_4444_SkColorType:
1118 return Write_4444_YUV;
1119 case kIndex_8_SkColorType:
1120 return Write_Index_YUV;
1126 class SkJPEGImageEncoder : public SkImageEncoder {
1128 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
1130 SkAutoTime atm("JPEG Encode");
1133 SkAutoLockPixels alp(bm);
1134 if (NULL == bm.getPixels()) {
1138 jpeg_compress_struct cinfo;
1139 skjpeg_error_mgr sk_err;
1140 skjpeg_destination_mgr sk_wstream(stream);
1142 // allocate these before set call setjmp
1143 SkAutoMalloc oneRow;
1144 SkAutoLockColors ctLocker;
1146 cinfo.err = jpeg_std_error(&sk_err);
1147 sk_err.error_exit = skjpeg_error_exit;
1148 if (setjmp(sk_err.fJmpBuf)) {
1152 // Keep after setjmp or mark volatile.
1153 const WriteScanline writer = ChooseWriter(bm);
1154 if (NULL == writer) {
1158 jpeg_create_compress(&cinfo);
1159 cinfo.dest = &sk_wstream;
1160 cinfo.image_width = bm.width();
1161 cinfo.image_height = bm.height();
1162 cinfo.input_components = 3;
1163 #ifdef WE_CONVERT_TO_YUV
1164 cinfo.in_color_space = JCS_YCbCr;
1166 cinfo.in_color_space = JCS_RGB;
1168 cinfo.input_gamma = 1;
1170 jpeg_set_defaults(&cinfo);
1171 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
1172 #ifdef DCT_IFAST_SUPPORTED
1173 cinfo.dct_method = JDCT_IFAST;
1176 jpeg_start_compress(&cinfo, TRUE);
1178 const int width = bm.width();
1179 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3);
1181 const SkPMColor* colors = ctLocker.lockColors(bm);
1182 const void* srcRow = bm.getPixels();
1184 while (cinfo.next_scanline < cinfo.image_height) {
1185 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
1187 writer(oneRowP, srcRow, width, colors);
1188 row_pointer[0] = oneRowP;
1189 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
1190 srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
1193 jpeg_finish_compress(&cinfo);
1194 jpeg_destroy_compress(&cinfo);
1200 ///////////////////////////////////////////////////////////////////////////////
1201 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
1202 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
1203 ///////////////////////////////////////////////////////////////////////////////
1205 static bool is_jpeg(SkStreamRewindable* stream) {
1206 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
1207 static const size_t HEADER_SIZE = sizeof(gHeader);
1209 char buffer[HEADER_SIZE];
1210 size_t len = stream->read(buffer, HEADER_SIZE);
1212 if (len != HEADER_SIZE) {
1213 return false; // can't read enough
1215 if (memcmp(buffer, gHeader, HEADER_SIZE)) {
1222 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
1223 if (is_jpeg(stream)) {
1224 return SkNEW(SkJPEGImageDecoder);
1229 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
1230 if (is_jpeg(stream)) {
1231 return SkImageDecoder::kJPEG_Format;
1233 return SkImageDecoder::kUnknown_Format;
1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1237 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);