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 // Takes ownership of stream.
109 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
110 : fSrcMgr(stream, decoder)
112 , fInfoInitialized(false)
113 , fHuffmanCreated(false)
114 , fDecompressStarted(false)
116 SkDEBUGCODE(fReadHeaderSucceeded = false;)
119 ~SkJPEGImageIndex() {
120 if (fHuffmanCreated) {
121 // Set to false before calling the libjpeg function, in case
122 // the libjpeg function calls longjmp. Our setjmp handler may
123 // attempt to delete this SkJPEGImageIndex, thus entering this
124 // destructor again. Setting fHuffmanCreated to false first
125 // prevents an infinite loop.
126 fHuffmanCreated = false;
127 jpeg_destroy_huffman_index(&fHuffmanIndex);
129 if (fDecompressStarted) {
130 // Like fHuffmanCreated, set to false before calling libjpeg
131 // function to prevent potential infinite loop.
132 fDecompressStarted = false;
133 jpeg_finish_decompress(&fCInfo);
135 if (fInfoInitialized) {
141 * Destroy the cinfo struct.
142 * After this call, if a huffman index was already built, it
143 * can be used after calling initializeInfoAndReadHeader
144 * again. Must not be called after startTileDecompress except
148 SkASSERT(fInfoInitialized);
149 SkASSERT(!fDecompressStarted);
150 // Like fHuffmanCreated, set to false before calling libjpeg
151 // function to prevent potential infinite loop.
152 fInfoInitialized = false;
153 jpeg_destroy_decompress(&fCInfo);
154 SkDEBUGCODE(fReadHeaderSucceeded = false;)
158 * Initialize the cinfo struct.
159 * Calls jpeg_create_decompress, makes customizations, and
160 * finally calls jpeg_read_header. Returns true if jpeg_read_header
161 * returns JPEG_HEADER_OK.
162 * If cinfo was already initialized, destroyInfo must be called to
163 * destroy the old one. Must not be called after startTileDecompress.
165 bool initializeInfoAndReadHeader() {
166 SkASSERT(!fInfoInitialized && !fDecompressStarted);
167 initialize_info(&fCInfo, &fSrcMgr);
168 fInfoInitialized = true;
169 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
170 SkDEBUGCODE(fReadHeaderSucceeded = success;)
174 jpeg_decompress_struct* cinfo() { return &fCInfo; }
176 huffman_index* huffmanIndex() { return &fHuffmanIndex; }
179 * Build the index to be used for tile based decoding.
180 * Must only be called after a successful call to
181 * initializeInfoAndReadHeader and must not be called more
184 bool buildHuffmanIndex() {
185 SkASSERT(fReadHeaderSucceeded);
186 SkASSERT(!fHuffmanCreated);
187 jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
188 SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
189 fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
190 return fHuffmanCreated;
194 * Start tile based decoding. Must only be called after a
195 * successful call to buildHuffmanIndex, and must only be
198 bool startTileDecompress() {
199 SkASSERT(fHuffmanCreated);
200 SkASSERT(fReadHeaderSucceeded);
201 SkASSERT(!fDecompressStarted);
202 if (jpeg_start_tile_decompress(&fCInfo)) {
203 fDecompressStarted = true;
210 skjpeg_source_mgr fSrcMgr;
211 SkAutoTDelete<SkStream> fStream;
212 jpeg_decompress_struct fCInfo;
213 huffman_index fHuffmanIndex;
214 bool fInfoInitialized;
215 bool fHuffmanCreated;
216 bool fDecompressStarted;
217 SkDEBUGCODE(bool fReadHeaderSucceeded;)
221 class SkJPEGImageDecoder : public SkImageDecoder {
223 #ifdef SK_BUILD_FOR_ANDROID
224 SkJPEGImageDecoder() {
230 virtual ~SkJPEGImageDecoder() {
231 SkDELETE(fImageIndex);
235 Format getFormat() const SK_OVERRIDE {
240 #ifdef SK_BUILD_FOR_ANDROID
241 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
242 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
244 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
245 virtual bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
246 void* planes[3], size_t rowBytes[3],
247 SkYUVColorSpace* colorSpace) SK_OVERRIDE;
250 #ifdef SK_BUILD_FOR_ANDROID
251 SkJPEGImageIndex* fImageIndex;
257 * Determine the appropriate bitmap colortype and out_color_space based on
258 * both the preference of the caller and the jpeg_color_space on the
259 * jpeg_decompress_struct passed in.
260 * Must be called after jpeg_read_header.
262 SkColorType getBitmapColorType(jpeg_decompress_struct*);
264 typedef SkImageDecoder INHERITED;
267 //////////////////////////////////////////////////////////////////////////
269 /* Automatically clean up after throwing an exception */
270 class JPEGAutoClean {
272 JPEGAutoClean(): cinfo_ptr(NULL) {}
275 jpeg_destroy_decompress(cinfo_ptr);
278 void set(jpeg_decompress_struct* info) {
282 jpeg_decompress_struct* cinfo_ptr;
285 ///////////////////////////////////////////////////////////////////////////////
287 /* If we need to better match the request, we might examine the image and
288 output dimensions, and determine if the downsampling jpeg provided is
289 not sufficient. If so, we can recompute a modified sampleSize value to
290 make up the difference.
292 To skip this additional scaling, just set sampleSize = 1; below.
294 static int recompute_sampleSize(int sampleSize,
295 const jpeg_decompress_struct& cinfo) {
296 return sampleSize * cinfo.output_width / cinfo.image_width;
299 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
300 /* These are initialized to 0, so if they have non-zero values, we assume
301 they are "valid" (i.e. have been computed by libjpeg)
303 return 0 != cinfo.output_width && 0 != cinfo.output_height;
306 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
307 for (int i = 0; i < count; i++) {
308 JSAMPLE* rowptr = (JSAMPLE*)buffer;
309 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
310 if (1 != row_count) {
317 #ifdef SK_BUILD_FOR_ANDROID
318 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
319 huffman_index *index, void* buffer, int count) {
320 for (int i = 0; i < count; i++) {
321 JSAMPLE* rowptr = (JSAMPLE*)buffer;
322 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
323 if (1 != row_count) {
331 ///////////////////////////////////////////////////////////////////////////////
333 // This guy exists just to aid in debugging, as it allows debuggers to just
334 // set a break-point in one place to see all error exists.
335 static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo,
336 int width, int height, const char caller[]) {
337 if (!(c_suppressJPEGImageDecoderErrors)) {
338 char buffer[JMSG_LENGTH_MAX];
339 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
340 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
341 cinfo.err->msg_code, buffer, caller, width, height);
345 static bool return_false(const jpeg_decompress_struct& cinfo,
346 const char caller[]) {
347 print_jpeg_decoder_errors(cinfo, 0, 0, caller);
351 #ifdef SK_BUILD_FOR_ANDROID
352 static bool return_false(const jpeg_decompress_struct& cinfo,
353 const SkBitmap& bm, const char caller[]) {
354 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
359 static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo,
360 const SkBitmap& bm, const char caller[]) {
361 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
362 return SkImageDecoder::kFailure;
365 ///////////////////////////////////////////////////////////////////////////////
367 // Convert a scanline of CMYK samples to RGBX in place. Note that this
368 // method moves the "scanline" pointer in its processing
369 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
370 // At this point we've received CMYK pixels from libjpeg. We
371 // perform a crude conversion to RGB (based on the formulae
372 // from easyrgb.com):
374 // C = ( C * (1 - K) + K ) // for each CMY component
376 // R = ( 1 - C ) * 255 // for each RGB component
377 // Unfortunately we are seeing inverted CMYK so all the original terms
378 // are 1-. This yields:
380 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
381 // The conversion from CMY->RGB remains the same
382 for (unsigned int x = 0; x < width; ++x, scanline += 4) {
383 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
384 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
385 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
391 * Common code for setting the error manager.
393 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
394 SkASSERT(cinfo != NULL);
395 SkASSERT(errorManager != NULL);
396 cinfo->err = jpeg_std_error(errorManager);
397 errorManager->error_exit = skjpeg_error_exit;
401 * Common code for turning off upsampling and smoothing. Turning these
402 * off helps performance without showing noticable differences in the
405 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
406 SkASSERT(cinfo != NULL);
407 /* this gives about 30% performance improvement. In theory it may
408 reduce the visual quality, in practice I'm not seeing a difference
410 cinfo->do_fancy_upsampling = 0;
412 /* this gives another few percents */
413 cinfo->do_block_smoothing = 0;
417 * Common code for setting the dct method.
419 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
420 SkASSERT(cinfo != NULL);
421 #ifdef DCT_IFAST_SUPPORTED
422 if (decoder.getPreferQualityOverSpeed()) {
423 cinfo->dct_method = JDCT_ISLOW;
425 cinfo->dct_method = JDCT_IFAST;
428 cinfo->dct_method = JDCT_ISLOW;
432 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
433 SkASSERT(cinfo != NULL);
435 SrcDepth srcDepth = k32Bit_SrcDepth;
436 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
437 srcDepth = k8BitGray_SrcDepth;
440 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
442 case kAlpha_8_SkColorType:
443 // Only respect A8 colortype if the original is grayscale,
444 // in which case we will treat the grayscale as alpha
446 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
447 colorType = kN32_SkColorType;
450 case kN32_SkColorType:
452 case kARGB_4444_SkColorType:
454 case kRGB_565_SkColorType:
455 // These are acceptable destination colortypes.
458 // Force all other colortypes to 8888.
459 colorType = kN32_SkColorType;
463 switch (cinfo->jpeg_color_space) {
467 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
468 // so libjpeg will give us CMYK samples back and we will later
469 // manually convert them to RGB
470 cinfo->out_color_space = JCS_CMYK;
473 if (kAlpha_8_SkColorType == colorType) {
474 cinfo->out_color_space = JCS_GRAYSCALE;
477 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
478 // colortype. Fall through to set to the default.
480 cinfo->out_color_space = JCS_RGB;
487 * Based on the colortype and dither mode, adjust out_color_space and
488 * dither_mode of cinfo. Only does work in ANDROID_RGB
490 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
491 SkColorType colorType,
492 const SkImageDecoder& decoder) {
493 SkASSERT(cinfo != NULL);
495 cinfo->dither_mode = JDITHER_NONE;
496 if (JCS_CMYK == cinfo->out_color_space) {
500 case kN32_SkColorType:
501 cinfo->out_color_space = JCS_RGBA_8888;
503 case kRGB_565_SkColorType:
504 cinfo->out_color_space = JCS_RGB_565;
505 if (decoder.getDitherImage()) {
506 cinfo->dither_mode = JDITHER_ORDERED;
516 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
517 Used when decoding fails partway through reading scanlines to fill
519 static void fill_below_level(int y, SkBitmap* bitmap) {
520 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
521 SkCanvas canvas(*bitmap);
522 canvas.clipRect(SkRect::Make(rect));
523 canvas.drawColor(SK_ColorWHITE);
527 * Get the config and bytes per pixel of the source data. Return
528 * whether the data is supported.
530 static bool get_src_config(const jpeg_decompress_struct& cinfo,
531 SkScaledBitmapSampler::SrcConfig* sc,
532 int* srcBytesPerPixel) {
533 SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
534 if (JCS_CMYK == cinfo.out_color_space) {
535 // In this case we will manually convert the CMYK values to RGB
536 *sc = SkScaledBitmapSampler::kRGBX;
537 // The CMYK work-around relies on 4 components per pixel here
538 *srcBytesPerPixel = 4;
539 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
540 *sc = SkScaledBitmapSampler::kRGB;
541 *srcBytesPerPixel = 3;
543 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
544 *sc = SkScaledBitmapSampler::kRGBX;
545 *srcBytesPerPixel = 4;
546 } else if (JCS_RGB_565 == cinfo.out_color_space) {
547 *sc = SkScaledBitmapSampler::kRGB_565;
548 *srcBytesPerPixel = 2;
550 } else if (1 == cinfo.out_color_components &&
551 JCS_GRAYSCALE == cinfo.out_color_space) {
552 *sc = SkScaledBitmapSampler::kGray;
553 *srcBytesPerPixel = 1;
560 SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
562 SkAutoTime atm("JPEG Decode");
565 JPEGAutoClean autoClean;
567 jpeg_decompress_struct cinfo;
568 skjpeg_source_mgr srcManager(stream, this);
570 skjpeg_error_mgr errorManager;
571 set_error_mgr(&cinfo, &errorManager);
573 // All objects need to be instantiated before this setjmp call so that
574 // they will be cleaned up properly if an error occurs.
575 if (setjmp(errorManager.fJmpBuf)) {
576 return return_failure(cinfo, *bm, "setjmp");
579 initialize_info(&cinfo, &srcManager);
580 autoClean.set(&cinfo);
582 int status = jpeg_read_header(&cinfo, true);
583 if (status != JPEG_HEADER_OK) {
584 return return_failure(cinfo, *bm, "read_header");
587 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it
588 can) much faster that we, just use their num/denom api to approximate
591 int sampleSize = this->getSampleSize();
593 set_dct_method(*this, &cinfo);
595 SkASSERT(1 == cinfo.scale_num);
596 cinfo.scale_denom = sampleSize;
598 turn_off_visual_optimizations(&cinfo);
600 const SkColorType colorType = this->getBitmapColorType(&cinfo);
601 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
602 kPremul_SkAlphaType : kOpaque_SkAlphaType;
604 adjust_out_color_space_and_dither(&cinfo, colorType, *this);
606 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
607 // Assume an A8 bitmap is not opaque to avoid the check of each
608 // individual pixel. It is very unlikely to be opaque, since
609 // an opaque A8 bitmap would not be very interesting.
610 // Otherwise, a jpeg image is opaque.
611 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
612 colorType, alphaType));
613 return success ? kSuccess : kFailure;
616 /* image_width and image_height are the original dimensions, available
617 after jpeg_read_header(). To see the scaled dimensions, we have to call
618 jpeg_start_decompress(), and then read output_width and output_height.
620 if (!jpeg_start_decompress(&cinfo)) {
621 /* If we failed here, we may still have enough information to return
622 to the caller if they just wanted (subsampled bounds). If sampleSize
623 was 1, then we would have already returned. Thus we just check if
624 we're in kDecodeBounds_Mode, and that we have valid output sizes.
626 One reason to fail here is that we have insufficient stream data
627 to complete the setup. However, output dimensions seem to get
628 computed very early, which is why this special check can pay off.
630 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
631 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
632 recompute_sampleSize(sampleSize, cinfo));
633 // Assume an A8 bitmap is not opaque to avoid the check of each
634 // individual pixel. It is very unlikely to be opaque, since
635 // an opaque A8 bitmap would not be very interesting.
636 // Otherwise, a jpeg image is opaque.
637 bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
638 colorType, alphaType));
639 return success ? kSuccess : kFailure;
641 return return_failure(cinfo, *bm, "start_decompress");
644 sampleSize = recompute_sampleSize(sampleSize, cinfo);
646 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
647 // Assume an A8 bitmap is not opaque to avoid the check of each
648 // individual pixel. It is very unlikely to be opaque, since
649 // an opaque A8 bitmap would not be very interesting.
650 // Otherwise, a jpeg image is opaque.
651 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
652 colorType, alphaType));
653 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
656 if (!this->allocPixelRef(bm, NULL)) {
657 return return_failure(cinfo, *bm, "allocPixelRef");
660 SkAutoLockPixels alp(*bm);
663 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
664 a significant performance boost.
666 if (sampleSize == 1 &&
667 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
668 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
670 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
671 INT32 const bpr = bm->rowBytes();
673 while (cinfo.output_scanline < cinfo.output_height) {
674 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
675 if (0 == row_count) {
676 // if row_count == 0, then we didn't get a scanline,
677 // so return early. We will return a partial image.
678 fill_below_level(cinfo.output_scanline, bm);
679 cinfo.output_scanline = cinfo.output_height;
680 jpeg_finish_decompress(&cinfo);
681 return kPartialSuccess;
683 if (this->shouldCancelDecode()) {
684 return return_failure(cinfo, *bm, "shouldCancelDecode");
688 jpeg_finish_decompress(&cinfo);
693 // check for supported formats
694 SkScaledBitmapSampler::SrcConfig sc;
695 int srcBytesPerPixel;
697 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
698 return return_failure(cinfo, *bm, "jpeg colorspace");
701 if (!sampler.begin(bm, sc, *this)) {
702 return return_failure(cinfo, *bm, "sampler.begin");
705 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
706 uint8_t* srcRow = (uint8_t*)srcStorage.get();
708 // Possibly skip initial rows [sampler.srcY0]
709 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
710 return return_failure(cinfo, *bm, "skip rows");
713 // now loop through scanlines until y == bm->height() - 1
714 for (int y = 0;; y++) {
715 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
716 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
717 if (0 == row_count) {
718 // if row_count == 0, then we didn't get a scanline,
719 // so return early. We will return a partial image.
720 fill_below_level(y, bm);
721 cinfo.output_scanline = cinfo.output_height;
722 jpeg_finish_decompress(&cinfo);
723 return kPartialSuccess;
725 if (this->shouldCancelDecode()) {
726 return return_failure(cinfo, *bm, "shouldCancelDecode");
729 if (JCS_CMYK == cinfo.out_color_space) {
730 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
733 sampler.next(srcRow);
734 if (bm->height() - 1 == y) {
739 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
740 return return_failure(cinfo, *bm, "skip rows");
744 // we formally skip the rest, so we don't get a complaint from libjpeg
745 if (!skip_src_rows(&cinfo, srcRow,
746 cinfo.output_height - cinfo.output_scanline)) {
747 return return_failure(cinfo, *bm, "skip rows");
749 jpeg_finish_decompress(&cinfo);
754 ///////////////////////////////////////////////////////////////////////////////
757 kSizeForMemoryAllocation_SizeType,
761 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component,
763 if (sizeType == kSizeForMemoryAllocation_SizeType) {
764 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE,
765 info.cur_comp_info[component]->height_in_blocks * DCTSIZE);
767 return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
768 info.cur_comp_info[component]->downsampled_height);
771 static bool appears_to_be_yuv(const jpeg_decompress_struct& info) {
772 return (info.jpeg_color_space == JCS_YCbCr)
774 && (info.num_components == 3)
775 && (info.comps_in_scan >= info.num_components)
776 && (info.scale_denom <= 8)
777 && (info.cur_comp_info[0])
778 && (info.cur_comp_info[1])
779 && (info.cur_comp_info[2])
780 && (info.cur_comp_info[1]->h_samp_factor == 1)
781 && (info.cur_comp_info[1]->v_samp_factor == 1)
782 && (info.cur_comp_info[2]->h_samp_factor == 1)
783 && (info.cur_comp_info[2]->v_samp_factor == 1);
786 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
788 SkASSERT(appears_to_be_yuv(cinfo));
789 for (int i = 0; i < 3; ++i) {
790 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
794 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) {
795 SkASSERT(appears_to_be_yuv(cinfo));
796 // U size and V size have to be the same if we're calling output_raw_data()
797 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType);
798 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType));
800 JSAMPARRAY bufferraw[3];
801 JSAMPROW bufferraw2[32];
802 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
803 bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
804 bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
805 int yWidth = cinfo.output_width;
806 int yHeight = cinfo.output_height;
807 int yMaxH = yHeight - 1;
808 int v = cinfo.cur_comp_info[0]->v_samp_factor;
809 int uvMaxH = uvSize.height() - 1;
810 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
811 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
812 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
813 size_t rowBytesY = rowBytes[0];
814 size_t rowBytesU = rowBytes[1];
815 size_t rowBytesV = rowBytes[2];
817 int yScanlinesToRead = DCTSIZE * v;
818 SkAutoMalloc lastRowStorage(rowBytesY * 4);
819 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
820 JSAMPROW uLastRow = yLastRow + rowBytesY;
821 JSAMPROW vLastRow = uLastRow + rowBytesY;
822 JSAMPROW dummyRow = vLastRow + rowBytesY;
824 while (cinfo.output_scanline < cinfo.output_height) {
825 // Request 8 or 16 scanlines: returns 0 or more scanlines.
826 bool hasYLastRow(false), hasUVLastRow(false);
827 // Assign 8 or 16 rows of memory to read the Y channel.
828 for (int i = 0; i < yScanlinesToRead; ++i) {
829 int scanline = (cinfo.output_scanline + i);
830 if (scanline < yMaxH) {
831 bufferraw2[i] = &outputY[scanline * rowBytesY];
832 } else if (scanline == yMaxH) {
833 bufferraw2[i] = yLastRow;
836 bufferraw2[i] = dummyRow;
839 int scaledScanline = cinfo.output_scanline / v;
840 // Assign 8 rows of memory to read the U and V channels.
841 for (int i = 0; i < 8; ++i) {
842 int scanline = (scaledScanline + i);
843 if (scanline < uvMaxH) {
844 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
845 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
846 } else if (scanline == uvMaxH) {
847 bufferraw2[16 + i] = uLastRow;
848 bufferraw2[24 + i] = vLastRow;
851 bufferraw2[16 + i] = dummyRow;
852 bufferraw2[24 + i] = dummyRow;
855 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead);
857 if (scanlinesRead == 0) {
862 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
865 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
866 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
870 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
875 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
876 void* planes[3], size_t rowBytes[3],
877 SkYUVColorSpace* colorSpace) {
879 SkAutoTime atm("JPEG YUV8 Decode");
881 if (this->getSampleSize() != 1) {
882 return false; // Resizing not supported
885 JPEGAutoClean autoClean;
887 jpeg_decompress_struct cinfo;
888 skjpeg_source_mgr srcManager(stream, this);
890 skjpeg_error_mgr errorManager;
891 set_error_mgr(&cinfo, &errorManager);
893 // All objects need to be instantiated before this setjmp call so that
894 // they will be cleaned up properly if an error occurs.
895 if (setjmp(errorManager.fJmpBuf)) {
896 return return_false(cinfo, "setjmp YUV8");
899 initialize_info(&cinfo, &srcManager);
900 autoClean.set(&cinfo);
902 int status = jpeg_read_header(&cinfo, true);
903 if (status != JPEG_HEADER_OK) {
904 return return_false(cinfo, "read_header YUV8");
907 if (!appears_to_be_yuv(cinfo)) {
908 // It's not an error to not be encoded in YUV, so no need to use return_false()
912 cinfo.out_color_space = JCS_YCbCr;
913 cinfo.raw_data_out = TRUE;
915 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only
916 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType);
920 set_dct_method(*this, &cinfo);
922 SkASSERT(1 == cinfo.scale_num);
923 cinfo.scale_denom = 1;
925 turn_off_visual_optimizations(&cinfo);
928 cinfo.dither_mode = JDITHER_NONE;
931 /* image_width and image_height are the original dimensions, available
932 after jpeg_read_header(). To see the scaled dimensions, we have to call
933 jpeg_start_decompress(), and then read output_width and output_height.
935 if (!jpeg_start_decompress(&cinfo)) {
936 return return_false(cinfo, "start_decompress YUV8");
939 // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV.
940 // Again, not really an error.
941 if (!appears_to_be_yuv(cinfo)) {
945 if (!output_raw_data(cinfo, planes, rowBytes)) {
946 return return_false(cinfo, "output_raw_data");
949 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
950 jpeg_finish_decompress(&cinfo);
952 if (NULL != colorSpace) {
953 *colorSpace = kJPEG_SkYUVColorSpace;
959 ///////////////////////////////////////////////////////////////////////////////
961 #ifdef SK_BUILD_FOR_ANDROID
962 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
964 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
966 skjpeg_error_mgr sk_err;
967 set_error_mgr(imageIndex->cinfo(), &sk_err);
969 // All objects need to be instantiated before this setjmp call so that
970 // they will be cleaned up properly if an error occurs.
971 if (setjmp(sk_err.fJmpBuf)) {
975 // create the cinfo used to create/build the huffmanIndex
976 if (!imageIndex->initializeInfoAndReadHeader()) {
980 if (!imageIndex->buildHuffmanIndex()) {
984 // destroy the cinfo used to create/build the huffman index
985 imageIndex->destroyInfo();
987 // Init decoder to image decode mode
988 if (!imageIndex->initializeInfoAndReadHeader()) {
992 jpeg_decompress_struct* cinfo = imageIndex->cinfo();
993 // We have a new cinfo, so set the error mgr again.
994 set_error_mgr(cinfo, &sk_err);
996 // FIXME: This sets cinfo->out_color_space, which we may change later
997 // based on the config in onDecodeSubset. This should be fine, since
998 // jpeg_init_read_tile_scanline will check out_color_space again after
999 // that change (when it calls jinit_color_deconverter).
1000 (void) this->getBitmapColorType(cinfo);
1002 turn_off_visual_optimizations(cinfo);
1004 // instead of jpeg_start_decompress() we start a tiled decompress
1005 if (!imageIndex->startTileDecompress()) {
1009 SkASSERT(1 == cinfo->scale_num);
1010 fImageWidth = cinfo->output_width;
1011 fImageHeight = cinfo->output_height;
1014 *width = fImageWidth;
1017 *height = fImageHeight;
1020 SkDELETE(fImageIndex);
1021 fImageIndex = imageIndex.detach();
1026 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
1027 if (NULL == fImageIndex) {
1030 jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
1032 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
1033 if (!rect.intersect(region)) {
1034 // If the requested region is entirely outside the image return false
1039 skjpeg_error_mgr errorManager;
1040 set_error_mgr(cinfo, &errorManager);
1042 if (setjmp(errorManager.fJmpBuf)) {
1046 int requestedSampleSize = this->getSampleSize();
1047 cinfo->scale_denom = requestedSampleSize;
1049 set_dct_method(*this, cinfo);
1051 const SkColorType colorType = this->getBitmapColorType(cinfo);
1052 adjust_out_color_space_and_dither(cinfo, colorType, *this);
1054 int startX = rect.fLeft;
1055 int startY = rect.fTop;
1056 int width = rect.width();
1057 int height = rect.height();
1059 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
1060 &startX, &startY, &width, &height);
1061 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
1062 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
1064 SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
1067 // Assume an A8 bitmap is not opaque to avoid the check of each
1068 // individual pixel. It is very unlikely to be opaque, since
1069 // an opaque A8 bitmap would not be very interesting.
1070 // Otherwise, a jpeg image is opaque.
1071 bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType,
1072 kAlpha_8_SkColorType == colorType ?
1073 kPremul_SkAlphaType : kOpaque_SkAlphaType));
1075 // Check ahead of time if the swap(dest, src) is possible or not.
1076 // If yes, then we will stick to AllocPixelRef since it's cheaper with the
1077 // swap happening. If no, then we will use alloc to allocate pixels to
1078 // prevent garbage collection.
1079 int w = rect.width() / actualSampleSize;
1080 int h = rect.height() / actualSampleSize;
1081 bool swapOnly = (rect == region) && bm->isNull() &&
1082 (w == bitmap.width()) && (h == bitmap.height()) &&
1083 ((startX - rect.x()) / actualSampleSize == 0) &&
1084 ((startY - rect.y()) / actualSampleSize == 0);
1086 if (!this->allocPixelRef(&bitmap, NULL)) {
1087 return return_false(*cinfo, bitmap, "allocPixelRef");
1090 if (!bitmap.tryAllocPixels()) {
1091 return return_false(*cinfo, bitmap, "allocPixels");
1095 SkAutoLockPixels alp(bitmap);
1098 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
1099 a significant performance boost.
1101 if (skiaSampleSize == 1 &&
1102 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) ||
1103 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565)))
1105 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
1106 INT32 const bpr = bitmap.rowBytes();
1107 int rowTotalCount = 0;
1109 while (rowTotalCount < height) {
1110 int rowCount = jpeg_read_tile_scanline(cinfo,
1111 fImageIndex->huffmanIndex(),
1113 // if rowCount == 0, then we didn't get a scanline, so abort.
1114 // onDecodeSubset() relies on onBuildTileIndex(), which
1115 // needs a complete image to succeed.
1116 if (0 == rowCount) {
1117 return return_false(*cinfo, bitmap, "read_scanlines");
1119 if (this->shouldCancelDecode()) {
1120 return return_false(*cinfo, bitmap, "shouldCancelDecode");
1122 rowTotalCount += rowCount;
1129 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
1130 region.width(), region.height(), startX, startY);
1136 // check for supported formats
1137 SkScaledBitmapSampler::SrcConfig sc;
1138 int srcBytesPerPixel;
1140 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
1141 return return_false(*cinfo, *bm, "jpeg colorspace");
1144 if (!sampler.begin(&bitmap, sc, *this)) {
1145 return return_false(*cinfo, bitmap, "sampler.begin");
1148 SkAutoMalloc srcStorage(width * srcBytesPerPixel);
1149 uint8_t* srcRow = (uint8_t*)srcStorage.get();
1151 // Possibly skip initial rows [sampler.srcY0]
1152 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
1153 return return_false(*cinfo, bitmap, "skip rows");
1156 // now loop through scanlines until y == bitmap->height() - 1
1157 for (int y = 0;; y++) {
1158 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
1159 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
1160 // if row_count == 0, then we didn't get a scanline, so abort.
1161 // onDecodeSubset() relies on onBuildTileIndex(), which
1162 // needs a complete image to succeed.
1163 if (0 == row_count) {
1164 return return_false(*cinfo, bitmap, "read_scanlines");
1166 if (this->shouldCancelDecode()) {
1167 return return_false(*cinfo, bitmap, "shouldCancelDecode");
1170 if (JCS_CMYK == cinfo->out_color_space) {
1171 convert_CMYK_to_RGB(srcRow, width);
1174 sampler.next(srcRow);
1175 if (bitmap.height() - 1 == y) {
1180 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
1181 sampler.srcDY() - 1)) {
1182 return return_false(*cinfo, bitmap, "skip rows");
1188 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
1189 region.width(), region.height(), startX, startY);
1195 ///////////////////////////////////////////////////////////////////////////////
1197 #include "SkColorPriv.h"
1199 // taken from jcolor.c in libjpeg
1200 #if 0 // 16bit - precise but slow
1201 #define CYR 19595 // 0.299
1202 #define CYG 38470 // 0.587
1203 #define CYB 7471 // 0.114
1205 #define CUR -11059 // -0.16874
1206 #define CUG -21709 // -0.33126
1207 #define CUB 32768 // 0.5
1209 #define CVR 32768 // 0.5
1210 #define CVG -27439 // -0.41869
1211 #define CVB -5329 // -0.08131
1214 #else // 8bit - fast, slightly less precise
1215 #define CYR 77 // 0.299
1216 #define CYG 150 // 0.587
1217 #define CYB 29 // 0.114
1219 #define CUR -43 // -0.16874
1220 #define CUG -85 // -0.33126
1221 #define CUB 128 // 0.5
1223 #define CVR 128 // 0.5
1224 #define CVG -107 // -0.41869
1225 #define CVB -21 // -0.08131
1230 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
1231 int r = SkGetPackedR32(c);
1232 int g = SkGetPackedG32(c);
1233 int b = SkGetPackedB32(c);
1235 int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
1236 int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
1237 int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
1240 dst[1] = SkToU8(u + 128);
1241 dst[2] = SkToU8(v + 128);
1244 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
1245 int r = SkGetPackedR4444(c);
1246 int g = SkGetPackedG4444(c);
1247 int b = SkGetPackedB4444(c);
1249 int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
1250 int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
1251 int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
1254 dst[1] = SkToU8(u + 128);
1255 dst[2] = SkToU8(v + 128);
1258 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
1259 int r = SkGetPackedR16(c);
1260 int g = SkGetPackedG16(c);
1261 int b = SkGetPackedB16(c);
1263 int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
1264 int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
1265 int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
1268 dst[1] = SkToU8(u + 128);
1269 dst[2] = SkToU8(v + 128);
1272 ///////////////////////////////////////////////////////////////////////////////
1274 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
1275 const void* SK_RESTRICT src, int width,
1276 const SkPMColor* SK_RESTRICT ctable);
1278 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
1279 const void* SK_RESTRICT srcRow, int width,
1281 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
1282 while (--width >= 0) {
1283 #ifdef WE_CONVERT_TO_YUV
1284 rgb2yuv_32(dst, *src++);
1286 uint32_t c = *src++;
1287 dst[0] = SkGetPackedR32(c);
1288 dst[1] = SkGetPackedG32(c);
1289 dst[2] = SkGetPackedB32(c);
1295 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
1296 const void* SK_RESTRICT srcRow, int width,
1298 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
1299 while (--width >= 0) {
1300 #ifdef WE_CONVERT_TO_YUV
1301 rgb2yuv_4444(dst, *src++);
1303 SkPMColor16 c = *src++;
1304 dst[0] = SkPacked4444ToR32(c);
1305 dst[1] = SkPacked4444ToG32(c);
1306 dst[2] = SkPacked4444ToB32(c);
1312 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
1313 const void* SK_RESTRICT srcRow, int width,
1315 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
1316 while (--width >= 0) {
1317 #ifdef WE_CONVERT_TO_YUV
1318 rgb2yuv_16(dst, *src++);
1320 uint16_t c = *src++;
1321 dst[0] = SkPacked16ToR32(c);
1322 dst[1] = SkPacked16ToG32(c);
1323 dst[2] = SkPacked16ToB32(c);
1329 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
1330 const void* SK_RESTRICT srcRow, int width,
1331 const SkPMColor* SK_RESTRICT ctable) {
1332 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
1333 while (--width >= 0) {
1334 #ifdef WE_CONVERT_TO_YUV
1335 rgb2yuv_32(dst, ctable[*src++]);
1337 uint32_t c = ctable[*src++];
1338 dst[0] = SkGetPackedR32(c);
1339 dst[1] = SkGetPackedG32(c);
1340 dst[2] = SkGetPackedB32(c);
1346 static WriteScanline ChooseWriter(const SkBitmap& bm) {
1347 switch (bm.colorType()) {
1348 case kN32_SkColorType:
1349 return Write_32_YUV;
1350 case kRGB_565_SkColorType:
1351 return Write_16_YUV;
1352 case kARGB_4444_SkColorType:
1353 return Write_4444_YUV;
1354 case kIndex_8_SkColorType:
1355 return Write_Index_YUV;
1361 class SkJPEGImageEncoder : public SkImageEncoder {
1363 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
1365 SkAutoTime atm("JPEG Encode");
1368 SkAutoLockPixels alp(bm);
1369 if (NULL == bm.getPixels()) {
1373 jpeg_compress_struct cinfo;
1374 skjpeg_error_mgr sk_err;
1375 skjpeg_destination_mgr sk_wstream(stream);
1377 // allocate these before set call setjmp
1378 SkAutoMalloc oneRow;
1380 cinfo.err = jpeg_std_error(&sk_err);
1381 sk_err.error_exit = skjpeg_error_exit;
1382 if (setjmp(sk_err.fJmpBuf)) {
1386 // Keep after setjmp or mark volatile.
1387 const WriteScanline writer = ChooseWriter(bm);
1388 if (NULL == writer) {
1392 jpeg_create_compress(&cinfo);
1393 cinfo.dest = &sk_wstream;
1394 cinfo.image_width = bm.width();
1395 cinfo.image_height = bm.height();
1396 cinfo.input_components = 3;
1397 #ifdef WE_CONVERT_TO_YUV
1398 cinfo.in_color_space = JCS_YCbCr;
1400 cinfo.in_color_space = JCS_RGB;
1402 cinfo.input_gamma = 1;
1404 jpeg_set_defaults(&cinfo);
1405 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
1406 #ifdef DCT_IFAST_SUPPORTED
1407 cinfo.dct_method = JDCT_IFAST;
1410 jpeg_start_compress(&cinfo, TRUE);
1412 const int width = bm.width();
1413 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3);
1415 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : NULL;
1416 const void* srcRow = bm.getPixels();
1418 while (cinfo.next_scanline < cinfo.image_height) {
1419 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
1421 writer(oneRowP, srcRow, width, colors);
1422 row_pointer[0] = oneRowP;
1423 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
1424 srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
1427 jpeg_finish_compress(&cinfo);
1428 jpeg_destroy_compress(&cinfo);
1434 ///////////////////////////////////////////////////////////////////////////////
1435 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
1436 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
1437 ///////////////////////////////////////////////////////////////////////////////
1439 static bool is_jpeg(SkStreamRewindable* stream) {
1440 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
1441 static const size_t HEADER_SIZE = sizeof(gHeader);
1443 char buffer[HEADER_SIZE];
1444 size_t len = stream->read(buffer, HEADER_SIZE);
1446 if (len != HEADER_SIZE) {
1447 return false; // can't read enough
1449 if (memcmp(buffer, gHeader, HEADER_SIZE)) {
1456 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
1457 if (is_jpeg(stream)) {
1458 return SkNEW(SkJPEGImageDecoder);
1463 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
1464 if (is_jpeg(stream)) {
1465 return SkImageDecoder::kJPEG_Format;
1467 return SkImageDecoder::kUnknown_Format;
1470 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1471 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1474 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1475 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1476 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);