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

Unified Diff: src/pdf/SkPDFImage.cpp

Issue 515493003: JPEG(JFIF only) directly embedded into PDF (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: nits from reed@ Created 6 years, 4 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/SkPDFImage.h ('k') | tests/PDFJpegEmbedTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pdf/SkPDFImage.cpp
diff --git a/src/pdf/SkPDFImage.cpp b/src/pdf/SkPDFImage.cpp
index 715fb4859dc9bb256cd6f0196927f131e32ace87..49460510d9b6f4ef8eb140c3b4c147c0470779d1 100644
--- a/src/pdf/SkPDFImage.cpp
+++ b/src/pdf/SkPDFImage.cpp
@@ -13,6 +13,7 @@
#include "SkData.h"
#include "SkFlate.h"
#include "SkPDFCatalog.h"
+#include "SkPixelRef.h"
#include "SkRect.h"
#include "SkStream.h"
#include "SkString.h"
@@ -628,3 +629,91 @@ bool SkPDFImage::populate(SkPDFCatalog* catalog) {
}
return true;
}
+
+namespace {
+/**
+ * This PDFObject assumes that its constructor was handed
+ * Jpeg-encoded data that can be directly embedded into a PDF.
+ */
+class PDFJPEGImage : public SkPDFObject {
+ SkAutoTUnref<SkData> fData;
+ int fWidth;
+ int fHeight;
+public:
+ PDFJPEGImage(SkData* data, int width, int height)
+ : fData(SkRef(data)), fWidth(width), fHeight(height) {}
+ virtual void getResources(const SkTSet<SkPDFObject*>&,
+ SkTSet<SkPDFObject*>*) SK_OVERRIDE {}
+ virtual void emitObject(
+ SkWStream* stream,
+ SkPDFCatalog* catalog, bool indirect) SK_OVERRIDE {
+ if (indirect) {
+ this->emitIndirectObject(stream, catalog);
+ return;
+ }
+ SkASSERT(fData.get());
+ const char kPrefaceFormat[] =
+ "<<"
+ "/Type /XObject\n"
+ "/Subtype /Image\n"
+ "/Width %d\n"
+ "/Height %d\n"
+ "/ColorSpace /DeviceRGB\n"
+ "/BitsPerComponent 8\n"
+ "/Filter /DCTDecode\n"
+ "/ColorTransform 0\n"
+ "/Length " SK_SIZE_T_SPECIFIER "\n"
+ ">> stream\n";
+ SkString preface(
+ SkStringPrintf(kPrefaceFormat, fWidth, fHeight, fData->size()));
+ const char kPostface[] = "\nendstream";
+ stream->write(preface.c_str(), preface.size());
+ stream->write(fData->data(), fData->size());
+ stream->write(kPostface, sizeof(kPostface));
+ }
+};
+
+/**
+ * If the bitmap is not subsetted, return its encoded data, if
+ * availible.
+ */
+static inline SkData* ref_encoded_data(const SkBitmap& bm) {
+ if ((NULL == bm.pixelRef())
+ || !bm.pixelRefOrigin().isZero()
+ || (bm.info().dimensions() != bm.pixelRef()->info().dimensions())) {
+ return NULL;
+ }
+ return bm.pixelRef()->refEncodedData();
+}
+
+/*
+ * This functions may give false negatives but no false positives.
+ */
+static bool is_jfif_jpeg(SkData* data) {
+ if (!data || (data->size() < 11)) {
+ return false;
+ }
+ 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 ...
+ return ((0 == memcmp(data->bytes(), bytesZeroToThree,
+ sizeof(bytesZeroToThree)))
+ && (0 == memcmp(data->bytes() + 6, bytesSixToTen,
+ sizeof(bytesSixToTen))));
+}
+} // namespace
+
+SkPDFObject* SkPDFCreateImageObject(
+ const SkBitmap& bitmap,
+ const SkIRect& subset,
+ SkPicture::EncodeBitmap encoder) {
+ if (SkIRect::MakeWH(bitmap.width(), bitmap.height()) == subset) {
+ SkAutoTUnref<SkData> encodedData(ref_encoded_data(bitmap));
+ if (is_jfif_jpeg(encodedData)) {
+ return SkNEW_ARGS(PDFJPEGImage,
+ (encodedData, bitmap.width(), bitmap.height()));
+ }
+ }
+ return SkPDFImage::CreateImage(bitmap, subset, encoder);
+}
« no previous file with comments | « src/pdf/SkPDFImage.h ('k') | tests/PDFJpegEmbedTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698