mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Rendering to images - bugfixing
This commit is contained in:
@ -737,7 +737,7 @@ std::vector<PDFInteger> PDFPageImageExportSettings::getPages() const
|
|||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
const QString& numberString = numbers.front();
|
const QString& numberString = numbers.front();
|
||||||
result.push_back(numberString.toLongLong(&ok));
|
result.push_back(numberString.toLongLong(&ok) - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,9 +747,9 @@ std::vector<PDFInteger> PDFPageImageExportSettings::getPages() const
|
|||||||
bool ok2 = false;
|
bool ok2 = false;
|
||||||
const QString& lowString = numbers.front();
|
const QString& lowString = numbers.front();
|
||||||
const QString& highString = numbers.back();
|
const QString& highString = numbers.back();
|
||||||
const PDFInteger low = lowString.toLongLong(&ok1);
|
const PDFInteger low = lowString.toLongLong(&ok1) - 1;
|
||||||
const PDFInteger high = highString.toLongLong(&ok2);
|
const PDFInteger high = highString.toLongLong(&ok2) - 1;
|
||||||
ok = ok1 && ok2 && low <= high;
|
ok = ok1 && ok2 && low <= high && low >= 0;
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
const PDFInteger count = high - low + 1;
|
const PDFInteger count = high - low + 1;
|
||||||
@ -792,6 +792,22 @@ std::vector<PDFInteger> PDFPageImageExportSettings::getPages() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PDFPageImageExportSettings::getOutputFileName(PDFInteger pageIndex, const QByteArray& outputFormat)
|
||||||
|
{
|
||||||
|
QString fileName = m_fileTemplate;
|
||||||
|
fileName.replace('%', QString::number(pageIndex + 1));
|
||||||
|
|
||||||
|
QFileInfo fileInfo(fileName);
|
||||||
|
if (fileInfo.suffix() != outputFormat)
|
||||||
|
{
|
||||||
|
fileName = QString("%1.%2").arg(fileName, QString::fromLatin1(outputFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add directory
|
||||||
|
QString fileNameWithDirectory = QString("%1/%2").arg(m_directory, fileName);
|
||||||
|
return QDir::toNativeSeparators(fileNameWithDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
PDFRasterizerPool::PDFRasterizerPool(const PDFDocument* document,
|
PDFRasterizerPool::PDFRasterizerPool(const PDFDocument* document,
|
||||||
const PDFFontCache* fontCache,
|
const PDFFontCache* fontCache,
|
||||||
const PDFCMS* cms,
|
const PDFCMS* cms,
|
||||||
|
@ -333,6 +333,9 @@ public:
|
|||||||
/// Returns list of selected pages
|
/// Returns list of selected pages
|
||||||
std::vector<PDFInteger> getPages() const;
|
std::vector<PDFInteger> getPages() const;
|
||||||
|
|
||||||
|
/// Returns output file name for given page
|
||||||
|
QString getOutputFileName(PDFInteger pageIndex, const QByteArray& outputFormat);
|
||||||
|
|
||||||
static constexpr int getMinDPIResolution() { return 72; }
|
static constexpr int getMinDPIResolution() { return 72; }
|
||||||
static constexpr int getMaxDPIResolution() { return 6000; }
|
static constexpr int getMaxDPIResolution() { return 6000; }
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "pdfrendertoimagesdialog.h"
|
#include "pdfrendertoimagesdialog.h"
|
||||||
#include "ui_pdfrendertoimagesdialog.h"
|
#include "ui_pdfrendertoimagesdialog.h"
|
||||||
|
|
||||||
#include "pdfcms.h"
|
|
||||||
#include "pdfutils.h"
|
#include "pdfutils.h"
|
||||||
#include "pdfwidgetutils.h"
|
#include "pdfwidgetutils.h"
|
||||||
#include "pdfoptionalcontent.h"
|
#include "pdfoptionalcontent.h"
|
||||||
@ -27,6 +26,8 @@
|
|||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <QImageWriter>
|
||||||
|
|
||||||
namespace pdfviewer
|
namespace pdfviewer
|
||||||
{
|
{
|
||||||
@ -41,7 +42,9 @@ PDFRenderToImagesDialog::PDFRenderToImagesDialog(const pdf::PDFDocument* documen
|
|||||||
m_proxy(proxy),
|
m_proxy(proxy),
|
||||||
m_progress(progress),
|
m_progress(progress),
|
||||||
m_imageExportSettings(document),
|
m_imageExportSettings(document),
|
||||||
m_isLoadingData(false)
|
m_isLoadingData(false),
|
||||||
|
m_optionalContentActivity(nullptr),
|
||||||
|
m_rasterizerPool(nullptr)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
@ -67,6 +70,7 @@ PDFRenderToImagesDialog::PDFRenderToImagesDialog(const pdf::PDFDocument* documen
|
|||||||
connect(ui->gammaEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &PDFRenderToImagesDialog::onGammaChanged);
|
connect(ui->gammaEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &PDFRenderToImagesDialog::onGammaChanged);
|
||||||
connect(ui->optimizedWriteCheckBox, &QCheckBox::clicked, this, &PDFRenderToImagesDialog::onOptimizedWriteChanged);
|
connect(ui->optimizedWriteCheckBox, &QCheckBox::clicked, this, &PDFRenderToImagesDialog::onOptimizedWriteChanged);
|
||||||
connect(ui->progressiveScanWriteCheckBox, &QCheckBox::clicked, this, &PDFRenderToImagesDialog::onProgressiveScanWriteChanged);
|
connect(ui->progressiveScanWriteCheckBox, &QCheckBox::clicked, this, &PDFRenderToImagesDialog::onProgressiveScanWriteChanged);
|
||||||
|
connect(&m_watcher, &QFutureWatcher<void>::finished, this, &PDFRenderToImagesDialog::onRenderingFinished);
|
||||||
|
|
||||||
ui->resolutionDPIEdit->setRange(pdf::PDFPageImageExportSettings::getMinDPIResolution(), pdf::PDFPageImageExportSettings::getMaxDPIResolution());
|
ui->resolutionDPIEdit->setRange(pdf::PDFPageImageExportSettings::getMinDPIResolution(), pdf::PDFPageImageExportSettings::getMaxDPIResolution());
|
||||||
ui->resolutionPixelsEdit->setRange(pdf::PDFPageImageExportSettings::getMinPixelResolution(), pdf::PDFPageImageExportSettings::getMaxPixelResolution());
|
ui->resolutionPixelsEdit->setRange(pdf::PDFPageImageExportSettings::getMinPixelResolution(), pdf::PDFPageImageExportSettings::getMaxPixelResolution());
|
||||||
@ -80,6 +84,9 @@ PDFRenderToImagesDialog::PDFRenderToImagesDialog(const pdf::PDFDocument* documen
|
|||||||
PDFRenderToImagesDialog::~PDFRenderToImagesDialog()
|
PDFRenderToImagesDialog::~PDFRenderToImagesDialog()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
|
|
||||||
|
Q_ASSERT(!m_optionalContentActivity);
|
||||||
|
Q_ASSERT(!m_rasterizerPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFRenderToImagesDialog::loadImageWriterSettings()
|
void PDFRenderToImagesDialog::loadImageWriterSettings()
|
||||||
@ -239,6 +246,19 @@ void PDFRenderToImagesDialog::onRenderError(pdf::PDFRenderError error)
|
|||||||
ui->progressMessagesEdit->setPlainText(QString("%1\n%2").arg(ui->progressMessagesEdit->toPlainText()).arg(error.message));
|
ui->progressMessagesEdit->setPlainText(QString("%1\n%2").arg(ui->progressMessagesEdit->toPlainText()).arg(error.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFRenderToImagesDialog::onRenderingFinished()
|
||||||
|
{
|
||||||
|
setEnabled(true);
|
||||||
|
|
||||||
|
delete m_rasterizerPool;
|
||||||
|
m_rasterizerPool = nullptr;
|
||||||
|
|
||||||
|
delete m_optionalContentActivity;
|
||||||
|
m_optionalContentActivity = nullptr;
|
||||||
|
|
||||||
|
m_cms.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void PDFRenderToImagesDialog::on_selectDirectoryButton_clicked()
|
void PDFRenderToImagesDialog::on_selectDirectoryButton_clicked()
|
||||||
{
|
{
|
||||||
QString directory = QFileDialog::getExistingDirectory(this, tr("Select output directory"), ui->directoryEdit->text());
|
QString directory = QFileDialog::getExistingDirectory(this, tr("Select output directory"), ui->directoryEdit->text());
|
||||||
@ -255,54 +275,69 @@ void PDFRenderToImagesDialog::on_buttonBox_clicked(QAbstractButton* button)
|
|||||||
QString message;
|
QString message;
|
||||||
if (m_imageExportSettings.validate(&message))
|
if (m_imageExportSettings.validate(&message))
|
||||||
{
|
{
|
||||||
// We are ready to render the document
|
|
||||||
std::vector<pdf::PDFInteger> pageIndices = m_imageExportSettings.getPages();
|
|
||||||
|
|
||||||
pdf::PDFOptionalContentActivity optionalContentActivity(m_document, pdf::OCUsage::Export, nullptr);
|
|
||||||
pdf::PDFCMSPointer cms = m_proxy->getCMSManager()->getCurrentCMS();
|
|
||||||
pdf::PDFRasterizerPool rasterizerPool(m_document, m_proxy->getFontCache(), cms.data(),
|
|
||||||
&optionalContentActivity, m_proxy->getFeatures(), m_proxy->getMeshQualitySettings(),
|
|
||||||
pdf::PDFRasterizerPool::getDefaultRasterizerCount(), m_proxy->isUsingOpenGL(), m_proxy->getSurfaceFormat(), this);
|
|
||||||
connect(&rasterizerPool, &pdf::PDFRasterizerPool::renderError, this, &PDFRenderToImagesDialog::onRenderError);
|
|
||||||
|
|
||||||
auto imageSizeGetter = [this](const pdf::PDFPage* page) -> QSize
|
|
||||||
{
|
|
||||||
Q_ASSERT(page);
|
|
||||||
|
|
||||||
switch (m_imageExportSettings.getResolutionMode())
|
|
||||||
{
|
|
||||||
case pdf::PDFPageImageExportSettings::ResolutionMode::DPI:
|
|
||||||
{
|
|
||||||
QSizeF size = page->getRotatedMediaBox().size() * m_imageExportSettings.getDpiResolution();
|
|
||||||
return size.toSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
case pdf::PDFPageImageExportSettings::ResolutionMode::Pixels:
|
|
||||||
{
|
|
||||||
int pixelResolution = m_imageExportSettings.getPixelResolution();
|
|
||||||
QSizeF size = page->getRotatedMediaBox().size().scaled(pixelResolution, pixelResolution, Qt::KeepAspectRatio);
|
|
||||||
return size.toSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Q_ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QSize();
|
|
||||||
};
|
|
||||||
|
|
||||||
auto processImage = [](const pdf::PDFInteger pageIndex, QImage&& image)
|
|
||||||
{
|
|
||||||
Q_UNUSED(pageIndex);
|
|
||||||
Q_UNUSED(image);
|
|
||||||
};
|
|
||||||
|
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
rasterizerPool.render(pageIndices, imageSizeGetter, processImage, m_progress);
|
|
||||||
setEnabled(true);
|
// We are ready to render the document
|
||||||
|
m_pageIndices = m_imageExportSettings.getPages();
|
||||||
|
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(m_document, pdf::OCUsage::Export, this);
|
||||||
|
m_cms = m_proxy->getCMSManager()->getCurrentCMS();
|
||||||
|
m_rasterizerPool = new pdf::PDFRasterizerPool(m_document, m_proxy->getFontCache(), m_cms.data(),
|
||||||
|
m_optionalContentActivity, m_proxy->getFeatures(), m_proxy->getMeshQualitySettings(),
|
||||||
|
pdf::PDFRasterizerPool::getDefaultRasterizerCount(), m_proxy->isUsingOpenGL(), m_proxy->getSurfaceFormat(), this);
|
||||||
|
connect(m_rasterizerPool, &pdf::PDFRasterizerPool::renderError, this, &PDFRenderToImagesDialog::onRenderError);
|
||||||
|
|
||||||
|
auto process = [this]()
|
||||||
|
{
|
||||||
|
auto imageSizeGetter = [this](const pdf::PDFPage* page) -> QSize
|
||||||
|
{
|
||||||
|
Q_ASSERT(page);
|
||||||
|
|
||||||
|
switch (m_imageExportSettings.getResolutionMode())
|
||||||
|
{
|
||||||
|
case pdf::PDFPageImageExportSettings::ResolutionMode::DPI:
|
||||||
|
{
|
||||||
|
QSizeF size = page->getRotatedMediaBox().size() * pdf::PDF_POINT_TO_INCH * m_imageExportSettings.getDpiResolution();
|
||||||
|
return size.toSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
case pdf::PDFPageImageExportSettings::ResolutionMode::Pixels:
|
||||||
|
{
|
||||||
|
int pixelResolution = m_imageExportSettings.getPixelResolution();
|
||||||
|
QSizeF size = page->getRotatedMediaBox().size().scaled(pixelResolution, pixelResolution, Qt::KeepAspectRatio);
|
||||||
|
return size.toSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSize();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto processImage = [this](const pdf::PDFInteger pageIndex, QImage&& image)
|
||||||
|
{
|
||||||
|
QString fileName = m_imageExportSettings.getOutputFileName(pageIndex, m_imageWriterSettings.getCurrentFormat());
|
||||||
|
|
||||||
|
QImageWriter imageWriter(fileName, m_imageWriterSettings.getCurrentFormat());
|
||||||
|
imageWriter.setSubType(m_imageWriterSettings.getCurrentSubtype());
|
||||||
|
imageWriter.setCompression(m_imageWriterSettings.getCompression());
|
||||||
|
imageWriter.setQuality(m_imageWriterSettings.getQuality());
|
||||||
|
imageWriter.setGamma(m_imageWriterSettings.getGamma());
|
||||||
|
imageWriter.setOptimizedWrite(m_imageWriterSettings.hasOptimizedWrite());
|
||||||
|
imageWriter.setProgressiveScanWrite(m_imageWriterSettings.hasProgressiveScanWrite());
|
||||||
|
|
||||||
|
if (!imageWriter.write(image))
|
||||||
|
{
|
||||||
|
emit m_rasterizerPool->renderError(pdf::PDFRenderError(pdf::RenderErrorType::Error, tr("Can't write page image to file '%1', because: %2.").arg(fileName).arg(imageWriter.errorString())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_rasterizerPool->render(m_pageIndices, imageSizeGetter, processImage, m_progress);
|
||||||
|
};
|
||||||
|
m_watcher.setFuture(QtConcurrent::run(process));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
#ifndef PDFRENDERTOIMAGESDIALOG_H
|
#ifndef PDFRENDERTOIMAGESDIALOG_H
|
||||||
#define PDFRENDERTOIMAGESDIALOG_H
|
#define PDFRENDERTOIMAGESDIALOG_H
|
||||||
|
|
||||||
|
#include "pdfcms.h"
|
||||||
#include "pdfrenderer.h"
|
#include "pdfrenderer.h"
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
class QAbstractButton;
|
class QAbstractButton;
|
||||||
|
|
||||||
@ -75,6 +77,7 @@ private:
|
|||||||
void onOptimizedWriteChanged(bool value);
|
void onOptimizedWriteChanged(bool value);
|
||||||
void onProgressiveScanWriteChanged(bool value);
|
void onProgressiveScanWriteChanged(bool value);
|
||||||
void onRenderError(pdf::PDFRenderError error);
|
void onRenderError(pdf::PDFRenderError error);
|
||||||
|
void onRenderingFinished();
|
||||||
|
|
||||||
Ui::PDFRenderToImagesDialog* ui;
|
Ui::PDFRenderToImagesDialog* ui;
|
||||||
const pdf::PDFDocument* m_document;
|
const pdf::PDFDocument* m_document;
|
||||||
@ -83,6 +86,12 @@ private:
|
|||||||
pdf::PDFImageWriterSettings m_imageWriterSettings;
|
pdf::PDFImageWriterSettings m_imageWriterSettings;
|
||||||
pdf::PDFPageImageExportSettings m_imageExportSettings;
|
pdf::PDFPageImageExportSettings m_imageExportSettings;
|
||||||
bool m_isLoadingData;
|
bool m_isLoadingData;
|
||||||
|
QFutureWatcher<void> m_watcher;
|
||||||
|
|
||||||
|
std::vector<pdf::PDFInteger> m_pageIndices;
|
||||||
|
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
|
||||||
|
pdf::PDFCMSPointer m_cms;
|
||||||
|
pdf::PDFRasterizerPool* m_rasterizerPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdfviewer
|
} // namespace pdfviewer
|
||||||
|
Reference in New Issue
Block a user