Chromium Code Reviews| 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 |