mirror of https://github.com/JakubMelka/PDF4QT.git
CMS optimization, some bugfixing
This commit is contained in:
parent
e89a26790e
commit
f759585870
|
@ -26,6 +26,7 @@
|
||||||
#pragma warning(disable:5033)
|
#pragma warning(disable:5033)
|
||||||
#define CMS_NO_REGISTER_KEYWORD
|
#define CMS_NO_REGISTER_KEYWORD
|
||||||
#include <lcms2.h>
|
#include <lcms2.h>
|
||||||
|
#include <lcms2_plugin.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -56,6 +57,14 @@ public:
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
static int installCmsPlugins();
|
||||||
|
|
||||||
|
static cmsBool optimizePipeline(cmsPipeline** Lut,
|
||||||
|
cmsUInt32Number Intent,
|
||||||
|
cmsUInt32Number* InputFormat,
|
||||||
|
cmsUInt32Number* OutputFormat,
|
||||||
|
cmsUInt32Number* dwFlags);
|
||||||
|
|
||||||
enum Profile
|
enum Profile
|
||||||
{
|
{
|
||||||
Output,
|
Output,
|
||||||
|
@ -415,6 +424,9 @@ PDFLittleCMS::PDFLittleCMS(const PDFCMSManager* manager, const PDFCMSSettings& s
|
||||||
m_paperColor(Qt::white),
|
m_paperColor(Qt::white),
|
||||||
m_profiles()
|
m_profiles()
|
||||||
{
|
{
|
||||||
|
static const int installed = installCmsPlugins();
|
||||||
|
Q_UNUSED(installed);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,6 +712,145 @@ void PDFLittleCMS::init()
|
||||||
m_transformationCache.reserve(64);
|
m_transformationCache.reserve(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PDFLittleCMS::installCmsPlugins()
|
||||||
|
{
|
||||||
|
static cmsPluginOptimization optimizationPlugin = { };
|
||||||
|
optimizationPlugin.base.Magic = cmsPluginMagicNumber;
|
||||||
|
optimizationPlugin.base.Type = cmsPluginOptimizationSig;
|
||||||
|
optimizationPlugin.base.Next = nullptr;
|
||||||
|
optimizationPlugin.base.ExpectedVersion = LCMS_VERSION;
|
||||||
|
optimizationPlugin.OptimizePtr = &PDFLittleCMS::optimizePipeline;
|
||||||
|
|
||||||
|
cmsPlugin(&optimizationPlugin);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsBool PDFLittleCMS::optimizePipeline(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
|
||||||
|
{
|
||||||
|
if (*dwFlags & cmsFLAGS_HIGHRESPRECALC)
|
||||||
|
{
|
||||||
|
// Do not optimize
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_UNUSED(Intent);
|
||||||
|
|
||||||
|
// We will find, if we can optimize...
|
||||||
|
bool shouldOptimize = false;
|
||||||
|
for (auto stage = cmsPipelineGetPtrToFirstStage(*Lut); stage; stage = cmsStageNext(stage))
|
||||||
|
{
|
||||||
|
if (cmsStageType(stage) == cmsSigCurveSetElemType)
|
||||||
|
{
|
||||||
|
_cmsStageToneCurvesData* data = reinterpret_cast<_cmsStageToneCurvesData*>(cmsStageData(stage));
|
||||||
|
for (cmsUInt32Number i = 0; i < data->nCurves; ++i)
|
||||||
|
{
|
||||||
|
const cmsToneCurve* curve = data->TheCurves[i];
|
||||||
|
const cmsInt32Number type = cmsGetToneCurveParametricType(curve);
|
||||||
|
|
||||||
|
if (type != 0 && !cmsIsToneCurveMultisegment(curve))
|
||||||
|
{
|
||||||
|
shouldOptimize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldOptimize)
|
||||||
|
{
|
||||||
|
cmsContext contextId = cmsGetPipelineContextID(*Lut);
|
||||||
|
cmsPipeline* pipeline = cmsPipelineAlloc(contextId, T_CHANNELS(*InputFormat), T_CHANNELS(*OutputFormat));
|
||||||
|
if (!pipeline)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto stage = cmsPipelineGetPtrToFirstStage(*Lut); stage; stage = cmsStageNext(stage))
|
||||||
|
{
|
||||||
|
if (cmsStageType(stage) == cmsSigCurveSetElemType)
|
||||||
|
{
|
||||||
|
_cmsStageToneCurvesData* data = reinterpret_cast<_cmsStageToneCurvesData*>(cmsStageData(stage));
|
||||||
|
std::vector<cmsToneCurve*> curves(data->nCurves, nullptr);
|
||||||
|
|
||||||
|
for (cmsUInt32Number i = 0; i < data->nCurves; ++i)
|
||||||
|
{
|
||||||
|
const cmsToneCurve* curve = data->TheCurves[i];
|
||||||
|
const cmsInt32Number type = cmsGetToneCurveParametricType(curve);
|
||||||
|
|
||||||
|
if (type != 0 && !cmsIsToneCurveMultisegment(curve))
|
||||||
|
{
|
||||||
|
std::array<cmsCurveSegment, 3> segments = { };
|
||||||
|
|
||||||
|
const cmsFloat64Number* params = cmsGetToneCurveParams(curve);
|
||||||
|
|
||||||
|
cmsCurveSegment& s1 = segments[0];
|
||||||
|
cmsCurveSegment& s2 = segments[1];
|
||||||
|
cmsCurveSegment& s3 = segments[2];
|
||||||
|
|
||||||
|
const cmsFloat32Number eps = cmsFloat32Number(1e-5);
|
||||||
|
const cmsFloat32Number low = 0.0f - eps;
|
||||||
|
const cmsFloat32Number high = 1.0f + eps;
|
||||||
|
|
||||||
|
s1.Type = type;
|
||||||
|
s1.nGridPoints = 0;
|
||||||
|
s1.SampledPoints = nullptr;
|
||||||
|
std::copy(params, params + (sizeof(s1.Params) / sizeof(*s1.Params)), s1.Params);
|
||||||
|
s1.x0 = std::numeric_limits<cmsFloat32Number>::min();
|
||||||
|
s1.x1 = low;
|
||||||
|
|
||||||
|
const cmsUInt32Number gridPoints = 1024;
|
||||||
|
const cmsFloat32Number factor = 1.0f / cmsFloat32Number(gridPoints - 1);
|
||||||
|
|
||||||
|
s2.Type = 0;
|
||||||
|
s2.nGridPoints = gridPoints;
|
||||||
|
s2.SampledPoints = static_cast<cmsFloat32Number*>(_cmsCalloc(contextId, gridPoints, sizeof(*s2.SampledPoints)));
|
||||||
|
std::copy(params, params + (sizeof(s2.Params) / sizeof(*s2.Params)), s2.Params);
|
||||||
|
s2.x0 = low;
|
||||||
|
s2.x1 = high;
|
||||||
|
|
||||||
|
for (cmsUInt32Number i = 0; i < gridPoints; ++i)
|
||||||
|
{
|
||||||
|
const cmsFloat32Number x = i * factor;
|
||||||
|
s2.SampledPoints[i] = cmsEvalToneCurveFloat(curve, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
s3.Type = type;
|
||||||
|
s3.nGridPoints = 0;
|
||||||
|
s3.SampledPoints = nullptr;
|
||||||
|
std::copy(params, params + (sizeof(s3.Params) / sizeof(*s3.Params)), s3.Params);
|
||||||
|
s3.x0 = high;
|
||||||
|
s3.x1 = std::numeric_limits<cmsFloat32Number>::max();
|
||||||
|
|
||||||
|
curves[i] = cmsBuildSegmentedToneCurve(contextId, cmsUInt32Number(segments.size()), segments.data());
|
||||||
|
|
||||||
|
_cmsFree(contextId, s2.SampledPoints);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curves[i] = cmsDupToneCurve(curve);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsStageAllocToneCurves(contextId, cmsFloat32Number(curves.size()), curves.data());
|
||||||
|
|
||||||
|
for (cmsToneCurve* curve : curves)
|
||||||
|
{
|
||||||
|
cmsFreeToneCurve(curve);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmsPipelineInsertStage(pipeline, cmsAT_END, cmsStageDup(stage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsPipelineFree(*Lut);
|
||||||
|
*Lut = pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
bool PDFLittleCMS::isSoftProofing() const
|
bool PDFLittleCMS::isSoftProofing() const
|
||||||
{
|
{
|
||||||
return (m_settings.isSoftProofing || m_settings.isGamutChecking) && m_profiles[SoftProofing];
|
return (m_settings.isSoftProofing || m_settings.isGamutChecking) && m_profiles[SoftProofing];
|
||||||
|
|
|
@ -49,6 +49,7 @@ PDFRenderToImagesDialog::PDFRenderToImagesDialog(const pdf::PDFDocument* documen
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
qRegisterMetaType<pdf::PDFRenderError>("PDFRenderError");
|
qRegisterMetaType<pdf::PDFRenderError>("PDFRenderError");
|
||||||
|
qRegisterMetaType<pdf::PDFInteger>("PDFInteger");
|
||||||
|
|
||||||
// Load image formats
|
// Load image formats
|
||||||
for (const QByteArray& format : m_imageWriterSettings.getFormats())
|
for (const QByteArray& format : m_imageWriterSettings.getFormats())
|
||||||
|
@ -245,7 +246,17 @@ void PDFRenderToImagesDialog::onProgressiveScanWriteChanged(bool value)
|
||||||
|
|
||||||
void PDFRenderToImagesDialog::onRenderError(pdf::PDFInteger pageIndex, pdf::PDFRenderError error)
|
void PDFRenderToImagesDialog::onRenderError(pdf::PDFInteger pageIndex, pdf::PDFRenderError error)
|
||||||
{
|
{
|
||||||
ui->progressMessagesEdit->setPlainText(QString("%1\n%2").arg(ui->progressMessagesEdit->toPlainText()).arg(tr("Page %1: %2").arg(pageIndex + 1).arg(error.message)));
|
QString text;
|
||||||
|
|
||||||
|
if (pageIndex != pdf::PDFCatalog::INVALID_PAGE_INDEX)
|
||||||
|
{
|
||||||
|
text = tr("%1\nPage %2: %3").arg(ui->progressMessagesEdit->toPlainText(), QString::number(pageIndex + 1), error.message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = QString("%1\n%2").arg(ui->progressMessagesEdit->toPlainText(), error.message);
|
||||||
|
}
|
||||||
|
ui->progressMessagesEdit->setPlainText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFRenderToImagesDialog::onRenderingFinished()
|
void PDFRenderToImagesDialog::onRenderingFinished()
|
||||||
|
|
Loading…
Reference in New Issue