|
|
Chromium Code Reviews|
Created:
5 years, 9 months ago by hal.canary Modified:
5 years, 8 months ago Reviewers:
mtklein CC:
reviews_skia.org Base URL:
https://skia.googlesource.com/skia.git@master Target Ref:
refs/heads/master Project:
skia Visibility:
Public. |
DescriptionPDF: Correctly embed JPEG images directly into PDF output.
We only embed images with YUV planes. That should only grab the
subset of color JPEGs supported by PDF.
BUG=skia:3180
Committed: https://skia.googlesource.com/skia/+/a8448bc3dfe0f2e768838b4416fb3ebf823b694e
Patch Set 1 : 2015-03-20 (Friday) 16:27:24 EDT #Patch Set 2 : 2015-03-20 (Friday) 18:26:44 EDT #Patch Set 3 : 2015-03-24 (Tuesday) 18:52:38 EDT #Patch Set 4 : 2015-03-24 (Tuesday) 22:25:33 EDT #Patch Set 5 : 2015-03-25 (Wednesday) 16:26:10 EDT #Patch Set 6 : 2015-03-25 (Wednesday) 16:28:39 EDT #
Total comments: 2
Patch Set 7 : 2015-03-27 (Friday) 14:57:49 EDT #Patch Set 8 : 2015-04-17 (Friday) 16:19:22 EDT #
Messages
Total messages: 26 (13 generated)
The CQ bit was checked by halcanary@google.com
Patchset #1 (id:1) has been deleted
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1025773002/20001
Note for Reviewers: The CQ is waiting for an approval. If you believe that the CL is not ready yet, or if you would like to L-G-T-M with comments then please uncheck the CQ checkbox. Waiting for LGTM from valid reviewer(s) till 2015-03-21 02:28 UTC
halcanary@google.com changed reviewers: + mtklein@google.com
PTAL
The CQ bit was unchecked by commit-bot@chromium.org
This issue passed the CQ. To commit it, remove "COMMIT=false" from the description and try again.
Take a look again while I test correctness.
The CQ bit was checked by halcanary@google.com
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1025773002/100001
lgtm https://codereview.chromium.org/1025773002/diff/120001/src/pdf/SkPDFBitmap.cpp File src/pdf/SkPDFBitmap.cpp (right): https://codereview.chromium.org/1025773002/diff/120001/src/pdf/SkPDFBitmap.cp... src/pdf/SkPDFBitmap.cpp:287: class PDFBitmap : public SkPDFBitmap { Oh come on.
Patchset #7 (id:140001) has been deleted
https://codereview.chromium.org/1025773002/diff/120001/src/pdf/SkPDFBitmap.cpp File src/pdf/SkPDFBitmap.cpp (right): https://codereview.chromium.org/1025773002/diff/120001/src/pdf/SkPDFBitmap.cp... src/pdf/SkPDFBitmap.cpp:287: class PDFBitmap : public SkPDFBitmap { On 2015/03/25 21:36:53, mtklein wrote: > Oh come on. Done.
The CQ bit was checked by halcanary@google.com
The patchset sent to the CQ was uploaded after l-g-t-m from mtklein@google.com Link to the patchset: https://codereview.chromium.org/1025773002/#ps160001 (title: "2015-03-27 (Friday) 14:57:49 EDT")
The CQ bit was unchecked by commit-bot@chromium.org
COMMIT=false is deprecated please use the dry run button instead.
The CQ bit was checked by halcanary@google.com
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1025773002/160001
The CQ bit was unchecked by commit-bot@chromium.org
Failed to apply patch for src/pdf/SkPDFBitmap.cpp:
While running git apply --index -3 -p1;
error: patch failed: src/pdf/SkPDFBitmap.cpp:6
Falling back to three-way merge...
Applied patch to 'src/pdf/SkPDFBitmap.cpp' with conflicts.
U src/pdf/SkPDFBitmap.cpp
Patch: src/pdf/SkPDFBitmap.cpp
Index: src/pdf/SkPDFBitmap.cpp
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index
e4580fcb98e69f7ec5b4f3eb63b69fd34bb207ab..d2bed41906f8c9ee092c84669bf1c018b073b770
100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -6,10 +6,13 @@
*/
#include "SkColorPriv.h"
+#include "SkData.h"
#include "SkFlate.h"
+#include "SkImageGenerator.h"
#include "SkPDFBitmap.h"
#include "SkPDFCanon.h"
#include "SkPDFCatalog.h"
+#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkUnPreMultiply.h"
@@ -248,7 +251,6 @@ public:
private:
const SkBitmap fBitmap;
- void emitDict(SkWStream*, SkPDFCatalog*, size_t) const;
};
void PDFAlphaBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
@@ -263,15 +265,6 @@ void PDFAlphaBitmap::emitObject(SkWStream* stream,
SkPDFCatalog* catalog) {
deflateWStream.finalize(); // call before detachAsStream().
SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
- this->emitDict(stream, catalog, asset->getLength());
- pdf_stream_begin(stream);
- stream->writeStream(asset.get(), asset->getLength());
- pdf_stream_end(stream);
-}
-
-void PDFAlphaBitmap::emitDict(SkWStream* stream,
- SkPDFCatalog* catalog,
- size_t length) const {
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
pdfDict.insertInt("Width", fBitmap.width());
@@ -279,14 +272,29 @@ void PDFAlphaBitmap::emitDict(SkWStream* stream,
pdfDict.insertName("ColorSpace", "DeviceGray");
pdfDict.insertInt("BitsPerComponent", 8);
pdfDict.insertName("Filter", "FlateDecode");
- pdfDict.insertInt("Length", length);
+ pdfDict.insertInt("Length", asset->getLength());
pdfDict.emitObject(stream, catalog);
+
+ pdf_stream_begin(stream);
+ stream->writeStream(asset.get(), asset->getLength());
+ pdf_stream_end(stream);
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
-void SkPDFBitmap::addResources(SkPDFCatalog* catalog) const {
+namespace {
+class PDFDefaultBitmap : public SkPDFBitmap {
+public:
+ const SkAutoTUnref<SkPDFObject> fSMask;
+ void emitObject(SkWStream*, SkPDFCatalog*) override;
+ void addResources(SkPDFCatalog*) const override;
+ PDFDefaultBitmap(const SkBitmap& bm, SkPDFObject* smask)
+ : SkPDFBitmap(bm), fSMask(smask) {}
+};
+} // namespace
+
+void PDFDefaultBitmap::addResources(SkPDFCatalog* catalog) const {
if (fSMask.get()) {
if (catalog->addObject(fSMask.get())) {
fSMask->addResources(catalog);
@@ -294,24 +302,6 @@ void SkPDFBitmap::addResources(SkPDFCatalog* catalog) const
{
}
}
-void SkPDFBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
- 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_to_pdf_pixels(fBitmap, &deflateWStream);
- deflateWStream.finalize(); // call before detachAsStream().
- SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
-
- this->emitDict(stream, catalog, asset->getLength());
- pdf_stream_begin(stream);
- stream->writeStream(asset.get(), asset->getLength());
- pdf_stream_end(stream);
-}
-
static SkPDFArray* make_indexed_color_space(const SkColorTable* table) {
SkPDFArray* result = SkNEW(SkPDFArray);
result->reserve(4);
@@ -342,9 +332,18 @@ static SkPDFArray* make_indexed_color_space(const
SkColorTable* table) {
return result;
}
-void SkPDFBitmap::emitDict(SkWStream* stream,
- SkPDFCatalog* catalog,
- size_t length) const {
+void PDFDefaultBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+ 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_to_pdf_pixels(fBitmap, &deflateWStream);
+ deflateWStream.finalize(); // call before detachAsStream().
+ SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
+
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
pdfDict.insertInt("Width", fBitmap.width());
@@ -363,15 +362,13 @@ void SkPDFBitmap::emitDict(SkWStream* stream,
pdfDict.insert("SMask", new SkPDFObjRef(fSMask))->unref();
}
pdfDict.insertName("Filter", "FlateDecode");
- pdfDict.insertInt("Length", length);
+ pdfDict.insertInt("Length", asset->getLength());
pdfDict.emitObject(stream, catalog);
-}
-
-SkPDFBitmap::SkPDFBitmap(const SkBitmap& bm,
- SkPDFObject* smask)
- : fBitmap(bm), fSMask(smask) {}
-SkPDFBitmap::~SkPDFBitmap() {}
+ pdf_stream_begin(stream);
+ stream->writeStream(asset.get(), asset->getLength());
+ pdf_stream_end(stream);
+}
////////////////////////////////////////////////////////////////////////////////
@@ -384,6 +381,55 @@ static const SkBitmap& immutable_bitmap(const SkBitmap& bm,
SkBitmap* copy) {
return *copy;
}
+namespace {
+/**
+ * This PDFObject assumes that its constructor was handed YUV JFIF
+ * Jpeg-encoded data that can be directly embedded into a PDF.
+ */
+class PDFJpegBitmap : public SkPDFBitmap {
+public:
+ SkAutoTUnref<SkData> fData;
+ PDFJpegBitmap(const SkBitmap& bm, SkData* data)
+ : SkPDFBitmap(bm), fData(SkRef(data)) {}
+ void emitObject(SkWStream*, SkPDFCatalog*) override;
+};
+
+void PDFJpegBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+ SkPDFDict pdfDict("XObject");
+ pdfDict.insertName("Subtype", "Image");
+ pdfDict.insertInt("Width", fBitmap.width());
+ pdfDict.insertInt("Height", fBitmap.height());
+ pdfDict.insertName("ColorSpace", "DeviceRGB");
+ pdfDict.insertInt("BitsPerComponent", 8);
+ pdfDict.insertName("Filter", "DCTDecode");
+ pdfDict.insertInt("ColorTransform", 0);
+ pdfDict.insertInt("Length", SkToInt(fData->size()));
+ pdfDict.emitObject(stream, catalog);
+ pdf_stream_begin(stream);
+ stream->write(fData->data(), fData->size());
+ pdf_stream_end(stream);
+}
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+static bool is_jfif_yuv_jpeg(SkData* data) {
+ const uint8_t bytesZeroToThree[] = {0xFF, 0xD8, 0xFF, 0xE0};
+ const uint8_t bytesSixToTen[] = {'J', 'F', 'I', 'F', 0};
+ // 0 1 2 3 4 5 6 7 8 9 10
+ // FF D8 FF E0 ?? ?? 'J' 'F' 'I' 'F' 00 ...
+ if (data->size() < 11 ||
+ 0 != memcmp(data->bytes(), bytesZeroToThree,
+ sizeof(bytesZeroToThree)) ||
+ 0 != memcmp(data->bytes() + 6, bytesSixToTen, sizeof(bytesSixToTen))) {
+ return false;
+ }
+ SkAutoTDelete<SkImageGenerator> gen(SkImageGenerator::NewFromData(data));
+ SkISize sizes[3];
+ // Only YUV JPEG allows access to YUV planes.
+ return gen && gen->getYUV8Planes(sizes, NULL, NULL, NULL);
+}
+
SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon, const SkBitmap& bitmap) {
SkASSERT(canon);
if (!SkColorTypeIsValid(bitmap.colorType()) ||
@@ -398,11 +444,23 @@ SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon, const
SkBitmap& bitmap) {
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());
+ if (data && is_jfif_yuv_jpeg(data)) {
+ SkPDFBitmap* pdfBitmap = SkNEW_ARGS(PDFJpegBitmap, (bm, data));
+ canon->addBitmap(pdfBitmap);
+ return pdfBitmap;
+ }
+ }
+
SkPDFObject* smask = NULL;
if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) {
smask = SkNEW_ARGS(PDFAlphaBitmap, (bm));
}
- SkPDFBitmap* pdfBitmap = SkNEW_ARGS(SkPDFBitmap, (bm, smask));
+ SkPDFBitmap* pdfBitmap = SkNEW_ARGS(PDFDefaultBitmap, (bm, smask));
canon->addBitmap(pdfBitmap);
return pdfBitmap;
}
The CQ bit was checked by halcanary@google.com
The patchset sent to the CQ was uploaded after l-g-t-m from mtklein@google.com Link to the patchset: https://codereview.chromium.org/1025773002/#ps180001 (title: "2015-04-17 (Friday) 16:19:22 EDT")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1025773002/180001
Message was sent while issue was closed.
Committed patchset #8 (id:180001) as https://skia.googlesource.com/skia/+/a8448bc3dfe0f2e768838b4416fb3ebf823b694e |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
