| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2007 The Android Open Source Project | 2 * Copyright 2007 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
| 10 #include "SkImageEncoder.h" | 10 #include "SkImageEncoder.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 } | 95 } |
| 96 /* To suppress error messages with a SK_DEBUG binary, set the | 96 /* To suppress error messages with a SK_DEBUG binary, set the |
| 97 * environment variable "skia_images_jpeg_suppressDecoderErrors" | 97 * environment variable "skia_images_jpeg_suppressDecoderErrors" |
| 98 * to "true". Inside a program that links to skia: | 98 * to "true". Inside a program that links to skia: |
| 99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */ | 99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */ |
| 100 if (c_suppressJPEGImageDecoderErrors) { | 100 if (c_suppressJPEGImageDecoderErrors) { |
| 101 cinfo->err->output_message = &do_nothing_output_message; | 101 cinfo->err->output_message = &do_nothing_output_message; |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 | 104 |
| 105 static void compute_uv_size(const jpeg_decompress_struct& info, int& width, int&
height) |
| 106 { |
| 107 int h = info.cur_comp_info[0]->h_samp_factor; |
| 108 int v = info.cur_comp_info[0]->v_samp_factor; |
| 109 width = (info.output_width + h - 1) / h; |
| 110 height = (info.output_height + v - 1) / v; |
| 111 } |
| 112 |
| 105 #ifdef SK_BUILD_FOR_ANDROID | 113 #ifdef SK_BUILD_FOR_ANDROID |
| 106 class SkJPEGImageIndex { | 114 class SkJPEGImageIndex { |
| 107 public: | 115 public: |
| 108 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) | 116 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) |
| 109 : fSrcMgr(stream, decoder) | 117 : fSrcMgr(stream, decoder) |
| 110 , fInfoInitialized(false) | 118 , fInfoInitialized(false) |
| 111 , fHuffmanCreated(false) | 119 , fHuffmanCreated(false) |
| 112 , fDecompressStarted(false) | 120 , fDecompressStarted(false) |
| 113 { | 121 { |
| 114 SkDEBUGCODE(fReadHeaderSucceeded = false;) | 122 SkDEBUGCODE(fReadHeaderSucceeded = false;) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 huffman_index fHuffmanIndex; | 218 huffman_index fHuffmanIndex; |
| 211 bool fInfoInitialized; | 219 bool fInfoInitialized; |
| 212 bool fHuffmanCreated; | 220 bool fHuffmanCreated; |
| 213 bool fDecompressStarted; | 221 bool fDecompressStarted; |
| 214 SkDEBUGCODE(bool fReadHeaderSucceeded;) | 222 SkDEBUGCODE(bool fReadHeaderSucceeded;) |
| 215 }; | 223 }; |
| 216 #endif | 224 #endif |
| 217 | 225 |
| 218 class SkJPEGImageDecoder : public SkImageDecoder { | 226 class SkJPEGImageDecoder : public SkImageDecoder { |
| 219 public: | 227 public: |
| 228 SkJPEGImageDecoder() { |
| 220 #ifdef SK_BUILD_FOR_ANDROID | 229 #ifdef SK_BUILD_FOR_ANDROID |
| 221 SkJPEGImageDecoder() { | |
| 222 fImageIndex = NULL; | 230 fImageIndex = NULL; |
| 223 fImageWidth = 0; | 231 fImageWidth = 0; |
| 224 fImageHeight = 0; | 232 fImageHeight = 0; |
| 233 #endif |
| 234 fYUVBuffers[0] = fYUVBuffers[1] = fYUVBuffers[2] = NULL; |
| 235 fRowBytes[0] = fRowBytes[1] = fRowBytes[2] = 0; |
| 225 } | 236 } |
| 226 | 237 |
| 238 #ifdef SK_BUILD_FOR_ANDROID |
| 227 virtual ~SkJPEGImageDecoder() { | 239 virtual ~SkJPEGImageDecoder() { |
| 228 SkDELETE(fImageIndex); | 240 SkDELETE(fImageIndex); |
| 229 } | 241 } |
| 230 #endif | 242 #endif |
| 231 | 243 |
| 232 virtual Format getFormat() const { | 244 virtual Format getFormat() const { |
| 233 return kJPEG_Format; | 245 return kJPEG_Format; |
| 234 } | 246 } |
| 235 | 247 |
| 236 protected: | 248 protected: |
| 237 #ifdef SK_BUILD_FOR_ANDROID | 249 #ifdef SK_BUILD_FOR_ANDROID |
| 238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h
eight) SK_OVERRIDE; | 250 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h
eight) SK_OVERRIDE; |
| 239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI
DE; | 251 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI
DE; |
| 240 #endif | 252 #endif |
| 241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 253 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 254 virtual void onSetYUVBuffers(void* yuv[3], size_t rowBytes[3]) SK_OVERRIDE; |
| 255 virtual bool onGetComponentSizes(SkStream* stream, SkISize sizes[3]) SK_OVER
RIDE; |
| 242 | 256 |
| 243 private: | 257 private: |
| 244 #ifdef SK_BUILD_FOR_ANDROID | 258 #ifdef SK_BUILD_FOR_ANDROID |
| 245 SkJPEGImageIndex* fImageIndex; | 259 SkJPEGImageIndex* fImageIndex; |
| 246 int fImageWidth; | 260 int fImageWidth; |
| 247 int fImageHeight; | 261 int fImageHeight; |
| 248 #endif | 262 #endif |
| 263 uint8_t* fYUVBuffers[3]; |
| 264 size_t fRowBytes[3]; |
| 265 |
| 266 bool isSupportedYUVFormat(jpeg_decompress_struct& cinfo) const { |
| 267 if ((cinfo.jpeg_color_space == JCS_YCbCr) && |
| 268 (cinfo.num_components == 3) && |
| 269 (cinfo.scale_denom <= 8) && |
| 270 (cinfo.cur_comp_info[1]->h_samp_factor == 1) && |
| 271 (cinfo.cur_comp_info[1]->v_samp_factor == 1) && |
| 272 (cinfo.cur_comp_info[2]->h_samp_factor == 1) && |
| 273 (cinfo.cur_comp_info[2]->v_samp_factor == 1)) { |
| 274 int h = cinfo.cur_comp_info[0]->h_samp_factor; |
| 275 int v = cinfo.cur_comp_info[0]->v_samp_factor; |
| 276 if (((h == 1) || (h == 2) || (h == 4)) && |
| 277 ((v == 1) || (v == 2))) { |
| 278 cinfo.out_color_space = JCS_YCbCr; |
| 279 cinfo.raw_data_out = TRUE; |
| 280 |
| 281 #ifdef SK_PRINT_YUV_FORMAT |
| 282 SkDebugf("YUV 4:%d:%d\n", 4 / h, (v == 1) ? 4 / h : 0); |
| 283 #endif |
| 284 return true; |
| 285 } |
| 286 } |
| 287 return false; |
| 288 } |
| 289 |
| 290 bool canDecodeToYUV(jpeg_decompress_struct& cinfo) const { |
| 291 return ((NULL != fYUVBuffers[0]) && |
| 292 (NULL != fYUVBuffers[1]) && |
| 293 (NULL != fYUVBuffers[2]) && |
| 294 (fRowBytes[0] > 0) && |
| 295 (fRowBytes[1] > 0) && |
| 296 (fRowBytes[2] > 0) && |
| 297 isSupportedYUVFormat(cinfo)); |
| 298 } |
| 249 | 299 |
| 250 /** | 300 /** |
| 251 * Determine the appropriate bitmap colortype and out_color_space based on | 301 * 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 | 302 * both the preference of the caller and the jpeg_color_space on the |
| 253 * jpeg_decompress_struct passed in. | 303 * jpeg_decompress_struct passed in. |
| 254 * Must be called after jpeg_read_header. | 304 * Must be called after jpeg_read_header. |
| 255 */ | 305 */ |
| 256 SkColorType getBitmapColorType(jpeg_decompress_struct*); | 306 SkColorType getBitmapColorType(jpeg_decompress_struct*); |
| 257 | 307 |
| 308 bool decodeToBitmap(SkBitmap* bm, |
| 309 jpeg_decompress_struct& cinfo, |
| 310 SkScaledBitmapSampler& sampler); |
| 311 bool decodeToYUV(jpeg_decompress_struct& cinfo); |
| 312 |
| 258 typedef SkImageDecoder INHERITED; | 313 typedef SkImageDecoder INHERITED; |
| 259 }; | 314 }; |
| 260 | 315 |
| 261 ////////////////////////////////////////////////////////////////////////// | 316 ////////////////////////////////////////////////////////////////////////// |
| 262 | 317 |
| 263 /* Automatically clean up after throwing an exception */ | 318 /* Automatically clean up after throwing an exception */ |
| 264 class JPEGAutoClean { | 319 class JPEGAutoClean { |
| 265 public: | 320 public: |
| 266 JPEGAutoClean(): cinfo_ptr(NULL) {} | 321 JPEGAutoClean(): cinfo_ptr(NULL) {} |
| 267 ~JPEGAutoClean() { | 322 ~JPEGAutoClean() { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 return false; | 373 return false; |
| 319 } | 374 } |
| 320 } | 375 } |
| 321 return true; | 376 return true; |
| 322 } | 377 } |
| 323 #endif | 378 #endif |
| 324 | 379 |
| 325 // This guy exists just to aid in debugging, as it allows debuggers to just | 380 // 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. | 381 // set a break-point in one place to see all error exists. |
| 327 static bool return_false(const jpeg_decompress_struct& cinfo, | 382 static bool return_false(const jpeg_decompress_struct& cinfo, |
| 328 const SkBitmap& bm, const char caller[]) { | 383 const SkBitmap* bm, const char caller[]) { |
| 329 if (!(c_suppressJPEGImageDecoderErrors)) { | 384 if (!(c_suppressJPEGImageDecoderErrors)) { |
| 330 char buffer[JMSG_LENGTH_MAX]; | 385 char buffer[JMSG_LENGTH_MAX]; |
| 331 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); | 386 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); |
| 332 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", | 387 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", |
| 333 cinfo.err->msg_code, buffer, caller, bm.width(), bm.height()); | 388 cinfo.err->msg_code, buffer, caller, |
| 389 (NULL != bm) ? bm->width() : 0, |
| 390 (NULL != bm) ? bm->height() : 0); |
| 334 } | 391 } |
| 335 return false; // must always return false | 392 return false; // must always return false |
| 336 } | 393 } |
| 337 | 394 |
| 338 // Convert a scanline of CMYK samples to RGBX in place. Note that this | 395 // Convert a scanline of CMYK samples to RGBX in place. Note that this |
| 339 // method moves the "scanline" pointer in its processing | 396 // method moves the "scanline" pointer in its processing |
| 340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { | 397 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { |
| 341 // At this point we've received CMYK pixels from libjpeg. We | 398 // At this point we've received CMYK pixels from libjpeg. We |
| 342 // perform a crude conversion to RGB (based on the formulae | 399 // perform a crude conversion to RGB (based on the formulae |
| 343 // from easyrgb.com): | 400 // from easyrgb.com): |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 | 595 |
| 539 jpeg_decompress_struct cinfo; | 596 jpeg_decompress_struct cinfo; |
| 540 skjpeg_source_mgr srcManager(stream, this); | 597 skjpeg_source_mgr srcManager(stream, this); |
| 541 | 598 |
| 542 skjpeg_error_mgr errorManager; | 599 skjpeg_error_mgr errorManager; |
| 543 set_error_mgr(&cinfo, &errorManager); | 600 set_error_mgr(&cinfo, &errorManager); |
| 544 | 601 |
| 545 // All objects need to be instantiated before this setjmp call so that | 602 // All objects need to be instantiated before this setjmp call so that |
| 546 // they will be cleaned up properly if an error occurs. | 603 // they will be cleaned up properly if an error occurs. |
| 547 if (setjmp(errorManager.fJmpBuf)) { | 604 if (setjmp(errorManager.fJmpBuf)) { |
| 548 return return_false(cinfo, *bm, "setjmp"); | 605 return return_false(cinfo, bm, "setjmp"); |
| 549 } | 606 } |
| 550 | 607 |
| 551 initialize_info(&cinfo, &srcManager); | 608 initialize_info(&cinfo, &srcManager); |
| 552 autoClean.set(&cinfo); | 609 autoClean.set(&cinfo); |
| 553 | 610 |
| 554 int status = jpeg_read_header(&cinfo, true); | 611 int status = jpeg_read_header(&cinfo, true); |
| 555 if (status != JPEG_HEADER_OK) { | 612 if (status != JPEG_HEADER_OK) { |
| 556 return return_false(cinfo, *bm, "read_header"); | 613 return return_false(cinfo, bm, "read_header"); |
| 557 } | 614 } |
| 558 | 615 |
| 559 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it | 616 /* 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 | 617 can) much faster that we, just use their num/denom api to approximate |
| 561 the size. | 618 the size. |
| 562 */ | 619 */ |
| 563 int sampleSize = this->getSampleSize(); | 620 int sampleSize = this->getSampleSize(); |
| 564 | 621 |
| 565 set_dct_method(*this, &cinfo); | 622 set_dct_method(*this, &cinfo); |
| 566 | 623 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension
s(cinfo)) { | 658 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension
s(cinfo)) { |
| 602 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, | 659 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, |
| 603 recompute_sampleSize(sampleSize, cinfo)); | 660 recompute_sampleSize(sampleSize, cinfo)); |
| 604 // Assume an A8 bitmap is not opaque to avoid the check of each | 661 // Assume an A8 bitmap is not opaque to avoid the check of each |
| 605 // individual pixel. It is very unlikely to be opaque, since | 662 // individual pixel. It is very unlikely to be opaque, since |
| 606 // an opaque A8 bitmap would not be very interesting. | 663 // an opaque A8 bitmap would not be very interesting. |
| 607 // Otherwise, a jpeg image is opaque. | 664 // Otherwise, a jpeg image is opaque. |
| 608 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled
Height(), | 665 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled
Height(), |
| 609 colorType, alphaType)); | 666 colorType, alphaType)); |
| 610 } else { | 667 } else { |
| 611 return return_false(cinfo, *bm, "start_decompress"); | 668 return return_false(cinfo, bm, "start_decompress"); |
| 612 } | 669 } |
| 613 } | 670 } |
| 614 sampleSize = recompute_sampleSize(sampleSize, cinfo); | 671 sampleSize = recompute_sampleSize(sampleSize, cinfo); |
| 615 | 672 |
| 616 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER | 673 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER |
| 617 // should we allow the Chooser (if present) to pick a colortype for us??? | 674 // should we allow the Chooser (if present) to pick a colortype for us??? |
| 618 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_h
eight)) { | 675 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_h
eight)) { |
| 619 return return_false(cinfo, *bm, "chooseFromOneChoice"); | 676 return return_false(cinfo, bm, "chooseFromOneChoice"); |
| 620 } | 677 } |
| 621 #endif | 678 #endif |
| 622 | 679 |
| 623 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl
eSize); | 680 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl
eSize); |
| 624 // Assume an A8 bitmap is not opaque to avoid the check of each | 681 // Assume an A8 bitmap is not opaque to avoid the check of each |
| 625 // individual pixel. It is very unlikely to be opaque, since | 682 // individual pixel. It is very unlikely to be opaque, since |
| 626 // an opaque A8 bitmap would not be very interesting. | 683 // an opaque A8 bitmap would not be very interesting. |
| 627 // Otherwise, a jpeg image is opaque. | 684 // Otherwise, a jpeg image is opaque. |
| 628 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), | 685 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), |
| 629 colorType, alphaType)); | 686 colorType, alphaType)); |
| 630 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 687 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 631 return true; | 688 return true; |
| 632 } | 689 } |
| 690 |
| 691 return canDecodeToYUV(cinfo) ? decodeToYUV(cinfo) : decodeToBitmap(bm, cinfo
, sampler); |
| 692 } |
| 693 |
| 694 bool SkJPEGImageDecoder::decodeToBitmap(SkBitmap* bm, |
| 695 jpeg_decompress_struct& cinfo, |
| 696 SkScaledBitmapSampler& sampler) { |
| 633 if (!this->allocPixelRef(bm, NULL)) { | 697 if (!this->allocPixelRef(bm, NULL)) { |
| 634 return return_false(cinfo, *bm, "allocPixelRef"); | 698 return return_false(cinfo, bm, "allocPixelRef"); |
| 635 } | 699 } |
| 636 | 700 |
| 637 SkAutoLockPixels alp(*bm); | 701 SkAutoLockPixels alp(*bm); |
| 638 | 702 |
| 639 #ifdef ANDROID_RGB | 703 #ifdef ANDROID_RGB |
| 640 /* short-circuit the SkScaledBitmapSampler when possible, as this gives | 704 /* short-circuit the SkScaledBitmapSampler when possible, as this gives |
| 641 a significant performance boost. | 705 a significant performance boost. |
| 642 */ | 706 */ |
| 643 if (sampleSize == 1 && | 707 if (sampleSize == 1 && |
| 644 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888
8) || | 708 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888
8) || |
| 645 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_
565))) | 709 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_
565))) |
| 646 { | 710 { |
| 647 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); | 711 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); |
| 648 INT32 const bpr = bm->rowBytes(); | 712 INT32 const bpr = bm->rowBytes(); |
| 649 | 713 |
| 650 while (cinfo.output_scanline < cinfo.output_height) { | 714 while (cinfo.output_scanline < cinfo.output_height) { |
| 651 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); | 715 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); |
| 652 if (0 == row_count) { | 716 if (0 == row_count) { |
| 653 // if row_count == 0, then we didn't get a scanline, | 717 // if row_count == 0, then we didn't get a scanline, |
| 654 // so return early. We will return a partial image. | 718 // so return early. We will return a partial image. |
| 655 fill_below_level(cinfo.output_scanline, bm); | 719 fill_below_level(cinfo.output_scanline, bm); |
| 656 cinfo.output_scanline = cinfo.output_height; | 720 cinfo.output_scanline = cinfo.output_height; |
| 657 break; // Skip to jpeg_finish_decompress() | 721 break; // Skip to jpeg_finish_decompress() |
| 658 } | 722 } |
| 659 if (this->shouldCancelDecode()) { | 723 if (this->shouldCancelDecode()) { |
| 660 return return_false(cinfo, *bm, "shouldCancelDecode"); | 724 return return_false(cinfo, bm, "shouldCancelDecode"); |
| 661 } | 725 } |
| 662 rowptr += bpr; | 726 rowptr += bpr; |
| 663 } | 727 } |
| 664 jpeg_finish_decompress(&cinfo); | 728 jpeg_finish_decompress(&cinfo); |
| 665 return true; | 729 return true; |
| 666 } | 730 } |
| 667 #endif | 731 #endif |
| 668 | 732 |
| 669 // check for supported formats | 733 // check for supported formats |
| 670 SkScaledBitmapSampler::SrcConfig sc; | 734 SkScaledBitmapSampler::SrcConfig sc; |
| 671 int srcBytesPerPixel; | 735 int srcBytesPerPixel; |
| 672 | 736 |
| 673 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { | 737 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { |
| 674 return return_false(cinfo, *bm, "jpeg colorspace"); | 738 return return_false(cinfo, bm, "jpeg colorspace"); |
| 675 } | 739 } |
| 676 | 740 |
| 677 if (!sampler.begin(bm, sc, *this)) { | 741 if (!sampler.begin(bm, sc, *this)) { |
| 678 return return_false(cinfo, *bm, "sampler.begin"); | 742 return return_false(cinfo, bm, "sampler.begin"); |
| 679 } | 743 } |
| 680 | 744 |
| 681 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); | 745 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); |
| 682 uint8_t* srcRow = (uint8_t*)srcStorage.get(); | 746 uint8_t* srcRow = (uint8_t*)srcStorage.get(); |
| 683 | 747 |
| 684 // Possibly skip initial rows [sampler.srcY0] | 748 // Possibly skip initial rows [sampler.srcY0] |
| 685 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { | 749 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { |
| 686 return return_false(cinfo, *bm, "skip rows"); | 750 return return_false(cinfo, bm, "skip rows"); |
| 687 } | 751 } |
| 688 | 752 |
| 689 // now loop through scanlines until y == bm->height() - 1 | 753 // now loop through scanlines until y == bm->height() - 1 |
| 690 for (int y = 0;; y++) { | 754 for (int y = 0;; y++) { |
| 691 JSAMPLE* rowptr = (JSAMPLE*)srcRow; | 755 JSAMPLE* rowptr = (JSAMPLE*)srcRow; |
| 692 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); | 756 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); |
| 693 if (0 == row_count) { | 757 if (0 == row_count) { |
| 694 // if row_count == 0, then we didn't get a scanline, | 758 // if row_count == 0, then we didn't get a scanline, |
| 695 // so return early. We will return a partial image. | 759 // so return early. We will return a partial image. |
| 696 fill_below_level(y, bm); | 760 fill_below_level(y, bm); |
| 697 cinfo.output_scanline = cinfo.output_height; | 761 cinfo.output_scanline = cinfo.output_height; |
| 698 break; // Skip to jpeg_finish_decompress() | 762 break; // Skip to jpeg_finish_decompress() |
| 699 } | 763 } |
| 700 if (this->shouldCancelDecode()) { | 764 if (this->shouldCancelDecode()) { |
| 701 return return_false(cinfo, *bm, "shouldCancelDecode"); | 765 return return_false(cinfo, bm, "shouldCancelDecode"); |
| 702 } | 766 } |
| 703 | 767 |
| 704 if (JCS_CMYK == cinfo.out_color_space) { | 768 if (JCS_CMYK == cinfo.out_color_space) { |
| 705 convert_CMYK_to_RGB(srcRow, cinfo.output_width); | 769 convert_CMYK_to_RGB(srcRow, cinfo.output_width); |
| 706 } | 770 } |
| 707 | 771 |
| 708 sampler.next(srcRow); | 772 sampler.next(srcRow); |
| 709 if (bm->height() - 1 == y) { | 773 if (bm->height() - 1 == y) { |
| 710 // we're done | 774 // we're done |
| 711 break; | 775 break; |
| 712 } | 776 } |
| 713 | 777 |
| 714 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { | 778 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { |
| 715 return return_false(cinfo, *bm, "skip rows"); | 779 return return_false(cinfo, bm, "skip rows"); |
| 716 } | 780 } |
| 717 } | 781 } |
| 718 | 782 |
| 719 // we formally skip the rest, so we don't get a complaint from libjpeg | 783 // we formally skip the rest, so we don't get a complaint from libjpeg |
| 720 if (!skip_src_rows(&cinfo, srcRow, | 784 if (!skip_src_rows(&cinfo, srcRow, |
| 721 cinfo.output_height - cinfo.output_scanline)) { | 785 cinfo.output_height - cinfo.output_scanline)) { |
| 722 return return_false(cinfo, *bm, "skip rows"); | 786 return return_false(cinfo, bm, "skip rows"); |
| 723 } | 787 } |
| 724 jpeg_finish_decompress(&cinfo); | 788 jpeg_finish_decompress(&cinfo); |
| 725 | 789 |
| 726 return true; | 790 return true; |
| 727 } | 791 } |
| 728 | 792 |
| 793 bool SkJPEGImageDecoder::decodeToYUV(jpeg_decompress_struct& cinfo) { |
| 794 uint8_t* bufferraw[3]; |
| 795 uint8_t* bufferraw2[32]; |
| 796 bufferraw[0] = (uint8_t*)&bufferraw2[0]; |
| 797 bufferraw[1] = (uint8_t*)&bufferraw2[16]; |
| 798 bufferraw[2] = (uint8_t*)&bufferraw2[24]; |
| 799 int yWidth = cinfo.output_width; |
| 800 int yHeight = cinfo.output_height; |
| 801 int yMaxH = yHeight - 1; |
| 802 int v = cinfo.cur_comp_info[0]->v_samp_factor; |
| 803 int uvWidth(0), uvHeight(0); |
| 804 compute_uv_size(cinfo, uvWidth, uvHeight); |
| 805 int uvMaxH = uvHeight - 1; |
| 806 |
| 807 SkAutoMalloc lastRowStorage(yWidth * 8); |
| 808 uint8_t* yLastRow = (uint8_t*)lastRowStorage.get(); |
| 809 uint8_t* uLastRow = yLastRow + 2 * yWidth; |
| 810 uint8_t* vLastRow = uLastRow + 2 * yWidth; |
| 811 uint8_t* dummyRow = vLastRow + 2 * yWidth; |
| 812 |
| 813 int scanlinesToRead = DCTSIZE * v; |
| 814 while (cinfo.output_scanline < cinfo.output_height) { |
| 815 // Request 8 or 16 scanlines: returns 0 or more scanlines. |
| 816 bool hasYLastRow(false), hasUVLastRow(false); |
| 817 for (int i = 0; i < scanlinesToRead; ++i) { |
| 818 int scanline = (cinfo.output_scanline + i); |
| 819 if (scanline < yMaxH) { |
| 820 bufferraw2[i] = &fYUVBuffers[0][scanline * fRowBytes[0]]; |
| 821 } else if (scanline == yMaxH) { |
| 822 bufferraw2[i] = yLastRow; |
| 823 hasYLastRow = true; |
| 824 } else { |
| 825 bufferraw2[i] = dummyRow; |
| 826 } |
| 827 } |
| 828 int scaledScanline = cinfo.output_scanline / v; |
| 829 for (int i = 0; i < 8; ++i) { |
| 830 int scanline = (scaledScanline + i); |
| 831 if (scanline < uvMaxH) { |
| 832 bufferraw2[16+i] = &fYUVBuffers[1][scanline * fRowBytes[1]]; |
| 833 bufferraw2[24+i] = &fYUVBuffers[2][scanline * fRowBytes[2]]; |
| 834 } else if (scanline == uvMaxH) { |
| 835 bufferraw2[16+i] = uLastRow; |
| 836 bufferraw2[24+i] = vLastRow; |
| 837 hasUVLastRow = true; |
| 838 } else { |
| 839 bufferraw2[16+i] = dummyRow; |
| 840 bufferraw2[24+i] = dummyRow; |
| 841 } |
| 842 } |
| 843 JDIMENSION scanlinesRead = |
| 844 jpeg_read_raw_data(&cinfo, (JSAMPIMAGE)bufferraw, scanlinesToRead); |
| 845 if (scanlinesRead == 0) { |
| 846 return false; |
| 847 } |
| 848 if (hasYLastRow) { |
| 849 memcpy(&fYUVBuffers[0][ yMaxH * yWidth], yLastRow, yWidth); |
| 850 } |
| 851 if (hasUVLastRow) { |
| 852 memcpy(&fYUVBuffers[1][uvMaxH * uvWidth], uLastRow, uvWidth); |
| 853 memcpy(&fYUVBuffers[2][uvMaxH * uvWidth], vLastRow, uvWidth); |
| 854 } |
| 855 } |
| 856 |
| 857 if (cinfo.output_scanline > cinfo.output_height) { |
| 858 cinfo.output_scanline = cinfo.output_height; |
| 859 } |
| 860 |
| 861 jpeg_finish_decompress(&cinfo); |
| 862 |
| 863 return true; |
| 864 } |
| 865 |
| 866 void SkJPEGImageDecoder::onSetYUVBuffers(void* yuv[3], size_t rowBytes[3]) { |
| 867 for (int i = 0; i < 3; ++i) { |
| 868 fYUVBuffers[i] = (uint8_t*)yuv[i]; |
| 869 fRowBytes[i] = rowBytes[i]; |
| 870 } |
| 871 } |
| 872 |
| 873 bool SkJPEGImageDecoder::onGetComponentSizes(SkStream* stream, SkISize sizes[3])
{ |
| 874 JPEGAutoClean autoClean; |
| 875 |
| 876 jpeg_decompress_struct cinfo; |
| 877 skjpeg_source_mgr srcManager(stream, this); |
| 878 |
| 879 skjpeg_error_mgr errorManager; |
| 880 set_error_mgr(&cinfo, &errorManager); |
| 881 |
| 882 // All objects need to be instantiated before this setjmp call so that |
| 883 // they will be cleaned up properly if an error occurs. |
| 884 if (setjmp(errorManager.fJmpBuf)) { |
| 885 return return_false(cinfo, NULL, "setjmp"); |
| 886 } |
| 887 |
| 888 initialize_info(&cinfo, &srcManager); |
| 889 autoClean.set(&cinfo); |
| 890 |
| 891 int status = jpeg_read_header(&cinfo, true); |
| 892 if (status != JPEG_HEADER_OK) { |
| 893 return return_false(cinfo, NULL, "read_header"); |
| 894 } |
| 895 |
| 896 if (isSupportedYUVFormat(cinfo)) { |
| 897 jpeg_start_decompress(&cinfo); // Compute output width |
| 898 sizes[0].set(cinfo.output_width, cinfo.output_height); |
| 899 int w(0), h(0); |
| 900 compute_uv_size(cinfo, w, h); |
| 901 sizes[1].set(w, h); |
| 902 sizes[2].set(w, h); |
| 903 jpeg_abort_decompress(&cinfo); |
| 904 return true; |
| 905 } |
| 906 return false; |
| 907 } |
| 908 |
| 729 #ifdef SK_BUILD_FOR_ANDROID | 909 #ifdef SK_BUILD_FOR_ANDROID |
| 730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
, int *height) { | 910 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
, int *height) { |
| 731 | 911 |
| 732 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str
eam, this))); | 912 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str
eam, this))); |
| 733 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); | 913 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); |
| 734 | 914 |
| 735 skjpeg_error_mgr sk_err; | 915 skjpeg_error_mgr sk_err; |
| 736 set_error_mgr(cinfo, &sk_err); | 916 set_error_mgr(cinfo, &sk_err); |
| 737 | 917 |
| 738 // All objects need to be instantiated before this setjmp call so that | 918 // All objects need to be instantiated before this setjmp call so that |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 // swap happening. If no, then we will use alloc to allocate pixels to | 1022 // swap happening. If no, then we will use alloc to allocate pixels to |
| 843 // prevent garbage collection. | 1023 // prevent garbage collection. |
| 844 int w = rect.width() / actualSampleSize; | 1024 int w = rect.width() / actualSampleSize; |
| 845 int h = rect.height() / actualSampleSize; | 1025 int h = rect.height() / actualSampleSize; |
| 846 bool swapOnly = (rect == region) && bm->isNull() && | 1026 bool swapOnly = (rect == region) && bm->isNull() && |
| 847 (w == bitmap.width()) && (h == bitmap.height()) && | 1027 (w == bitmap.width()) && (h == bitmap.height()) && |
| 848 ((startX - rect.x()) / actualSampleSize == 0) && | 1028 ((startX - rect.x()) / actualSampleSize == 0) && |
| 849 ((startY - rect.y()) / actualSampleSize == 0); | 1029 ((startY - rect.y()) / actualSampleSize == 0); |
| 850 if (swapOnly) { | 1030 if (swapOnly) { |
| 851 if (!this->allocPixelRef(&bitmap, NULL)) { | 1031 if (!this->allocPixelRef(&bitmap, NULL)) { |
| 852 return return_false(*cinfo, bitmap, "allocPixelRef"); | 1032 return return_false(*cinfo, &bitmap, "allocPixelRef"); |
| 853 } | 1033 } |
| 854 } else { | 1034 } else { |
| 855 if (!bitmap.allocPixels()) { | 1035 if (!bitmap.allocPixels()) { |
| 856 return return_false(*cinfo, bitmap, "allocPixels"); | 1036 return return_false(*cinfo, &bitmap, "allocPixels"); |
| 857 } | 1037 } |
| 858 } | 1038 } |
| 859 | 1039 |
| 860 SkAutoLockPixels alp(bitmap); | 1040 SkAutoLockPixels alp(bitmap); |
| 861 | 1041 |
| 862 #ifdef ANDROID_RGB | 1042 #ifdef ANDROID_RGB |
| 863 /* short-circuit the SkScaledBitmapSampler when possible, as this gives | 1043 /* short-circuit the SkScaledBitmapSampler when possible, as this gives |
| 864 a significant performance boost. | 1044 a significant performance boost. |
| 865 */ | 1045 */ |
| 866 if (skiaSampleSize == 1 && | 1046 if (skiaSampleSize == 1 && |
| 867 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_88
88) || | 1047 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_88
88) || |
| 868 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB
_565))) | 1048 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB
_565))) |
| 869 { | 1049 { |
| 870 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); | 1050 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); |
| 871 INT32 const bpr = bitmap.rowBytes(); | 1051 INT32 const bpr = bitmap.rowBytes(); |
| 872 int rowTotalCount = 0; | 1052 int rowTotalCount = 0; |
| 873 | 1053 |
| 874 while (rowTotalCount < height) { | 1054 while (rowTotalCount < height) { |
| 875 int rowCount = jpeg_read_tile_scanline(cinfo, | 1055 int rowCount = jpeg_read_tile_scanline(cinfo, |
| 876 fImageIndex->huffmanIndex(), | 1056 fImageIndex->huffmanIndex(), |
| 877 &rowptr); | 1057 &rowptr); |
| 878 // if rowCount == 0, then we didn't get a scanline, so abort. | 1058 // if rowCount == 0, then we didn't get a scanline, so abort. |
| 879 // onDecodeSubset() relies on onBuildTileIndex(), which | 1059 // onDecodeSubset() relies on onBuildTileIndex(), which |
| 880 // needs a complete image to succeed. | 1060 // needs a complete image to succeed. |
| 881 if (0 == rowCount) { | 1061 if (0 == rowCount) { |
| 882 return return_false(*cinfo, bitmap, "read_scanlines"); | 1062 return return_false(*cinfo, &bitmap, "read_scanlines"); |
| 883 } | 1063 } |
| 884 if (this->shouldCancelDecode()) { | 1064 if (this->shouldCancelDecode()) { |
| 885 return return_false(*cinfo, bitmap, "shouldCancelDecode"); | 1065 return return_false(*cinfo, &bitmap, "shouldCancelDecode"); |
| 886 } | 1066 } |
| 887 rowTotalCount += rowCount; | 1067 rowTotalCount += rowCount; |
| 888 rowptr += bpr; | 1068 rowptr += bpr; |
| 889 } | 1069 } |
| 890 | 1070 |
| 891 if (swapOnly) { | 1071 if (swapOnly) { |
| 892 bm->swap(bitmap); | 1072 bm->swap(bitmap); |
| 893 } else { | 1073 } else { |
| 894 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), | 1074 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), |
| 895 region.width(), region.height(), startX, startY); | 1075 region.width(), region.height(), startX, startY); |
| 896 } | 1076 } |
| 897 return true; | 1077 return true; |
| 898 } | 1078 } |
| 899 #endif | 1079 #endif |
| 900 | 1080 |
| 901 // check for supported formats | 1081 // check for supported formats |
| 902 SkScaledBitmapSampler::SrcConfig sc; | 1082 SkScaledBitmapSampler::SrcConfig sc; |
| 903 int srcBytesPerPixel; | 1083 int srcBytesPerPixel; |
| 904 | 1084 |
| 905 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) { | 1085 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) { |
| 906 return return_false(*cinfo, *bm, "jpeg colorspace"); | 1086 return return_false(*cinfo, bm, "jpeg colorspace"); |
| 907 } | 1087 } |
| 908 | 1088 |
| 909 if (!sampler.begin(&bitmap, sc, *this)) { | 1089 if (!sampler.begin(&bitmap, sc, *this)) { |
| 910 return return_false(*cinfo, bitmap, "sampler.begin"); | 1090 return return_false(*cinfo, &bitmap, "sampler.begin"); |
| 911 } | 1091 } |
| 912 | 1092 |
| 913 SkAutoMalloc srcStorage(width * srcBytesPerPixel); | 1093 SkAutoMalloc srcStorage(width * srcBytesPerPixel); |
| 914 uint8_t* srcRow = (uint8_t*)srcStorage.get(); | 1094 uint8_t* srcRow = (uint8_t*)srcStorage.get(); |
| 915 | 1095 |
| 916 // Possibly skip initial rows [sampler.srcY0] | 1096 // Possibly skip initial rows [sampler.srcY0] |
| 917 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.
srcY0())) { | 1097 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.
srcY0())) { |
| 918 return return_false(*cinfo, bitmap, "skip rows"); | 1098 return return_false(*cinfo, &bitmap, "skip rows"); |
| 919 } | 1099 } |
| 920 | 1100 |
| 921 // now loop through scanlines until y == bitmap->height() - 1 | 1101 // now loop through scanlines until y == bitmap->height() - 1 |
| 922 for (int y = 0;; y++) { | 1102 for (int y = 0;; y++) { |
| 923 JSAMPLE* rowptr = (JSAMPLE*)srcRow; | 1103 JSAMPLE* rowptr = (JSAMPLE*)srcRow; |
| 924 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex
(), &rowptr); | 1104 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. | 1105 // if row_count == 0, then we didn't get a scanline, so abort. |
| 926 // onDecodeSubset() relies on onBuildTileIndex(), which | 1106 // onDecodeSubset() relies on onBuildTileIndex(), which |
| 927 // needs a complete image to succeed. | 1107 // needs a complete image to succeed. |
| 928 if (0 == row_count) { | 1108 if (0 == row_count) { |
| 929 return return_false(*cinfo, bitmap, "read_scanlines"); | 1109 return return_false(*cinfo, &bitmap, "read_scanlines"); |
| 930 } | 1110 } |
| 931 if (this->shouldCancelDecode()) { | 1111 if (this->shouldCancelDecode()) { |
| 932 return return_false(*cinfo, bitmap, "shouldCancelDecode"); | 1112 return return_false(*cinfo, &bitmap, "shouldCancelDecode"); |
| 933 } | 1113 } |
| 934 | 1114 |
| 935 if (JCS_CMYK == cinfo->out_color_space) { | 1115 if (JCS_CMYK == cinfo->out_color_space) { |
| 936 convert_CMYK_to_RGB(srcRow, width); | 1116 convert_CMYK_to_RGB(srcRow, width); |
| 937 } | 1117 } |
| 938 | 1118 |
| 939 sampler.next(srcRow); | 1119 sampler.next(srcRow); |
| 940 if (bitmap.height() - 1 == y) { | 1120 if (bitmap.height() - 1 == y) { |
| 941 // we're done | 1121 // we're done |
| 942 break; | 1122 break; |
| 943 } | 1123 } |
| 944 | 1124 |
| 945 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, | 1125 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, |
| 946 sampler.srcDY() - 1)) { | 1126 sampler.srcDY() - 1)) { |
| 947 return return_false(*cinfo, bitmap, "skip rows"); | 1127 return return_false(*cinfo, &bitmap, "skip rows"); |
| 948 } | 1128 } |
| 949 } | 1129 } |
| 950 if (swapOnly) { | 1130 if (swapOnly) { |
| 951 bm->swap(bitmap); | 1131 bm->swap(bitmap); |
| 952 } else { | 1132 } else { |
| 953 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), | 1133 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), |
| 954 region.width(), region.height(), startX, startY); | 1134 region.width(), region.height(), startX, startY); |
| 955 } | 1135 } |
| 956 return true; | 1136 return true; |
| 957 } | 1137 } |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 return SkImageDecoder::kUnknown_Format; | 1413 return SkImageDecoder::kUnknown_Format; |
| 1234 } | 1414 } |
| 1235 | 1415 |
| 1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1416 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
| 1237 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; | 1417 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; |
| 1238 } | 1418 } |
| 1239 | 1419 |
| 1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); | 1420 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); |
| 1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); | 1421 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); |
| 1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); | 1422 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); |
| OLD | NEW |