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 |