| 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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 242 | 242 |
| 243 private: | 243 private: |
| 244 #ifdef SK_BUILD_FOR_ANDROID | 244 #ifdef SK_BUILD_FOR_ANDROID |
| 245 SkJPEGImageIndex* fImageIndex; | 245 SkJPEGImageIndex* fImageIndex; |
| 246 int fImageWidth; | 246 int fImageWidth; |
| 247 int fImageHeight; | 247 int fImageHeight; |
| 248 #endif | 248 #endif |
| 249 | 249 |
| 250 /** | 250 /** |
| 251 * Determine the appropriate bitmap config and out_color_space based on | 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 | 252 * both the preference of the caller and the jpeg_color_space on the |
| 253 * jpeg_decompress_struct passed in. | 253 * jpeg_decompress_struct passed in. |
| 254 * Must be called after jpeg_read_header. | 254 * Must be called after jpeg_read_header. |
| 255 */ | 255 */ |
| 256 SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*); | 256 SkColorType getBitmapColorType(jpeg_decompress_struct*); |
| 257 | 257 |
| 258 typedef SkImageDecoder INHERITED; | 258 typedef SkImageDecoder INHERITED; |
| 259 }; | 259 }; |
| 260 | 260 |
| 261 ////////////////////////////////////////////////////////////////////////// | 261 ////////////////////////////////////////////////////////////////////////// |
| 262 | 262 |
| 263 /* Automatically clean up after throwing an exception */ | 263 /* Automatically clean up after throwing an exception */ |
| 264 class JPEGAutoClean { | 264 class JPEGAutoClean { |
| 265 public: | 265 public: |
| 266 JPEGAutoClean(): cinfo_ptr(NULL) {} | 266 JPEGAutoClean(): cinfo_ptr(NULL) {} |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 if (decoder.getPreferQualityOverSpeed()) { | 393 if (decoder.getPreferQualityOverSpeed()) { |
| 394 cinfo->dct_method = JDCT_ISLOW; | 394 cinfo->dct_method = JDCT_ISLOW; |
| 395 } else { | 395 } else { |
| 396 cinfo->dct_method = JDCT_IFAST; | 396 cinfo->dct_method = JDCT_IFAST; |
| 397 } | 397 } |
| 398 #else | 398 #else |
| 399 cinfo->dct_method = JDCT_ISLOW; | 399 cinfo->dct_method = JDCT_ISLOW; |
| 400 #endif | 400 #endif |
| 401 } | 401 } |
| 402 | 402 |
| 403 SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cin
fo) { | 403 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo
) { |
| 404 SkASSERT(cinfo != NULL); | 404 SkASSERT(cinfo != NULL); |
| 405 | 405 |
| 406 SrcDepth srcDepth = k32Bit_SrcDepth; | 406 SrcDepth srcDepth = k32Bit_SrcDepth; |
| 407 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { | 407 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { |
| 408 srcDepth = k8BitGray_SrcDepth; | 408 srcDepth = k8BitGray_SrcDepth; |
| 409 } | 409 } |
| 410 | 410 |
| 411 SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false); | 411 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false)
; |
| 412 switch (config) { | 412 switch (colorType) { |
| 413 case SkBitmap::kA8_Config: | 413 case kAlpha_8_SkColorType: |
| 414 // Only respect A8 config if the original is grayscale, | 414 // Only respect A8 colortype if the original is grayscale, |
| 415 // in which case we will treat the grayscale as alpha | 415 // in which case we will treat the grayscale as alpha |
| 416 // values. | 416 // values. |
| 417 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { | 417 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { |
| 418 config = SkBitmap::kARGB_8888_Config; | 418 colorType = kN32_SkColorType; |
| 419 } | 419 } |
| 420 break; | 420 break; |
| 421 case SkBitmap::kARGB_8888_Config: | 421 case kN32_SkColorType: |
| 422 // Fall through. | 422 // Fall through. |
| 423 case SkBitmap::kARGB_4444_Config: | 423 case kARGB_4444_SkColorType: |
| 424 // Fall through. | 424 // Fall through. |
| 425 case SkBitmap::kRGB_565_Config: | 425 case kRGB_565_SkColorType: |
| 426 // These are acceptable destination configs. | 426 // These are acceptable destination colortypes. |
| 427 break; | 427 break; |
| 428 default: | 428 default: |
| 429 // Force all other configs to 8888. | 429 // Force all other colortypes to 8888. |
| 430 config = SkBitmap::kARGB_8888_Config; | 430 colorType = kN32_SkColorType; |
| 431 break; | 431 break; |
| 432 } | 432 } |
| 433 | 433 |
| 434 switch (cinfo->jpeg_color_space) { | 434 switch (cinfo->jpeg_color_space) { |
| 435 case JCS_CMYK: | 435 case JCS_CMYK: |
| 436 // Fall through. | 436 // Fall through. |
| 437 case JCS_YCCK: | 437 case JCS_YCCK: |
| 438 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up | 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 | 439 // so libjpeg will give us CMYK samples back and we will later |
| 440 // manually convert them to RGB | 440 // manually convert them to RGB |
| 441 cinfo->out_color_space = JCS_CMYK; | 441 cinfo->out_color_space = JCS_CMYK; |
| 442 break; | 442 break; |
| 443 case JCS_GRAYSCALE: | 443 case JCS_GRAYSCALE: |
| 444 if (SkBitmap::kA8_Config == config) { | 444 if (kAlpha_8_SkColorType == colorType) { |
| 445 cinfo->out_color_space = JCS_GRAYSCALE; | 445 cinfo->out_color_space = JCS_GRAYSCALE; |
| 446 break; | 446 break; |
| 447 } | 447 } |
| 448 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB | 448 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB |
| 449 // config. Fall through to set to the default. | 449 // colortype. Fall through to set to the default. |
| 450 default: | 450 default: |
| 451 cinfo->out_color_space = JCS_RGB; | 451 cinfo->out_color_space = JCS_RGB; |
| 452 break; | 452 break; |
| 453 } | 453 } |
| 454 return config; | 454 return colorType; |
| 455 } | 455 } |
| 456 | 456 |
| 457 #ifdef ANDROID_RGB | |
| 458 /** | 457 /** |
| 459 * Based on the config and dither mode, adjust out_color_space and | 458 * Based on the colortype and dither mode, adjust out_color_space and |
| 460 * dither_mode of cinfo. | 459 * dither_mode of cinfo. Only does work in ANDROID_RGB |
| 461 */ | 460 */ |
| 462 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, | 461 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, |
| 463 SkBitmap::Config config, | 462 SkColorType colorType, |
| 464 const SkImageDecoder& decoder) { | 463 const SkImageDecoder& decoder) { |
| 465 SkASSERT(cinfo != NULL); | 464 SkASSERT(cinfo != NULL); |
| 465 #ifdef ANDROID_RGB |
| 466 cinfo->dither_mode = JDITHER_NONE; | 466 cinfo->dither_mode = JDITHER_NONE; |
| 467 if (JCS_CMYK == cinfo->out_color_space) { | 467 if (JCS_CMYK == cinfo->out_color_space) { |
| 468 return; | 468 return; |
| 469 } | 469 } |
| 470 switch(config) { | 470 switch (colorType) { |
| 471 case SkBitmap::kARGB_8888_Config: | 471 case kN32_SkColorType: |
| 472 cinfo->out_color_space = JCS_RGBA_8888; | 472 cinfo->out_color_space = JCS_RGBA_8888; |
| 473 break; | 473 break; |
| 474 case SkBitmap::kRGB_565_Config: | 474 case kRGB_565_SkColorType: |
| 475 cinfo->out_color_space = JCS_RGB_565; | 475 cinfo->out_color_space = JCS_RGB_565; |
| 476 if (decoder.getDitherImage()) { | 476 if (decoder.getDitherImage()) { |
| 477 cinfo->dither_mode = JDITHER_ORDERED; | 477 cinfo->dither_mode = JDITHER_ORDERED; |
| 478 } | 478 } |
| 479 break; | 479 break; |
| 480 default: | 480 default: |
| 481 break; | 481 break; |
| 482 } | 482 } |
| 483 #endif |
| 483 } | 484 } |
| 484 #endif | |
| 485 | 485 |
| 486 | 486 |
| 487 /** | 487 /** |
| 488 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y. | 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 | 489 Used when decoding fails partway through reading scanlines to fill |
| 490 remaining lines. */ | 490 remaining lines. */ |
| 491 static void fill_below_level(int y, SkBitmap* bitmap) { | 491 static void fill_below_level(int y, SkBitmap* bitmap) { |
| 492 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height()); | 492 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height()); |
| 493 SkCanvas canvas(*bitmap); | 493 SkCanvas canvas(*bitmap); |
| 494 canvas.clipRect(SkRect::Make(rect)); | 494 canvas.clipRect(SkRect::Make(rect)); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 */ | 562 */ |
| 563 int sampleSize = this->getSampleSize(); | 563 int sampleSize = this->getSampleSize(); |
| 564 | 564 |
| 565 set_dct_method(*this, &cinfo); | 565 set_dct_method(*this, &cinfo); |
| 566 | 566 |
| 567 SkASSERT(1 == cinfo.scale_num); | 567 SkASSERT(1 == cinfo.scale_num); |
| 568 cinfo.scale_denom = sampleSize; | 568 cinfo.scale_denom = sampleSize; |
| 569 | 569 |
| 570 turn_off_visual_optimizations(&cinfo); | 570 turn_off_visual_optimizations(&cinfo); |
| 571 | 571 |
| 572 const SkBitmap::Config config = this->getBitmapConfig(&cinfo); | 572 const SkColorType colorType = this->getBitmapColorType(&cinfo); |
| 573 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ? |
| 574 kPremul_SkAlphaType : kOpaque_SkAlphaType; |
| 573 | 575 |
| 574 #ifdef ANDROID_RGB | 576 adjust_out_color_space_and_dither(&cinfo, colorType, *this); |
| 575 adjust_out_color_space_and_dither(&cinfo, config, *this); | |
| 576 #endif | |
| 577 | 577 |
| 578 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { | 578 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 579 // Assume an A8 bitmap is not opaque to avoid the check of each | 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 | 580 // individual pixel. It is very unlikely to be opaque, since |
| 581 // an opaque A8 bitmap would not be very interesting. | 581 // an opaque A8 bitmap would not be very interesting. |
| 582 // Otherwise, a jpeg image is opaque. | 582 // Otherwise, a jpeg image is opaque. |
| 583 return bm->setConfig(config, cinfo.image_width, cinfo.image_height, 0, | 583 return bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_heig
ht, |
| 584 SkBitmap::kA8_Config == config ? | 584 colorType, alphaType)); |
| 585 kPremul_SkAlphaType : kOpaque_SkAlphaType); | |
| 586 } | 585 } |
| 587 | 586 |
| 588 /* image_width and image_height are the original dimensions, available | 587 /* image_width and image_height are the original dimensions, available |
| 589 after jpeg_read_header(). To see the scaled dimensions, we have to call | 588 after jpeg_read_header(). To see the scaled dimensions, we have to call |
| 590 jpeg_start_decompress(), and then read output_width and output_height. | 589 jpeg_start_decompress(), and then read output_width and output_height. |
| 591 */ | 590 */ |
| 592 if (!jpeg_start_decompress(&cinfo)) { | 591 if (!jpeg_start_decompress(&cinfo)) { |
| 593 /* If we failed here, we may still have enough information to return | 592 /* If we failed here, we may still have enough information to return |
| 594 to the caller if they just wanted (subsampled bounds). If sampleSize | 593 to the caller if they just wanted (subsampled bounds). If sampleSize |
| 595 was 1, then we would have already returned. Thus we just check if | 594 was 1, then we would have already returned. Thus we just check if |
| 596 we're in kDecodeBounds_Mode, and that we have valid output sizes. | 595 we're in kDecodeBounds_Mode, and that we have valid output sizes. |
| 597 | 596 |
| 598 One reason to fail here is that we have insufficient stream data | 597 One reason to fail here is that we have insufficient stream data |
| 599 to complete the setup. However, output dimensions seem to get | 598 to complete the setup. However, output dimensions seem to get |
| 600 computed very early, which is why this special check can pay off. | 599 computed very early, which is why this special check can pay off. |
| 601 */ | 600 */ |
| 602 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension
s(cinfo)) { | 601 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension
s(cinfo)) { |
| 603 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, | 602 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, |
| 604 recompute_sampleSize(sampleSize, cinfo)); | 603 recompute_sampleSize(sampleSize, cinfo)); |
| 605 // Assume an A8 bitmap is not opaque to avoid the check of each | 604 // Assume an A8 bitmap is not opaque to avoid the check of each |
| 606 // individual pixel. It is very unlikely to be opaque, since | 605 // individual pixel. It is very unlikely to be opaque, since |
| 607 // an opaque A8 bitmap would not be very interesting. | 606 // an opaque A8 bitmap would not be very interesting. |
| 608 // Otherwise, a jpeg image is opaque. | 607 // Otherwise, a jpeg image is opaque. |
| 609 return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight()
, | 608 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled
Height(), |
| 610 0, SkBitmap::kA8_Config == config ? | 609 colorType, alphaType)); |
| 611 kPremul_SkAlphaType : kOpaque_SkAlphaType); | |
| 612 } else { | 610 } else { |
| 613 return return_false(cinfo, *bm, "start_decompress"); | 611 return return_false(cinfo, *bm, "start_decompress"); |
| 614 } | 612 } |
| 615 } | 613 } |
| 616 sampleSize = recompute_sampleSize(sampleSize, cinfo); | 614 sampleSize = recompute_sampleSize(sampleSize, cinfo); |
| 617 | 615 |
| 618 // should we allow the Chooser (if present) to pick a config for us??? | 616 // should we allow the Chooser (if present) to pick a colortype for us??? |
| 619 if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_heig
ht)) { | 617 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_h
eight)) { |
| 620 return return_false(cinfo, *bm, "chooseFromOneChoice"); | 618 return return_false(cinfo, *bm, "chooseFromOneChoice"); |
| 621 } | 619 } |
| 622 | 620 |
| 623 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl
eSize); | 621 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl
eSize); |
| 624 // Assume an A8 bitmap is not opaque to avoid the check of each | 622 // Assume an A8 bitmap is not opaque to avoid the check of each |
| 625 // individual pixel. It is very unlikely to be opaque, since | 623 // individual pixel. It is very unlikely to be opaque, since |
| 626 // an opaque A8 bitmap would not be very interesting. | 624 // an opaque A8 bitmap would not be very interesting. |
| 627 // Otherwise, a jpeg image is opaque. | 625 // Otherwise, a jpeg image is opaque. |
| 628 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, | 626 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), |
| 629 SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul
_SkAlphaType); | 627 colorType, alphaType)); |
| 630 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 628 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 631 return true; | 629 return true; |
| 632 } | 630 } |
| 633 if (!this->allocPixelRef(bm, NULL)) { | 631 if (!this->allocPixelRef(bm, NULL)) { |
| 634 return return_false(cinfo, *bm, "allocPixelRef"); | 632 return return_false(cinfo, *bm, "allocPixelRef"); |
| 635 } | 633 } |
| 636 | 634 |
| 637 SkAutoLockPixels alp(*bm); | 635 SkAutoLockPixels alp(*bm); |
| 638 | 636 |
| 639 #ifdef ANDROID_RGB | 637 #ifdef ANDROID_RGB |
| 640 /* short-circuit the SkScaledBitmapSampler when possible, as this gives | 638 /* short-circuit the SkScaledBitmapSampler when possible, as this gives |
| 641 a significant performance boost. | 639 a significant performance boost. |
| 642 */ | 640 */ |
| 643 if (sampleSize == 1 && | 641 if (sampleSize == 1 && |
| 644 ((config == SkBitmap::kARGB_8888_Config && | 642 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888
8) || |
| 645 cinfo.out_color_space == JCS_RGBA_8888) || | 643 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_
565))) |
| 646 (config == SkBitmap::kRGB_565_Config && | |
| 647 cinfo.out_color_space == JCS_RGB_565))) | |
| 648 { | 644 { |
| 649 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); | 645 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); |
| 650 INT32 const bpr = bm->rowBytes(); | 646 INT32 const bpr = bm->rowBytes(); |
| 651 | 647 |
| 652 while (cinfo.output_scanline < cinfo.output_height) { | 648 while (cinfo.output_scanline < cinfo.output_height) { |
| 653 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); | 649 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); |
| 654 if (0 == row_count) { | 650 if (0 == row_count) { |
| 655 // if row_count == 0, then we didn't get a scanline, | 651 // if row_count == 0, then we didn't get a scanline, |
| 656 // so return early. We will return a partial image. | 652 // so return early. We will return a partial image. |
| 657 fill_below_level(cinfo.output_scanline, bm); | 653 fill_below_level(cinfo.output_scanline, bm); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 | 753 |
| 758 // Init decoder to image decode mode | 754 // Init decoder to image decode mode |
| 759 if (!imageIndex->initializeInfoAndReadHeader()) { | 755 if (!imageIndex->initializeInfoAndReadHeader()) { |
| 760 return false; | 756 return false; |
| 761 } | 757 } |
| 762 | 758 |
| 763 // FIXME: This sets cinfo->out_color_space, which we may change later | 759 // FIXME: This sets cinfo->out_color_space, which we may change later |
| 764 // based on the config in onDecodeSubset. This should be fine, since | 760 // based on the config in onDecodeSubset. This should be fine, since |
| 765 // jpeg_init_read_tile_scanline will check out_color_space again after | 761 // jpeg_init_read_tile_scanline will check out_color_space again after |
| 766 // that change (when it calls jinit_color_deconverter). | 762 // that change (when it calls jinit_color_deconverter). |
| 767 (void) this->getBitmapConfig(cinfo); | 763 (void) this->getBitmapColorType(cinfo); |
| 768 | 764 |
| 769 turn_off_visual_optimizations(cinfo); | 765 turn_off_visual_optimizations(cinfo); |
| 770 | 766 |
| 771 // instead of jpeg_start_decompress() we start a tiled decompress | 767 // instead of jpeg_start_decompress() we start a tiled decompress |
| 772 if (!imageIndex->startTileDecompress()) { | 768 if (!imageIndex->startTileDecompress()) { |
| 773 return false; | 769 return false; |
| 774 } | 770 } |
| 775 | 771 |
| 776 SkASSERT(1 == cinfo->scale_num); | 772 SkASSERT(1 == cinfo->scale_num); |
| 777 fImageWidth = cinfo->output_width; | 773 fImageWidth = cinfo->output_width; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 808 | 804 |
| 809 if (setjmp(errorManager.fJmpBuf)) { | 805 if (setjmp(errorManager.fJmpBuf)) { |
| 810 return false; | 806 return false; |
| 811 } | 807 } |
| 812 | 808 |
| 813 int requestedSampleSize = this->getSampleSize(); | 809 int requestedSampleSize = this->getSampleSize(); |
| 814 cinfo->scale_denom = requestedSampleSize; | 810 cinfo->scale_denom = requestedSampleSize; |
| 815 | 811 |
| 816 set_dct_method(*this, cinfo); | 812 set_dct_method(*this, cinfo); |
| 817 | 813 |
| 818 const SkBitmap::Config config = this->getBitmapConfig(cinfo); | 814 const SkColorType colorType = this->getBitmapColorType(cinfo); |
| 819 #ifdef ANDROID_RGB | 815 adjust_out_color_space_and_dither(cinfo, colorType, *this); |
| 820 adjust_out_color_space_and_dither(cinfo, config, *this); | |
| 821 #endif | |
| 822 | 816 |
| 823 int startX = rect.fLeft; | 817 int startX = rect.fLeft; |
| 824 int startY = rect.fTop; | 818 int startY = rect.fTop; |
| 825 int width = rect.width(); | 819 int width = rect.width(); |
| 826 int height = rect.height(); | 820 int height = rect.height(); |
| 827 | 821 |
| 828 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), | 822 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), |
| 829 &startX, &startY, &width, &height); | 823 &startX, &startY, &width, &height); |
| 830 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); | 824 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); |
| 831 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_siz
e); | 825 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_siz
e); |
| 832 | 826 |
| 833 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); | 827 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); |
| 834 | 828 |
| 835 SkBitmap bitmap; | 829 SkBitmap bitmap; |
| 836 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); | |
| 837 // Assume an A8 bitmap is not opaque to avoid the check of each | 830 // Assume an A8 bitmap is not opaque to avoid the check of each |
| 838 // individual pixel. It is very unlikely to be opaque, since | 831 // individual pixel. It is very unlikely to be opaque, since |
| 839 // an opaque A8 bitmap would not be very interesting. | 832 // an opaque A8 bitmap would not be very interesting. |
| 840 // Otherwise, a jpeg image is opaque. | 833 // Otherwise, a jpeg image is opaque. |
| 841 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, | 834 bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight
(), colorType, |
| 842 config == SkBitmap::kA8_Config ? kPremul_SkAlphaType : | 835 kAlpha_8_SkColorType == colorType ? |
| 843 kOpaque_SkAlphaType); | 836 kPremul_SkAlphaType : kOpaque_SkAlphaTy
pe)); |
| 844 | 837 |
| 845 // Check ahead of time if the swap(dest, src) is possible or not. | 838 // Check ahead of time if the swap(dest, src) is possible or not. |
| 846 // If yes, then we will stick to AllocPixelRef since it's cheaper with the | 839 // If yes, then we will stick to AllocPixelRef since it's cheaper with the |
| 847 // swap happening. If no, then we will use alloc to allocate pixels to | 840 // swap happening. If no, then we will use alloc to allocate pixels to |
| 848 // prevent garbage collection. | 841 // prevent garbage collection. |
| 849 int w = rect.width() / actualSampleSize; | 842 int w = rect.width() / actualSampleSize; |
| 850 int h = rect.height() / actualSampleSize; | 843 int h = rect.height() / actualSampleSize; |
| 851 bool swapOnly = (rect == region) && bm->isNull() && | 844 bool swapOnly = (rect == region) && bm->isNull() && |
| 852 (w == bitmap.width()) && (h == bitmap.height()) && | 845 (w == bitmap.width()) && (h == bitmap.height()) && |
| 853 ((startX - rect.x()) / actualSampleSize == 0) && | 846 ((startX - rect.x()) / actualSampleSize == 0) && |
| 854 ((startY - rect.y()) / actualSampleSize == 0); | 847 ((startY - rect.y()) / actualSampleSize == 0); |
| 855 if (swapOnly) { | 848 if (swapOnly) { |
| 856 if (!this->allocPixelRef(&bitmap, NULL)) { | 849 if (!this->allocPixelRef(&bitmap, NULL)) { |
| 857 return return_false(*cinfo, bitmap, "allocPixelRef"); | 850 return return_false(*cinfo, bitmap, "allocPixelRef"); |
| 858 } | 851 } |
| 859 } else { | 852 } else { |
| 860 if (!bitmap.allocPixels()) { | 853 if (!bitmap.allocPixels()) { |
| 861 return return_false(*cinfo, bitmap, "allocPixels"); | 854 return return_false(*cinfo, bitmap, "allocPixels"); |
| 862 } | 855 } |
| 863 } | 856 } |
| 864 | 857 |
| 865 SkAutoLockPixels alp(bitmap); | 858 SkAutoLockPixels alp(bitmap); |
| 866 | 859 |
| 867 #ifdef ANDROID_RGB | 860 #ifdef ANDROID_RGB |
| 868 /* short-circuit the SkScaledBitmapSampler when possible, as this gives | 861 /* short-circuit the SkScaledBitmapSampler when possible, as this gives |
| 869 a significant performance boost. | 862 a significant performance boost. |
| 870 */ | 863 */ |
| 871 if (skiaSampleSize == 1 && | 864 if (skiaSampleSize == 1 && |
| 872 ((config == SkBitmap::kARGB_8888_Config && | 865 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_88
88) || |
| 873 cinfo->out_color_space == JCS_RGBA_8888) || | 866 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB
_565))) |
| 874 (config == SkBitmap::kRGB_565_Config && | |
| 875 cinfo->out_color_space == JCS_RGB_565))) | |
| 876 { | 867 { |
| 877 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); | 868 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); |
| 878 INT32 const bpr = bitmap.rowBytes(); | 869 INT32 const bpr = bitmap.rowBytes(); |
| 879 int rowTotalCount = 0; | 870 int rowTotalCount = 0; |
| 880 | 871 |
| 881 while (rowTotalCount < height) { | 872 while (rowTotalCount < height) { |
| 882 int rowCount = jpeg_read_tile_scanline(cinfo, | 873 int rowCount = jpeg_read_tile_scanline(cinfo, |
| 883 fImageIndex->huffmanIndex(), | 874 fImageIndex->huffmanIndex(), |
| 884 &rowptr); | 875 &rowptr); |
| 885 // if rowCount == 0, then we didn't get a scanline, so abort. | 876 // if rowCount == 0, then we didn't get a scanline, so abort. |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1109 uint32_t c = ctable[*src++]; | 1100 uint32_t c = ctable[*src++]; |
| 1110 dst[0] = SkGetPackedR32(c); | 1101 dst[0] = SkGetPackedR32(c); |
| 1111 dst[1] = SkGetPackedG32(c); | 1102 dst[1] = SkGetPackedG32(c); |
| 1112 dst[2] = SkGetPackedB32(c); | 1103 dst[2] = SkGetPackedB32(c); |
| 1113 #endif | 1104 #endif |
| 1114 dst += 3; | 1105 dst += 3; |
| 1115 } | 1106 } |
| 1116 } | 1107 } |
| 1117 | 1108 |
| 1118 static WriteScanline ChooseWriter(const SkBitmap& bm) { | 1109 static WriteScanline ChooseWriter(const SkBitmap& bm) { |
| 1119 switch (bm.config()) { | 1110 switch (bm.colorType()) { |
| 1120 case SkBitmap::kARGB_8888_Config: | 1111 case kN32_SkColorType: |
| 1121 return Write_32_YUV; | 1112 return Write_32_YUV; |
| 1122 case SkBitmap::kRGB_565_Config: | 1113 case kRGB_565_SkColorType: |
| 1123 return Write_16_YUV; | 1114 return Write_16_YUV; |
| 1124 case SkBitmap::kARGB_4444_Config: | 1115 case kARGB_4444_SkColorType: |
| 1125 return Write_4444_YUV; | 1116 return Write_4444_YUV; |
| 1126 case SkBitmap::kIndex8_Config: | 1117 case kIndex_8_SkColorType: |
| 1127 return Write_Index_YUV; | 1118 return Write_Index_YUV; |
| 1128 default: | 1119 default: |
| 1129 return NULL; | 1120 return NULL; |
| 1130 } | 1121 } |
| 1131 } | 1122 } |
| 1132 | 1123 |
| 1133 class SkJPEGImageEncoder : public SkImageEncoder { | 1124 class SkJPEGImageEncoder : public SkImageEncoder { |
| 1134 protected: | 1125 protected: |
| 1135 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { | 1126 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { |
| 1136 #ifdef TIME_ENCODE | 1127 #ifdef TIME_ENCODE |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 return SkImageDecoder::kUnknown_Format; | 1231 return SkImageDecoder::kUnknown_Format; |
| 1241 } | 1232 } |
| 1242 | 1233 |
| 1243 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1234 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
| 1244 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; | 1235 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; |
| 1245 } | 1236 } |
| 1246 | 1237 |
| 1247 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); | 1238 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); |
| 1248 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); | 1239 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); |
| 1249 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); | 1240 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); |
| OLD | NEW |