OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2010 The Android Open Source Project | 2 * Copyright 2010 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 #include "SkPDFImage.h" | 8 #include "SkPDFImage.h" |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
11 #include "SkColor.h" | 11 #include "SkColor.h" |
12 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
13 #include "SkData.h" | 13 #include "SkData.h" |
14 #include "SkFlate.h" | 14 #include "SkFlate.h" |
15 #include "SkPDFBitmap.h" | 15 #include "SkPDFBitmap.h" |
16 #include "SkPDFCatalog.h" | 16 #include "SkPDFCatalog.h" |
17 #include "SkPixelRef.h" | 17 #include "SkPixelRef.h" |
18 #include "SkRect.h" | 18 #include "SkRect.h" |
19 #include "SkStream.h" | 19 #include "SkStream.h" |
20 #include "SkString.h" | 20 #include "SkString.h" |
21 #include "SkUnPreMultiply.h" | 21 #include "SkUnPreMultiply.h" |
22 | 22 |
23 static const int kNoColorTransform = 0; | |
24 | |
25 static size_t get_uncompressed_size(const SkBitmap& bitmap, | 23 static size_t get_uncompressed_size(const SkBitmap& bitmap, |
26 const SkIRect& srcRect) { | 24 const SkIRect& srcRect) { |
27 switch (bitmap.colorType()) { | 25 switch (bitmap.colorType()) { |
28 case kIndex_8_SkColorType: | 26 case kIndex_8_SkColorType: |
29 return srcRect.width() * srcRect.height(); | 27 return srcRect.width() * srcRect.height(); |
30 case kARGB_4444_SkColorType: | 28 case kARGB_4444_SkColorType: |
31 return ((srcRect.width() * 3 + 1) / 2) * srcRect.height(); | 29 return ((srcRect.width() * 3 + 1) / 2) * srcRect.height(); |
32 case kRGB_565_SkColorType: | 30 case kRGB_565_SkColorType: |
33 return srcRect.width() * 3 * srcRect.height(); | 31 return srcRect.width() * 3 * srcRect.height(); |
34 case kRGBA_8888_SkColorType: | 32 case kRGBA_8888_SkColorType: |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 SkASSERT(false); | 448 SkASSERT(false); |
451 } | 449 } |
452 | 450 |
453 outBitmap.setImmutable(); | 451 outBitmap.setImmutable(); |
454 | 452 |
455 return outBitmap; | 453 return outBitmap; |
456 } | 454 } |
457 | 455 |
458 // static | 456 // static |
459 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, | 457 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, |
460 const SkIRect& srcRect, | 458 const SkIRect& srcRect) { |
461 SkData* (*encoder)(size_t*, const SkBitmap&) ) { | |
462 if (bitmap.colorType() == kUnknown_SkColorType) { | 459 if (bitmap.colorType() == kUnknown_SkColorType) { |
463 return NULL; | 460 return NULL; |
464 } | 461 } |
465 | 462 |
466 bool isTransparent = false; | 463 bool isTransparent = false; |
467 SkAutoTDelete<SkStream> alphaData; | 464 SkAutoTDelete<SkStream> alphaData; |
468 if (!bitmap.isOpaque()) { | 465 if (!bitmap.isOpaque()) { |
469 // Note that isOpaque is not guaranteed to return false for bitmaps | 466 // Note that isOpaque is not guaranteed to return false for bitmaps |
470 // with alpha support but a completely opaque alpha channel, | 467 // with alpha support but a completely opaque alpha channel, |
471 // so alphaData may still be NULL if we have a completely opaque | 468 // so alphaData may still be NULL if we have a completely opaque |
472 // (or transparent) bitmap. | 469 // (or transparent) bitmap. |
473 alphaData.reset( | 470 alphaData.reset( |
474 extract_image_data(bitmap, srcRect, true, &isTransparent)); | 471 extract_image_data(bitmap, srcRect, true, &isTransparent)); |
475 } | 472 } |
476 if (isTransparent) { | 473 if (isTransparent) { |
477 return NULL; | 474 return NULL; |
478 } | 475 } |
479 | 476 |
480 SkPDFImage* image; | 477 SkPDFImage* image; |
481 SkColorType colorType = bitmap.colorType(); | 478 SkColorType colorType = bitmap.colorType(); |
482 if (alphaData.get() != NULL && (kN32_SkColorType == colorType || | 479 if (alphaData.get() != NULL && (kN32_SkColorType == colorType || |
483 kARGB_4444_SkColorType == colorType)) { | 480 kARGB_4444_SkColorType == colorType)) { |
484 if (kN32_SkColorType == colorType) { | 481 if (kN32_SkColorType == colorType) { |
485 image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, | 482 image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, |
486 SkIRect::MakeWH(srcRect.width(), | 483 SkIRect::MakeWH(srcRect.width(), |
487 srcRect.height()), | 484 srcRect.height()))); |
488 encoder)); | |
489 } else { | 485 } else { |
490 SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect); | 486 SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect); |
491 image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false, | 487 image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false, |
492 SkIRect::MakeWH(srcRect.width(), | 488 SkIRect::MakeWH(srcRect.width(), |
493 srcRect.height()), | 489 srcRect.height()))); |
494 encoder)); | |
495 } | 490 } |
496 } else { | 491 } else { |
497 image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect, encoder)); | 492 image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect)); |
498 } | 493 } |
499 if (alphaData.get() != NULL) { | 494 if (alphaData.get() != NULL) { |
500 SkAutoTUnref<SkPDFImage> mask( | 495 SkAutoTUnref<SkPDFImage> mask( |
501 SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap, | 496 SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap, true, srcRect)) ); |
502 true, srcRect, NULL))); | |
503 image->insert("SMask", new SkPDFObjRef(mask))->unref(); | 497 image->insert("SMask", new SkPDFObjRef(mask))->unref(); |
504 } | 498 } |
505 return image; | 499 return image; |
506 } | 500 } |
507 | 501 |
508 SkPDFImage::~SkPDFImage() {} | 502 SkPDFImage::~SkPDFImage() {} |
509 | 503 |
510 SkPDFImage::SkPDFImage(SkStream* stream, | 504 SkPDFImage::SkPDFImage(SkStream* stream, |
511 const SkBitmap& bitmap, | 505 const SkBitmap& bitmap, |
512 bool isAlpha, | 506 bool isAlpha, |
513 const SkIRect& srcRect, | 507 const SkIRect& srcRect) |
514 SkData* (*encoder)(size_t*, const SkBitmap&)) | |
515 : fIsAlpha(isAlpha), | 508 : fIsAlpha(isAlpha), |
516 fSrcRect(srcRect), | 509 fSrcRect(srcRect) { |
517 fEncoder(encoder) { | |
518 | 510 |
519 if (bitmap.isImmutable()) { | 511 if (bitmap.isImmutable()) { |
520 fBitmap = bitmap; | 512 fBitmap = bitmap; |
521 } else { | 513 } else { |
522 bitmap.deepCopyTo(&fBitmap); | 514 bitmap.deepCopyTo(&fBitmap); |
523 fBitmap.setImmutable(); | 515 fBitmap.setImmutable(); |
524 } | 516 } |
525 | 517 |
526 if (stream != NULL) { | 518 if (stream != NULL) { |
527 this->setData(stream); | 519 this->setData(stream); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
581 decodeValue->append(scale5Val.get()); | 573 decodeValue->append(scale5Val.get()); |
582 insert("Decode", decodeValue.get()); | 574 insert("Decode", decodeValue.get()); |
583 } | 575 } |
584 } | 576 } |
585 | 577 |
586 SkPDFImage::SkPDFImage(SkPDFImage& pdfImage) | 578 SkPDFImage::SkPDFImage(SkPDFImage& pdfImage) |
587 : SkPDFStream(pdfImage), | 579 : SkPDFStream(pdfImage), |
588 fBitmap(pdfImage.fBitmap), | 580 fBitmap(pdfImage.fBitmap), |
589 fIsAlpha(pdfImage.fIsAlpha), | 581 fIsAlpha(pdfImage.fIsAlpha), |
590 fSrcRect(pdfImage.fSrcRect), | 582 fSrcRect(pdfImage.fSrcRect), |
591 fEncoder(pdfImage.fEncoder), | |
592 fStreamValid(pdfImage.fStreamValid) { | 583 fStreamValid(pdfImage.fStreamValid) { |
593 // Nothing to do here - the image params are already copied in SkPDFStream's | 584 // Nothing to do here - the image params are already copied in SkPDFStream's |
594 // constructor, and the bitmap will be regenerated and encoded in | 585 // constructor, and the bitmap will be regenerated and encoded in |
595 // populate. | 586 // populate. |
596 } | 587 } |
597 | 588 |
598 bool SkPDFImage::populate(SkPDFCatalog* catalog) { | 589 bool SkPDFImage::populate(SkPDFCatalog* catalog) { |
599 if (getState() == kUnused_State) { | 590 if (getState() == kUnused_State) { |
600 // Initializing image data for the first time. | 591 // Initializing image data for the first time. |
mtklein
2015/02/20 03:36:13
Do both these comments still make sense here?
hal.canary
2015/02/20 12:52:57
Yes. This class caches the Deflate-encoded data (
| |
601 if (fEncoder && get_uncompressed_size(fBitmap, fSrcRect) > 1) { | |
602 SkBitmap subset; | |
603 // Extract subset | |
604 if (!fBitmap.extractSubset(&subset, fSrcRect)) { | |
605 return false; | |
606 } | |
607 size_t pixelRefOffset = 0; | |
608 SkAutoTUnref<SkData> data(fEncoder(&pixelRefOffset, subset)); | |
609 if (data.get() && data->size() < get_uncompressed_size(fBitmap, | |
610 fSrcRect)) { | |
611 this->setData(data.get()); | |
612 | |
613 insertName("Filter", "DCTDecode"); | |
614 insertInt("ColorTransform", kNoColorTransform); | |
615 insertInt("Length", this->dataSize()); | |
616 setState(kCompressed_State); | |
617 return true; | |
618 } | |
619 } | |
620 // Fallback method | 592 // Fallback method |
621 if (!fStreamValid) { | 593 if (!fStreamValid) { |
622 SkAutoTDelete<SkStream> stream( | 594 SkAutoTDelete<SkStream> stream( |
623 extract_image_data(fBitmap, fSrcRect, fIsAlpha, NULL)); | 595 extract_image_data(fBitmap, fSrcRect, fIsAlpha, NULL)); |
624 this->setData(stream); | 596 this->setData(stream); |
625 fStreamValid = true; | 597 fStreamValid = true; |
626 } | 598 } |
627 return INHERITED::populate(catalog); | 599 return INHERITED::populate(catalog); |
628 } | 600 } |
629 #ifndef SK_NO_FLATE | 601 #ifndef SK_NO_FLATE |
630 else if (getState() == kNoCompression_State) { | 602 else if (getState() == kNoCompression_State) { |
631 #else // SK_NO_FLATE | |
632 else if (getState() == kNoCompression_State && fEncoder) { | |
633 #endif // SK_NO_FLATE | |
634 // Compression has not been requested when the stream was first created, | 603 // Compression has not been requested when the stream was first created, |
635 // but the new catalog wants it compressed. | 604 // but the new catalog wants it compressed. |
636 if (!getSubstitute()) { | 605 if (!getSubstitute()) { |
637 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); | 606 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); |
638 setSubstitute(substitute); | 607 setSubstitute(substitute); |
639 catalog->setSubstitute(this, substitute); | 608 catalog->setSubstitute(this, substitute); |
640 } | 609 } |
641 return false; | 610 return false; |
642 } | 611 } |
612 #endif // SK_NO_FLATE | |
643 return true; | 613 return true; |
644 } | 614 } |
645 | 615 |
646 #if 0 // reenable when we can figure out the JPEG colorspace | 616 #if 0 // reenable when we can figure out the JPEG colorspace |
647 namespace { | 617 namespace { |
648 /** | 618 /** |
649 * This PDFObject assumes that its constructor was handed | 619 * This PDFObject assumes that its constructor was handed |
650 * Jpeg-encoded data that can be directly embedded into a PDF. | 620 * Jpeg-encoded data that can be directly embedded into a PDF. |
651 */ | 621 */ |
652 class PDFJPEGImage : public SkPDFObject { | 622 class PDFJPEGImage : public SkPDFObject { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 return ((0 == memcmp(data->bytes(), bytesZeroToThree, | 682 return ((0 == memcmp(data->bytes(), bytesZeroToThree, |
713 sizeof(bytesZeroToThree))) | 683 sizeof(bytesZeroToThree))) |
714 && (0 == memcmp(data->bytes() + 6, bytesSixToTen, | 684 && (0 == memcmp(data->bytes() + 6, bytesSixToTen, |
715 sizeof(bytesSixToTen)))); | 685 sizeof(bytesSixToTen)))); |
716 } | 686 } |
717 } // namespace | 687 } // namespace |
718 #endif | 688 #endif |
719 | 689 |
720 SkPDFObject* SkPDFCreateImageObject( | 690 SkPDFObject* SkPDFCreateImageObject( |
721 const SkBitmap& bitmap, | 691 const SkBitmap& bitmap, |
722 const SkIRect& subset, | 692 const SkIRect& subset) { |
723 SkData* (*encoder)(size_t*, const SkBitmap&)) { | |
724 if (SkPDFObject* pdfBitmap = SkPDFBitmap::Create(bitmap, subset)) { | 693 if (SkPDFObject* pdfBitmap = SkPDFBitmap::Create(bitmap, subset)) { |
725 return pdfBitmap; | 694 return pdfBitmap; |
726 } | 695 } |
727 #if 0 // reenable when we can figure out the JPEG colorspace | 696 #if 0 // reenable when we can figure out the JPEG colorspace |
728 if (SkIRect::MakeWH(bitmap.width(), bitmap.height()) == subset) { | 697 if (SkIRect::MakeWH(bitmap.width(), bitmap.height()) == subset) { |
729 SkAutoTUnref<SkData> encodedData(ref_encoded_data(bitmap)); | 698 SkAutoTUnref<SkData> encodedData(ref_encoded_data(bitmap)); |
730 if (is_jfif_jpeg(encodedData)) { | 699 if (is_jfif_jpeg(encodedData)) { |
731 return SkNEW_ARGS(PDFJPEGImage, | 700 return SkNEW_ARGS(PDFJPEGImage, |
732 (encodedData, bitmap.width(), bitmap.height())); | 701 (encodedData, bitmap.width(), bitmap.height())); |
733 } | 702 } |
734 } | 703 } |
735 #endif | 704 #endif |
736 return SkPDFImage::CreateImage(bitmap, subset, encoder); | 705 return SkPDFImage::CreateImage(bitmap, subset); |
737 } | 706 } |
OLD | NEW |