Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1090)

Unified Diff: src/pdf/SkPDFBitmap.cpp

Issue 1372783003: SkPDF: Implement drawImage*() properly (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-09-30 (Wednesday) 21:22:24 EDT Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pdf/SkPDFBitmap.h ('k') | src/pdf/SkPDFCanon.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pdf/SkPDFBitmap.cpp
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index de43221630e5ed85e9db28bdf8738c3957c54ada..1978040ec93309a4527912f55dea7d0ce5b32421 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -8,14 +8,33 @@
#include "SkColorPriv.h"
#include "SkData.h"
#include "SkDeflate.h"
-#include "SkImageGenerator.h"
+#include "SkImage_Base.h"
#include "SkJpegInfo.h"
#include "SkPDFBitmap.h"
#include "SkPDFCanon.h"
-#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkUnPreMultiply.h"
+void image_get_ro_pixels(const SkImage* image, SkBitmap* dst) {
+ if(as_IB(image)->getROPixels(dst)
+ && dst->dimensions() == image->dimensions()) {
+ return;
+ }
+ // no pixels or wrong size: fill with zeros.
+ SkAlphaType at = image->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+ dst->setInfo(SkImageInfo::MakeN32(image->width(), image->height(), at));
+}
+
+bool image_compute_is_opaque(const SkImage* image) {
+ if (image->isOpaque()) {
+ return true;
+ }
+ // keep output PDF small at cost of possible resource use.
+ SkBitmap bm;
+ image_get_ro_pixels(image, &bm);
+ return SkBitmap::ComputeIsOpaque(bm);
+}
+
////////////////////////////////////////////////////////////////////////////////
static void pdf_stream_begin(SkWStream* stream) {
@@ -239,80 +258,6 @@ static void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) {
}
}
-////////////////////////////////////////////////////////////////////////////////
-
-namespace {
-// This SkPDFObject only outputs the alpha layer of the given bitmap.
-class PDFAlphaBitmap : public SkPDFObject {
-public:
- PDFAlphaBitmap(const SkBitmap& bm) : fBitmap(bm) {}
- ~PDFAlphaBitmap() {}
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override;
-
-private:
- const SkBitmap fBitmap;
-};
-
-void PDFAlphaBitmap::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
- SkAutoLockPixels autoLockPixels(fBitmap);
- SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType ||
- fBitmap.getColorTable());
-
- // Write to a temporary buffer to get the compressed length.
- SkDynamicMemoryWStream buffer;
- SkDeflateWStream deflateWStream(&buffer);
- bitmap_alpha_to_a8(fBitmap, &deflateWStream);
- deflateWStream.finalize(); // call before detachAsStream().
- SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
-
- SkPDFDict pdfDict("XObject");
- pdfDict.insertName("Subtype", "Image");
- pdfDict.insertInt("Width", fBitmap.width());
- pdfDict.insertInt("Height", fBitmap.height());
- pdfDict.insertName("ColorSpace", "DeviceGray");
- pdfDict.insertInt("BitsPerComponent", 8);
- pdfDict.insertName("Filter", "FlateDecode");
- pdfDict.insertInt("Length", asset->getLength());
- pdfDict.emitObject(stream, objNumMap, substitutes);
-
- pdf_stream_begin(stream);
- stream->writeStream(asset.get(), asset->getLength());
- pdf_stream_end(stream);
-}
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-namespace {
-class PDFDefaultBitmap : public SkPDFBitmap {
-public:
- const SkAutoTUnref<SkPDFObject> fSMask;
- void emitObject(SkWStream*,
- const SkPDFObjNumMap&,
- const SkPDFSubstituteMap&) const override;
- void addResources(SkPDFObjNumMap*,
- const SkPDFSubstituteMap&) const override;
- PDFDefaultBitmap(const SkBitmap& bm, SkPDFObject* smask)
- : SkPDFBitmap(bm), fSMask(smask) {}
-};
-} // namespace
-
-void PDFDefaultBitmap::addResources(
- SkPDFObjNumMap* catalog,
- const SkPDFSubstituteMap& substitutes) const {
- if (fSMask.get()) {
- SkPDFObject* obj = substitutes.getSubstitute(fSMask.get());
- SkASSERT(obj);
- if (catalog->addObject(obj)) {
- obj->addResources(catalog, substitutes);
- }
- }
-}
-
static SkPDFArray* make_indexed_color_space(const SkColorTable* table) {
SkPDFArray* result = new SkPDFArray;
result->reserve(4);
@@ -343,37 +288,48 @@ static SkPDFArray* make_indexed_color_space(const SkColorTable* table) {
return result;
}
-void PDFDefaultBitmap::emitObject(SkWStream* stream,
- const SkPDFObjNumMap& objNumMap,
- const SkPDFSubstituteMap& substitutes) const {
- SkAutoLockPixels autoLockPixels(fBitmap);
- SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType ||
- fBitmap.getColorTable());
+static void emit_image_xobject(SkWStream* stream,
+ const SkImage* image,
+ bool alpha,
+ SkPDFObject* smask,
+ const SkPDFObjNumMap& objNumMap,
+ const SkPDFSubstituteMap& substitutes) {
+ SkBitmap bitmap;
+ image_get_ro_pixels(image, &bitmap); // TODO(halcanary): test
+ SkAutoLockPixels autoLockPixels(bitmap); // with malformed images.
+ SkASSERT(bitmap.colorType() != kIndex_8_SkColorType ||
+ bitmap.getColorTable());
// Write to a temporary buffer to get the compressed length.
SkDynamicMemoryWStream buffer;
SkDeflateWStream deflateWStream(&buffer);
- bitmap_to_pdf_pixels(fBitmap, &deflateWStream);
+ if (alpha) {
+ bitmap_alpha_to_a8(bitmap, &deflateWStream);
+ } else {
+ bitmap_to_pdf_pixels(bitmap, &deflateWStream);
+ }
deflateWStream.finalize(); // call before detachAsStream().
SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
- pdfDict.insertInt("Width", fBitmap.width());
- pdfDict.insertInt("Height", fBitmap.height());
- if (fBitmap.colorType() == kIndex_8_SkColorType) {
- SkASSERT(1 == pdf_color_component_count(fBitmap.colorType()));
+ pdfDict.insertInt("Width", bitmap.width());
+ pdfDict.insertInt("Height", bitmap.height());
+ if (alpha) {
+ pdfDict.insertName("ColorSpace", "DeviceGray");
+ } else if (bitmap.colorType() == kIndex_8_SkColorType) {
+ SkASSERT(1 == pdf_color_component_count(bitmap.colorType()));
pdfDict.insertObject("ColorSpace",
- make_indexed_color_space(fBitmap.getColorTable()));
- } else if (1 == pdf_color_component_count(fBitmap.colorType())) {
+ make_indexed_color_space(bitmap.getColorTable()));
+ } else if (1 == pdf_color_component_count(bitmap.colorType())) {
pdfDict.insertName("ColorSpace", "DeviceGray");
} else {
pdfDict.insertName("ColorSpace", "DeviceRGB");
}
- pdfDict.insertInt("BitsPerComponent", 8);
- if (fSMask) {
- pdfDict.insertObjRef("SMask", SkRef(fSMask.get()));
+ if (smask) {
+ pdfDict.insertObjRef("SMask", SkRef(smask));
}
+ pdfDict.insertInt("BitsPerComponent", 8);
pdfDict.insertName("Filter", "FlateDecode");
pdfDict.insertInt("Length", asset->getLength());
pdfDict.emitObject(stream, objNumMap, substitutes);
@@ -385,26 +341,68 @@ void PDFDefaultBitmap::emitObject(SkWStream* stream,
////////////////////////////////////////////////////////////////////////////////
-static const SkBitmap& immutable_bitmap(const SkBitmap& bm, SkBitmap* copy) {
- if (bm.isImmutable()) {
- return bm;
+namespace {
+// This SkPDFObject only outputs the alpha layer of the given bitmap.
+class PDFAlphaBitmap : public SkPDFObject {
+public:
+ PDFAlphaBitmap(const SkImage* image) : fImage(SkRef(image)) {}
+ ~PDFAlphaBitmap() {}
+ void emitObject(SkWStream* stream,
+ const SkPDFObjNumMap& objNumMap,
+ const SkPDFSubstituteMap& subs) const override {
+ emit_image_xobject(stream, fImage, true, nullptr, objNumMap, subs);
}
- bm.copyTo(copy);
- copy->setImmutable();
- return *copy;
-}
+
+private:
+ SkAutoTUnref<const SkImage> fImage;
+};
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace {
+class PDFDefaultBitmap : public SkPDFObject {
+public:
+ void emitObject(SkWStream* stream,
+ const SkPDFObjNumMap& objNumMap,
+ const SkPDFSubstituteMap& substitutes) const override {
+ emit_image_xobject(stream, fImage, false, fSMask, objNumMap, substitutes);
+ }
+ void addResources(SkPDFObjNumMap* catalog,
+ const SkPDFSubstituteMap& substitutes) const override {
+ if (fSMask.get()) {
+ SkPDFObject* obj = substitutes.getSubstitute(fSMask.get());
+ SkASSERT(obj);
+ if (catalog->addObject(obj)) {
+ obj->addResources(catalog, substitutes);
+ }
+ }
+ }
+ PDFDefaultBitmap(const SkImage* image, SkPDFObject* smask)
+ : fImage(SkRef(image)), fSMask(smask) {}
+
+private:
+ SkAutoTUnref<const SkImage> fImage;
+ const SkAutoTUnref<SkPDFObject> fSMask;
+};
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
namespace {
/**
- * This PDFObject assumes that its constructor was handed YUV JFIF
- * Jpeg-encoded data that can be directly embedded into a PDF.
+ * This PDFObject assumes that its constructor was handed YUV or
+ * Grayscale JFIF Jpeg-encoded data that can be directly embedded
+ * into a PDF.
*/
-class PDFJpegBitmap : public SkPDFBitmap {
+class PDFJpegBitmap : public SkPDFObject {
public:
+ SkISize fSize;
SkAutoTUnref<SkData> fData;
bool fIsYUV;
- PDFJpegBitmap(const SkBitmap& bm, SkData* data, bool isYUV)
- : SkPDFBitmap(bm), fData(SkRef(data)), fIsYUV(isYUV) {}
+ PDFJpegBitmap(SkISize size, SkData* data, bool isYUV)
+ : fSize(size), fData(SkRef(data)), fIsYUV(isYUV) {}
void emitObject(SkWStream*,
const SkPDFObjNumMap&,
const SkPDFSubstituteMap&) const override;
@@ -415,8 +413,8 @@ void PDFJpegBitmap::emitObject(SkWStream* stream,
const SkPDFSubstituteMap& substituteMap) const {
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
- pdfDict.insertInt("Width", fBitmap.width());
- pdfDict.insertInt("Height", fBitmap.height());
+ pdfDict.insertInt("Width", fSize.width());
+ pdfDict.insertInt("Height", fSize.height());
if (fIsYUV) {
pdfDict.insertName("ColorSpace", "DeviceRGB");
} else {
@@ -435,39 +433,23 @@ void PDFJpegBitmap::emitObject(SkWStream* stream,
////////////////////////////////////////////////////////////////////////////////
-SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon, const SkBitmap& bitmap) {
- SkASSERT(canon);
- if (!SkColorTypeIsValid(bitmap.colorType()) ||
- kUnknown_SkColorType == bitmap.colorType()) {
- return nullptr;
- }
- SkBitmap copy;
- const SkBitmap& bm = immutable_bitmap(bitmap, &copy);
- if (bm.drawsNothing()) {
- return nullptr;
- }
- if (SkPDFBitmap* canonBitmap = canon->findBitmap(bm)) {
- return SkRef(canonBitmap);
- }
-
- if (bm.pixelRef() && bm.pixelRefOrigin().isZero() &&
- bm.dimensions() == bm.pixelRef()->info().dimensions()) {
- // Requires the bitmap to be backed by lazy pixels.
- SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
- SkJFIFInfo info;
- if (data && SkIsJFIF(data, &info)) {
- bool yuv = info.fType == SkJFIFInfo::kYCbCr;
- SkPDFBitmap* pdfBitmap = new PDFJpegBitmap(bm, data, yuv);
- canon->addBitmap(pdfBitmap);
- return pdfBitmap;
+SkPDFObject* SkPDFCreateBitmapObject(const SkImage* image) {
+ SkAutoTUnref<SkData> data(image->refEncoded());
+ SkJFIFInfo info;
+ if (data && SkIsJFIF(data, &info)) {
+ bool yuv = info.fType == SkJFIFInfo::kYCbCr;
+ if (info.fSize == image->dimensions()) { // Sanity check.
+ // hold on to data, not image.
+ #ifdef SK_PDF_IMAGE_STATS
+ gJpegImageObjects.fetch_add(1);
+ #endif
+ return new PDFJpegBitmap(info.fSize, data, yuv);
}
}
-
- SkPDFObject* smask = nullptr;
- if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) {
- smask = new PDFAlphaBitmap(bm);
- }
- SkPDFBitmap* pdfBitmap = new PDFDefaultBitmap(bm, smask);
- canon->addBitmap(pdfBitmap);
- return pdfBitmap;
+ SkPDFObject* smask =
+ image_compute_is_opaque(image) ? nullptr : new PDFAlphaBitmap(image);
+ #ifdef SK_PDF_IMAGE_STATS
+ gRegularImageObjects.fetch_add(1);
+ #endif
+ return new PDFDefaultBitmap(image, smask);
}
« no previous file with comments | « src/pdf/SkPDFBitmap.h ('k') | src/pdf/SkPDFCanon.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698