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

Unified Diff: src/pdf/SkPDFBitmap.cpp

Issue 1686313005: SkPDF: Implement Paeth predictor for images. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-02-25 (Thursday) 14:57:16 EST Created 4 years, 10 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 | « gyp/pdf.gypi ('k') | src/pdf/SkPngPredictors.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 4e49db518d802896ed069a75fe4f3f66d9bd0bb2..85874ed707658dbdcd4fcff7cd5f01f5505a7cb9 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -14,6 +14,7 @@
#include "SkPDFCanon.h"
#include "SkStream.h"
#include "SkUnPreMultiply.h"
+#include "SkPngPredictors.h"
void image_get_ro_pixels(const SkImage* image, SkBitmap* dst) {
if(as_IB(image)->getROPixels(dst)
@@ -172,12 +173,70 @@ static size_t pdf_color_component_count(SkColorType ct) {
}
}
-static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) {
+//#define SK_PDF_USE_BEST_PNG_PREDICTOR
+//#define SK_PDF_USE_PAETH_PNG_PREDICTOR
+namespace {
+#if defined(SK_PDF_USE_BEST_PNG_PREDICTOR) || defined(SK_PDF_USE_PAETH_PNG_PREDICTOR)
+template<int BPP>
+class PngPredictor {
+public:
+ PngPredictor(int widthInPixels)
+ : fBuffer(2 * (BPP * widthInPixels + 1))
+ , fWidth(widthInPixels)
+ , fFirstline(true) {
+ fScanline = fBuffer.get();
+ fPrevScanline = &fScanline[BPP * widthInPixels + 1];
+ }
+ bool predicts() { return true; }
+ uint8_t* scanline() { return &fScanline[1]; }
+ void write(SkWStream* out) {
+ static_assert(3 == BPP || 1 == BPP, "");
+ #if defined(SK_PDF_USE_BEST_PNG_PREDICTOR) // smaller
+ auto encode = (3 == BPP) ? &SkPngEncode3 : &SkPngEncode1;
+ #elif defined(SK_PDF_USE_PAETH_PNG_PREDICTOR) // faster
+ auto encode = (3 == BPP) ? &SkPaethEncode3 : &SkPaethEncode1;
+ #endif
+ fPrevScanline[0] = encode(
+ fWidth, fFirstline ? nullptr : &fPrevScanline[1],
+ &fScanline[1], &fPrevScanline[1]);
+ out->write(fPrevScanline, BPP * fWidth + 1);
+ SkTSwap(fScanline, fPrevScanline);
+ fFirstline = false;
+ }
+private:
+ SkAutoTMalloc<uint8_t> fBuffer;
+ uint8_t* fScanline;
+ uint8_t* fPrevScanline;
+ uint8_t* fScratch;
+ int fWidth;
+ bool fFirstline;
+};
+#else
+template<int BPP>
+class PngPredictor {
+public:
+ PngPredictor(int widthInPixels)
+ : fBuffer(BPP * widthInPixels)
+ , fWidthInBytes(BPP * widthInPixels) {
+ }
+ bool predicts() { return false; }
+ uint8_t* scanline() { return fBuffer.get(); }
+ void write(SkWStream* out) {
+ out->write(fBuffer.get(), fWidthInBytes);
+ }
+private:
+ SkAutoTMalloc<uint8_t> fBuffer;
+ int fWidthInBytes;
+};
+#endif
+} // namespace
+
+static bool bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) {
if (!bitmap.getPixels()) {
size_t size = pixel_count(bitmap) *
pdf_color_component_count(bitmap.colorType());
fill_stream(out, '\x00', size);
- return;
+ return false;
}
SkBitmap copy;
const SkBitmap& bm = not4444(bitmap, &copy);
@@ -187,10 +246,10 @@ static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType: {
SkASSERT(3 == pdf_color_component_count(colorType));
- SkAutoTMalloc<uint8_t> scanline(3 * bm.width());
+ PngPredictor<3> pngPredictorFilter(bm.width());
for (int y = 0; y < bm.height(); ++y) {
const uint32_t* src = bm.getAddr32(0, y);
- uint8_t* dst = scanline.get();
+ uint8_t* dst = pngPredictorFilter.scanline();
for (int x = 0; x < bm.width(); ++x) {
uint32_t color = *src++;
U8CPU alpha = SkGetA32Component(color, colorType);
@@ -201,30 +260,30 @@ static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) {
}
dst += 3;
}
- out->write(scanline.get(), 3 * bm.width());
+ pngPredictorFilter.write(out);
}
- return;
+ return pngPredictorFilter.predicts();
}
case kRGB_565_SkColorType: {
SkASSERT(3 == pdf_color_component_count(colorType));
- SkAutoTMalloc<uint8_t> scanline(3 * bm.width());
+ PngPredictor<3> pngPredictorFilter(bm.width());
for (int y = 0; y < bm.height(); ++y) {
const uint16_t* src = bm.getAddr16(0, y);
- uint8_t* dst = scanline.get();
+ uint8_t* dst = pngPredictorFilter.scanline();
for (int x = 0; x < bm.width(); ++x) {
U16CPU color565 = *src++;
*dst++ = SkPacked16ToR32(color565);
*dst++ = SkPacked16ToG32(color565);
*dst++ = SkPacked16ToB32(color565);
}
- out->write(scanline.get(), 3 * bm.width());
+ pngPredictorFilter.write(out);
}
- return;
+ return pngPredictorFilter.predicts();
}
case kAlpha_8_SkColorType:
SkASSERT(1 == pdf_color_component_count(colorType));
fill_stream(out, '\x00', pixel_count(bm));
- return;
+ return false;
case kGray_8_SkColorType:
case kIndex_8_SkColorType:
SkASSERT(1 == pdf_color_component_count(colorType));
@@ -232,20 +291,21 @@ static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) {
for (int y = 0; y < bm.height(); ++y) {
out->write(bm.getAddr8(0, y), bm.width());
}
- return;
+ return false;
case kUnknown_SkColorType:
case kARGB_4444_SkColorType:
default:
SkDEBUGFAIL("unexpected color type");
+ return false;
}
}
////////////////////////////////////////////////////////////////////////////////
-static void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) {
+static bool bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) {
if (!bitmap.getPixels()) {
fill_stream(out, '\xFF', pixel_count(bitmap));
- return;
+ return false;
}
SkBitmap copy;
const SkBitmap& bm = not4444(bitmap, &copy);
@@ -254,22 +314,22 @@ static void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) {
switch (colorType) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType: {
- SkAutoTMalloc<uint8_t> scanline(bm.width());
+ PngPredictor<1> pngPredictorFilter(bm.width());
for (int y = 0; y < bm.height(); ++y) {
- uint8_t* dst = scanline.get();
+ uint8_t* dst = pngPredictorFilter.scanline();
const SkPMColor* src = bm.getAddr32(0, y);
for (int x = 0; x < bm.width(); ++x) {
*dst++ = SkGetA32Component(*src++, colorType);
}
- out->write(scanline.get(), bm.width());
+ pngPredictorFilter.write(out);
}
- return;
+ return pngPredictorFilter.predicts();
}
case kAlpha_8_SkColorType:
for (int y = 0; y < bm.height(); ++y) {
out->write(bm.getAddr8(0, y), bm.width());
}
- return;
+ return false;
case kIndex_8_SkColorType: {
SkColorTable* ct = bm.getColorTable();
SkASSERT(ct);
@@ -282,18 +342,19 @@ static void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) {
}
out->write(scanline.get(), bm.width());
}
- return;
+ return false;
}
case kRGB_565_SkColorType:
case kGray_8_SkColorType:
SkDEBUGFAIL("color type has no alpha");
- return;
+ return false;
case kARGB_4444_SkColorType:
SkDEBUGFAIL("4444 color type should have been converted to N32");
- return;
+ return false;
case kUnknown_SkColorType:
default:
SkDEBUGFAIL("unexpected color type");
+ return false;
}
}
@@ -340,10 +401,11 @@ static void emit_image_xobject(SkWStream* stream,
// Write to a temporary buffer to get the compressed length.
SkDynamicMemoryWStream buffer;
SkDeflateWStream deflateWStream(&buffer);
+ bool usePngPredictor = false;
if (alpha) {
- bitmap_alpha_to_a8(bitmap, &deflateWStream);
+ usePngPredictor = bitmap_alpha_to_a8(bitmap, &deflateWStream);
} else {
- bitmap_to_pdf_pixels(bitmap, &deflateWStream);
+ usePngPredictor = bitmap_to_pdf_pixels(bitmap, &deflateWStream);
}
deflateWStream.finalize(); // call before detachAsStream().
SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
@@ -368,6 +430,14 @@ static void emit_image_xobject(SkWStream* stream,
}
pdfDict.insertInt("BitsPerComponent", 8);
pdfDict.insertName("Filter", "FlateDecode");
+ if (usePngPredictor) {
+ SkAutoTUnref<SkPDFDict> params(new SkPDFDict);
+ params->insertInt("BitsPerComponent", 8);
+ params->insertInt("Predictor", 15);
+ params->insertInt("Colors", alpha ? 1 : 3);
+ params->insertInt("Columns", bitmap.width());
+ pdfDict.insertObject("DecodeParms", params.detach());
+ }
pdfDict.insertInt("Length", asset->getLength());
pdfDict.emitObject(stream, objNumMap, substitutes);
« no previous file with comments | « gyp/pdf.gypi ('k') | src/pdf/SkPngPredictors.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698