From 9cd527bc1f384926985d63c741641316a66f17a4 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 7 Sep 2018 19:16:23 +0200 Subject: Add support for generating PDFs with losslessly encoded images This patch adds the QPainter::LosslessImageRendering flag to QPainter::RenderHints and allows QPdfEngine to recognize it and encode images using a lossless data compression algorithm provided by zlib instead of using lossy JPEG compression, which can produce artifacts with some images. Task-number: QTBUG-54809 Change-Id: If9e2bc64da3bf3afcd5d6c74f0ee82336ef05a19 Reviewed-by: Lars Knoll --- src/gui/painting/qpainter.cpp | 7 +++++++ src/gui/painting/qpainter.h | 3 ++- src/gui/painting/qpdf.cpp | 15 ++++++++++----- src/gui/painting/qpdf_p.h | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src/gui') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index b70b29e54e..df2f5e11d3 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1437,6 +1437,13 @@ void QPainterPrivate::updateState(QPainterState *newState) by slightly less than half a pixel. Also will treat default constructed pens as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5. + \value LosslessImageRendering Use a lossless image rendering, whenever possible. + Currently, this hint is only used when QPainter is employed to output a PDF + file through QPrinter or QPdfWriter, where drawImage()/drawPixmap() calls + will encode images using a lossless compression algorithm instead of lossy + JPEG compression. + This value was added in Qt 5.13. + \sa renderHints(), setRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}, {Concentric Circles Example} diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 482f5fb63d..87c4899f0b 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -91,7 +91,8 @@ public: SmoothPixmapTransform = 0x04, HighQualityAntialiasing = 0x08, NonCosmeticDefaultPen = 0x10, - Qt4CompatiblePainting = 0x20 + Qt4CompatiblePainting = 0x20, + LosslessImageRendering = 0x40, }; Q_FLAG(RenderHint) diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 4fd0d3c8fe..26737e3da1 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -944,7 +944,8 @@ void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, con QPixmap pm = sourceRect != pixmap.rect() ? pixmap.copy(sourceRect) : pixmap; QImage image = pm.toImage(); bool bitmap = true; - const int object = d->addImage(image, &bitmap, pm.cacheKey()); + const bool lossless = painter()->testRenderHint(QPainter::LosslessImageRendering); + const int object = d->addImage(image, &bitmap, lossless, pm.cacheKey()); if (object < 0) return; @@ -972,7 +973,8 @@ void QPdfEngine::drawImage(const QRectF &rectangle, const QImage &image, const Q QRect sourceRect = sr.toRect(); QImage im = sourceRect != image.rect() ? image.copy(sourceRect) : image; bool bitmap = true; - const int object = d->addImage(im, &bitmap, im.cacheKey()); + const bool lossless = painter()->testRenderHint(QPainter::LosslessImageRendering); + const int object = d->addImage(im, &bitmap, lossless, im.cacheKey()); if (object < 0) return; @@ -2578,6 +2580,8 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha) int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, int *gStateObject) { + Q_Q(QPdfEngine); + int paintType = 2; // Uncolored tiling int w = 8; int h = 8; @@ -2607,7 +2611,8 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, return 0; QImage image = brush.textureImage(); bool bitmap = true; - imageObject = addImage(image, &bitmap, image.cacheKey()); + const bool lossless = q->painter()->testRenderHint(QPainter::LosslessImageRendering); + imageObject = addImage(image, &bitmap, lossless, image.cacheKey()); if (imageObject != -1) { QImage::Format f = image.format(); if (f != QImage::Format_MonoLSB && f != QImage::Format_Mono) { @@ -2669,7 +2674,7 @@ static inline bool is_monochrome(const QVector &colorTable) /*! * Adds an image to the pdf and return the pdf-object id. Returns -1 if adding the image failed. */ -int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_no) +int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless, qint64 serial_no) { if (img.isNull()) return -1; @@ -2730,7 +2735,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n bool hasAlpha = false; bool hasMask = false; - if (QImageWriter::supportedImageFormats().contains("jpeg") && !grayscale) { + if (QImageWriter::supportedImageFormats().contains("jpeg") && !grayscale && !lossless) { QBuffer buffer(&imageData); QImageWriter writer(&buffer, "jpeg"); writer.setQuality(94); diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h index 5a909f2ede..4868f064c7 100644 --- a/src/gui/painting/qpdf_p.h +++ b/src/gui/painting/qpdf_p.h @@ -241,7 +241,7 @@ public: void writeHeader(); void writeTail(); - int addImage(const QImage &image, bool *bitmap, qint64 serial_no); + int addImage(const QImage &image, bool *bitmap, bool lossless, qint64 serial_no); int addConstantAlphaObject(int brushAlpha, int penAlpha = 255); int addBrushPattern(const QTransform &matrix, bool *specifyColor, int *gStateObject); -- cgit v1.2.3