diff --git a/PdfForQtLib/PdfForQtLib.pro b/PdfForQtLib/PdfForQtLib.pro
index 99d3432..b0a8889 100644
--- a/PdfForQtLib/PdfForQtLib.pro
+++ b/PdfForQtLib/PdfForQtLib.pro
@@ -39,6 +39,7 @@ SOURCES += \
sources/pdfaction.cpp \
sources/pdfblendfunction.cpp \
sources/pdfccittfaxdecoder.cpp \
+ sources/pdfcms.cpp \
sources/pdfcompiler.cpp \
sources/pdffile.cpp \
sources/pdfitemmodels.cpp \
@@ -77,6 +78,7 @@ HEADERS += \
sources/pdfaction.h \
sources/pdfblendfunction.h \
sources/pdfccittfaxdecoder.h \
+ sources/pdfcms.h \
sources/pdfcompiler.h \
sources/pdffile.h \
sources/pdfitemmodels.h \
@@ -174,6 +176,16 @@ zlib.files = $$PDFFORQT_DEPENDENCIES_PATH/zlib/bin/zlib.dll
zlib.path = $$DESTDIR/install
INSTALLS += zlib
+# Link lcms2
+LIBS += -L$$PDFFORQT_DEPENDENCIES_PATH/lcms2/bin/ -llcms2
+INCLUDEPATH += $$PDFFORQT_DEPENDENCIES_PATH/lcms2/include
+DEPENDPATH += $$PDFFORQT_DEPENDENCIES_PATH/lcms2/include
+
+# Add lcms2 to installations
+lcms2.files = $$PDFFORQT_DEPENDENCIES_PATH/lcms2/bin/lcms2.dll
+lcms2.path = $$DESTDIR/install
+INSTALLS += lcms2
+
# ensure debug info even for RELEASE build
CONFIG += force_debug_info
diff --git a/PdfForQtLib/sources/pdfcms.cpp b/PdfForQtLib/sources/pdfcms.cpp
new file mode 100644
index 0000000..7f64ea6
--- /dev/null
+++ b/PdfForQtLib/sources/pdfcms.cpp
@@ -0,0 +1,219 @@
+// Copyright (C) 2019 Jakub Melka
+//
+// This file is part of PdfForQt.
+//
+// PdfForQt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// PdfForQt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDFForQt. If not, see .
+
+#include "pdfcms.h"
+
+#pragma warning(push)
+#pragma warning(disable:5033)
+#include
+#pragma warning(pop)
+
+namespace pdf
+{
+
+bool PDFCMSGeneric::isCompatible(const PDFCMSSettings& settings) const
+{
+ return settings.system == PDFCMSSettings::System::Generic;
+}
+
+QColor PDFCMSGeneric::getColorFromDeviceGray(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
+{
+ Q_UNUSED(color);
+ Q_UNUSED(intent);
+ Q_UNUSED(reporter);
+ return QColor();
+}
+
+QColor PDFCMSGeneric::getColorFromDeviceRGB(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
+{
+ Q_UNUSED(color);
+ Q_UNUSED(intent);
+ Q_UNUSED(reporter);
+ return QColor();
+}
+
+QColor PDFCMSGeneric::getColorFromDeviceCMYK(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
+{
+ Q_UNUSED(color);
+ Q_UNUSED(intent);
+ Q_UNUSED(reporter);
+ return QColor();
+}
+
+QColor PDFCMSGeneric::getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const
+{
+ Q_UNUSED(color);
+ Q_UNUSED(intent);
+ Q_UNUSED(reporter);
+ Q_UNUSED(whitePoint);
+ return QColor();
+}
+
+PDFCMSManager::PDFCMSManager(QObject* parent) :
+ BaseClass(parent)
+{
+
+}
+
+const PDFColorSpaceIdentifiers& PDFCMSManager::getOutputProfiles() const
+{
+ QMutexLocker lock(&m_mutex);
+ return m_outputProfiles.get(this, &PDFCMSManager::getOutputProfilesImpl);
+}
+
+const PDFColorSpaceIdentifiers& PDFCMSManager::getGrayProfiles() const
+{
+ QMutexLocker lock(&m_mutex);
+ return m_grayProfiles.get(this, &PDFCMSManager::getGrayProfilesImpl);
+}
+
+const PDFColorSpaceIdentifiers& PDFCMSManager::getRGBProfiles() const
+{
+ QMutexLocker lock(&m_mutex);
+ return m_RGBProfiles.get(this, &PDFCMSManager::getRGBProfilesImpl);
+}
+
+const PDFColorSpaceIdentifiers& PDFCMSManager::getCMYKProfiles() const
+{
+ QMutexLocker lock(&m_mutex);
+ return m_CMYKProfiles.get(this, &PDFCMSManager::getCMYKProfilesImpl);
+}
+
+PDFCMSSettings PDFCMSManager::getDefaultSettings() const
+{
+ PDFCMSSettings settings;
+
+ auto getFirstProfileId = [](const PDFColorSpaceIdentifiers& identifiers)
+ {
+ if (!identifiers.empty())
+ {
+ return identifiers.front().id;
+ }
+ return QString();
+ };
+
+ settings.system = PDFCMSSettings::System::LittleCMS2;
+ settings.outputCS = getFirstProfileId(getOutputProfiles());
+ settings.deviceGray = getFirstProfileId(getGrayProfiles());
+ settings.deviceRGB = getFirstProfileId(getRGBProfiles());
+ settings.deviceCMYK = getFirstProfileId(getCMYKProfiles());
+
+ return settings;
+}
+
+QString PDFCMSManager::getSystemName(PDFCMSSettings::System system)
+{
+ switch (system)
+ {
+ case PDFCMSSettings::System::Generic:
+ return tr("Generic");
+
+ case PDFCMSSettings::System::LittleCMS2:
+ {
+ const int major = LCMS_VERSION / 1000;
+ const int minor = (LCMS_VERSION % 1000) / 10;
+ return tr("Little CMS %1.%2").arg(major).arg(minor);
+ }
+
+ default:
+ {
+ Q_ASSERT(false);
+ break;
+ }
+ }
+
+ return QString();
+}
+
+PDFColorSpaceIdentifiers PDFCMSManager::getOutputProfilesImpl() const
+{
+ // Currently, we only support sRGB output color profile.
+ return { PDFColorSpaceIdentifier::createSRGB() };
+}
+
+PDFColorSpaceIdentifiers PDFCMSManager::getGrayProfilesImpl() const
+{
+ // Jakub Melka: We create gray profiles for temperature 5000K, 6500K and 9300K.
+ // We also use linear gamma and gamma value 2.2.
+ return {
+ PDFColorSpaceIdentifier::createGray(tr("Gray D65, γ = 2.2"), "@GENERIC_Gray_D65_g22", 6500.0, 2.2),
+ PDFColorSpaceIdentifier::createGray(tr("Gray D50, γ = 2.2"), "@GENERIC_Gray_D50_g22", 5000.0, 2.2),
+ PDFColorSpaceIdentifier::createGray(tr("Gray D93, γ = 2.2"), "@GENERIC_Gray_D93_g22", 9300.0, 2.2),
+ PDFColorSpaceIdentifier::createGray(tr("Gray D65, γ = 1.0 (linear)"), "@GENERIC_Gray_D65_g10", 6500.0, 1.0),
+ PDFColorSpaceIdentifier::createGray(tr("Gray D50, γ = 1.0 (linear)"), "@GENERIC_Gray_D50_g10", 5000.0, 1.0),
+ PDFColorSpaceIdentifier::createGray(tr("Gray D93, γ = 1.0 (linear)"), "@GENERIC_Gray_D93_g10", 9300.0, 1.0)
+ };
+}
+
+PDFColorSpaceIdentifiers PDFCMSManager::getRGBProfilesImpl() const
+{
+ // Jakub Melka: We create RGB profiles for common standars and also for
+ // default standard sRGB. See https://en.wikipedia.org/wiki/Color_spaces_with_RGB_primaries.
+ return {
+ PDFColorSpaceIdentifier::createSRGB(),
+ PDFColorSpaceIdentifier::createRGB(tr("HDTV (ITU-R BT.709)"), "@GENERIC_RGB_HDTV", 6500, QPointF(0.64, 0.33), QPointF(0.30, 0.60), QPointF(0.15, 0.06), 20.0 / 9.0),
+ PDFColorSpaceIdentifier::createRGB(tr("Adobe RGB 1998"), "@GENERIC_RGB_Adobe1998", 6500, QPointF(0.64, 0.33), QPointF(0.30, 0.60), QPointF(0.15, 0.06), 563.0 / 256.0),
+ PDFColorSpaceIdentifier::createRGB(tr("PAL / SECAM"), "@GENERIC_RGB_PalSecam", 6500, QPointF(0.64, 0.33), QPointF(0.29, 0.60), QPointF(0.15, 0.06), 14.0 / 5.0),
+ PDFColorSpaceIdentifier::createRGB(tr("NTSC"), "@GENERIC_RGB_NTSC", 6500, QPointF(0.64, 0.34), QPointF(0.31, 0.595), QPointF(0.155, 0.07), 20.0 / 9.0),
+ PDFColorSpaceIdentifier::createRGB(tr("Adobe Wide Gamut RGB"), "@GENERIC_RGB_AdobeWideGamut", 5000, QPointF(0.735, 0.265), QPointF(0.115, 0.826), QPointF(0.157, 0.018), 563.0 / 256.0),
+ PDFColorSpaceIdentifier::createRGB(tr("ProPhoto RGB"), "@GENERIC_RGB_ProPhoto", 5000, QPointF(0.7347, 0.2653), QPointF(0.1596, 0.8404), QPointF(0.0366, 0.0001), 9.0 / 5.0)
+ };
+}
+
+PDFColorSpaceIdentifiers PDFCMSManager::getCMYKProfilesImpl() const
+{
+ return {
+
+ };
+}
+
+PDFColorSpaceIdentifier PDFColorSpaceIdentifier::createGray(QString name, QString id, PDFReal temperature, PDFReal gamma)
+{
+ PDFColorSpaceIdentifier result;
+ result.type = Type::Gray;
+ result.name = qMove(name);
+ result.id = qMove(id);
+ result.temperature = temperature;
+ result.gamma = gamma;
+ return result;
+}
+
+PDFColorSpaceIdentifier PDFColorSpaceIdentifier::createSRGB()
+{
+ PDFColorSpaceIdentifier result;
+ result.type = Type::sRGB;
+ result.name = PDFCMSManager::tr("sRGB");
+ result.id = "@GENERIC_sRGB";
+ return result;
+}
+
+PDFColorSpaceIdentifier PDFColorSpaceIdentifier::createRGB(QString name, QString id, PDFReal temperature, QPointF primaryR, QPointF primaryG, QPointF primaryB, PDFReal gamma)
+{
+ PDFColorSpaceIdentifier result;
+ result.type = Type::RGB;
+ result.name = qMove(name);
+ result.id = qMove(id);
+ result.temperature = temperature;
+ result.primaryR = primaryR;
+ result.primaryG = primaryG;
+ result.primaryB = primaryB;
+ result.gamma = gamma;
+ return result;
+}
+
+} // namespace pdf
+
diff --git a/PdfForQtLib/sources/pdfcms.h b/PdfForQtLib/sources/pdfcms.h
new file mode 100644
index 0000000..311c6d4
--- /dev/null
+++ b/PdfForQtLib/sources/pdfcms.h
@@ -0,0 +1,225 @@
+// Copyright (C) 2019 Jakub Melka
+//
+// This file is part of PdfForQt.
+//
+// PdfForQt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// PdfForQt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDFForQt. If not, see .
+
+#ifndef PDFCMS_H
+#define PDFCMS_H
+
+#include "pdfglobal.h"
+#include "pdfcolorspaces.h"
+#include "pdfexception.h"
+#include "pdfutils.h"
+
+#include
+
+#include
+
+namespace pdf
+{
+
+/// This simple structure stores settings for color management system, and what
+/// color management system should be used. At default, two color management
+/// system are available - generic (which uses default imprecise color management),
+/// and CMS using engine LittleCMS2, which was written by Marti Maria, and is
+/// linked as separate library.
+struct PDFCMSSettings
+{
+ /// Type of color management system
+ enum class System
+ {
+ Generic,
+ LittleCMS2
+ };
+
+ /// Controls accuracy of the color transformations. High accuracy
+ /// could mean high memory consumption, but better color accuracy,
+ /// low accuracy means low memory consumption and low color accuracy.
+ enum class Accuracy
+ {
+ Low,
+ Medium,
+ High
+ };
+
+ bool operator==(const PDFCMSSettings&) const = default;
+
+ System system = System::Generic;
+ Accuracy accuracy = Accuracy::Medium;
+ RenderingIntent intent = RenderingIntent::Auto;
+ bool isBlackPointCompensationActive = true;
+ bool isWhitePaperColorTransformed = false;
+ QString outputCS; ///< Output (rendering) color space
+ QString deviceGray; ///< Identifiers for color space (device gray)
+ QString deviceRGB; ///< Identifiers for color space (device RGB)
+ QString deviceCMYK; ///< Identifiers for color space (device CMYK)
+};
+
+/// Color management system base class. It contains functions to transform
+/// colors from various color system to device color system. If color management
+/// system can't handle color transform, it should return invalid color.
+class PDFCMS
+{
+public:
+ explicit inline PDFCMS() = default;
+ virtual ~PDFCMS() = default;
+
+ /// This function should decide, if color management system is compatible with these
+ /// settings (so, it transforms colors according to this setting). If this
+ /// function returns false, then this color management system should be replaced
+ /// by newly created one, according these settings.
+ virtual bool isCompatible(const PDFCMSSettings& settings) const = 0;
+
+ /// Converts color in Device Gray color space to the target device
+ /// color space. If error occurs, then invalid color is returned.
+ /// Caller then should handle this - try to convert color as accurate
+ /// as possible.
+ /// \param color Single color channel value
+ /// \param intent Rendering intent
+ /// \param reporter Render error reporter (used, when color transform fails)
+ virtual QColor getColorFromDeviceGray(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const = 0;
+
+ /// Converts color in Device RGB color space to the target device
+ /// color space. If error occurs, then invalid color is returned.
+ /// Caller then should handle this - try to convert color as accurate
+ /// as possible.
+ /// \param color Three color channel value (R,G,B channel)
+ /// \param intent Rendering intent
+ /// \param reporter Render error reporter (used, when color transform fails)
+ virtual QColor getColorFromDeviceRGB(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const = 0;
+
+ /// Converts color in Device CMYK color space to the target device
+ /// color space. If error occurs, then invalid color is returned.
+ /// Caller then should handle this - try to convert color as accurate
+ /// as possible.
+ /// \param color Four color channel value (C,M,Y,K channel)
+ /// \param intent Rendering intent
+ /// \param reporter Render error reporter (used, when color transform fails)
+ virtual QColor getColorFromDeviceCMYK(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const = 0;
+
+ /// Converts color in XYZ color space to the target device
+ /// color space. If error occurs, then invalid color is returned.
+ /// Caller then should handle this - try to convert color as accurate
+ /// as possible.
+ /// \param whitePoint White point of source XYZ color space
+ /// \param Three color channel value (X,Y,Z channel)
+ /// \param intent Rendering intent
+ /// \param reporter Render error reporter (used, when color transform fails)
+ virtual QColor getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const = 0;
+};
+
+class PDFCMSGeneric : public PDFCMS
+{
+public:
+ explicit inline PDFCMSGeneric() = default;
+
+ virtual bool isCompatible(const PDFCMSSettings& settings) const override;
+ virtual QColor getColorFromDeviceGray(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
+ virtual QColor getColorFromDeviceRGB(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
+ virtual QColor getColorFromDeviceCMYK(const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
+ virtual QColor getColorFromXYZ(const PDFColor3& whitePoint, const PDFColor& color, RenderingIntent intent, PDFRenderErrorReporter* reporter) const override;
+};
+
+struct PDFColorSpaceIdentifier
+{
+ enum class Type
+ {
+ Gray,
+ sRGB,
+ RGB,
+ CMYK
+ };
+
+ Type type = Type::sRGB;
+ QString name;
+ QString id;
+ PDFReal temperature = 6500.0;
+ QPointF primaryR;
+ QPointF primaryG;
+ QPointF primaryB;
+ PDFReal gamma = 1.0;
+
+ /// Creates gray color space identifier
+ /// \param name Name of color profile
+ /// \param id Identifier of color profile
+ /// \param temperature White point temperature
+ /// \param gamma Gamma correction
+ static PDFColorSpaceIdentifier createGray(QString name, QString id, PDFReal temperature, PDFReal gamma);
+
+ /// Creates sRGB color space identifier
+ static PDFColorSpaceIdentifier createSRGB();
+
+ /// Creates RGB color space identifier
+ /// \param name Name of color profile
+ /// \param id Identifier of color profile
+ /// \param temperature White point temperature
+ /// \param primaryR Primary red
+ /// \param primaryG Primary green
+ /// \param primaryB Primary blue
+ /// \param gamma Gamma correction
+ static PDFColorSpaceIdentifier createRGB(QString name, QString id, PDFReal temperature, QPointF primaryR, QPointF primaryG, QPointF primaryB, PDFReal gamma);
+};
+
+using PDFColorSpaceIdentifiers = std::vector;
+
+/// Manager, that manages current color management system and also list
+/// of usable input and output color profiles. It has color profiles
+/// for outout device, and color profiles for input (gray/RGB/CMYK).
+/// It also handles settings, and it's changes. Constant functions
+/// is save to call from multiple threads, this also holds for some
+/// non-constant functions - manager is protected by mutexes.
+class PDFFORQTLIBSHARED_EXPORT PDFCMSManager : public QObject
+{
+ Q_OBJECT
+
+private:
+ using BaseClass = QObject;
+
+public:
+ explicit PDFCMSManager(QObject* parent);
+
+ const PDFColorSpaceIdentifiers& getOutputProfiles() const;
+ const PDFColorSpaceIdentifiers& getGrayProfiles() const;
+ const PDFColorSpaceIdentifiers& getRGBProfiles() const;
+ const PDFColorSpaceIdentifiers& getCMYKProfiles() const;
+
+ /// Returns default color management settings
+ PDFCMSSettings getDefaultSettings() const;
+
+ /// Get translated name for color management system
+ /// \param system System
+ static QString getSystemName(PDFCMSSettings::System system);
+
+signals:
+ void colorManagementSystemChanged();
+
+private:
+ PDFColorSpaceIdentifiers getOutputProfilesImpl() const;
+ PDFColorSpaceIdentifiers getGrayProfilesImpl() const;
+ PDFColorSpaceIdentifiers getRGBProfilesImpl() const;
+ PDFColorSpaceIdentifiers getCMYKProfilesImpl() const;
+
+ PDFCMSSettings m_settings;
+
+ mutable QMutex m_mutex;
+ mutable PDFCachedItem m_outputProfiles;
+ mutable PDFCachedItem m_grayProfiles;
+ mutable PDFCachedItem m_RGBProfiles;
+ mutable PDFCachedItem m_CMYKProfiles;
+};
+
+} // namespace pdf
+
+#endif // PDFCMS_H
diff --git a/PdfForQtLib/sources/pdfglobal.h b/PdfForQtLib/sources/pdfglobal.h
index cd72079..1f3d7b7 100644
--- a/PdfForQtLib/sources/pdfglobal.h
+++ b/PdfForQtLib/sources/pdfglobal.h
@@ -150,6 +150,7 @@ enum class RendererEngine
enum class RenderingIntent
{
+ Auto, ///< Rendering intent is automatically selected
Perceptual,
AbsoluteColorimetric,
RelativeColorimetric,
diff --git a/PdfForQtViewer/pdfforqtviewer.qrc b/PdfForQtViewer/pdfforqtviewer.qrc
index 002f588..a0bddf9 100644
--- a/PdfForQtViewer/pdfforqtviewer.qrc
+++ b/PdfForQtViewer/pdfforqtviewer.qrc
@@ -26,5 +26,6 @@
resources/shortcuts.svg
resources/info.svg
resources/send-mail.svg
+ resources/cms.svg
diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp
index b7f552d..d4f2f8f 100644
--- a/PdfForQtViewer/pdfviewermainwindow.cpp
+++ b/PdfForQtViewer/pdfviewermainwindow.cpp
@@ -59,9 +59,10 @@
namespace pdfviewer
{
-PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
+PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::PDFViewerMainWindow),
+ m_CMSManager(new pdf::PDFCMSManager(this)),
m_settings(new PDFViewerSettings(this)),
m_pdfWidget(nullptr),
m_sidebarDockWidget(nullptr),
@@ -544,8 +545,7 @@ void PDFViewerMainWindow::readSettings()
restoreState(state);
}
- m_settings->readSettings(settings);
-
+ m_settings->readSettings(settings, m_CMSManager->getDefaultSettings());
}
void PDFViewerMainWindow::readActionSettings()
@@ -976,10 +976,11 @@ void PDFViewerMainWindow::on_actionRendering_Errors_triggered()
void PDFViewerMainWindow::on_actionOptions_triggered()
{
- PDFViewerSettingsDialog dialog(m_settings->getSettings(), getActions(), this);
+ PDFViewerSettingsDialog dialog(m_settings->getSettings(), m_settings->getColorManagementSystemSettings(), getActions(), m_CMSManager, this);
if (dialog.exec() == QDialog::Accepted)
{
m_settings->setSettings(dialog.getSettings());
+ m_settings->setColorManagementSystemSettings(dialog.getCMSSettings());
}
}
diff --git a/PdfForQtViewer/pdfviewermainwindow.h b/PdfForQtViewer/pdfviewermainwindow.h
index 180876e..79f863a 100644
--- a/PdfForQtViewer/pdfviewermainwindow.h
+++ b/PdfForQtViewer/pdfviewermainwindow.h
@@ -139,6 +139,7 @@ private:
};
Ui::PDFViewerMainWindow* ui;
+ pdf::PDFCMSManager* m_CMSManager;
PDFViewerSettings* m_settings;
pdf::PDFWidget* m_pdfWidget;
QSharedPointer m_pdfDocument;
diff --git a/PdfForQtViewer/pdfviewersettings.cpp b/PdfForQtViewer/pdfviewersettings.cpp
index f7f9511..9c4e44a 100644
--- a/PdfForQtViewer/pdfviewersettings.cpp
+++ b/PdfForQtViewer/pdfviewersettings.cpp
@@ -26,11 +26,14 @@ const int PIXMAP_CACHE_LIMIT = QPixmapCache::cacheLimit();
void PDFViewerSettings::setSettings(const PDFViewerSettings::Settings& settings)
{
- m_settings = settings;
- emit settingsChanged();
+ if (m_settings != settings)
+ {
+ m_settings = settings;
+ emit settingsChanged();
+ }
}
-void PDFViewerSettings::readSettings(QSettings& settings)
+void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSettings& defaultCMSSettings)
{
Settings defaultSettings;
@@ -52,6 +55,18 @@ void PDFViewerSettings::readSettings(QSettings& settings)
m_settings.m_allowLaunchURI = settings.value("allowLaunchURI", defaultSettings.m_allowLaunchURI).toBool();
settings.endGroup();
+ settings.beginGroup("ColorManagementSystemSettings");
+ m_colorManagementSystemSettings.system = static_cast(settings.value("system", int(defaultCMSSettings.system)).toInt());
+ m_colorManagementSystemSettings.accuracy = static_cast(settings.value("accuracy", int(defaultCMSSettings.accuracy)).toInt());
+ m_colorManagementSystemSettings.intent = static_cast(settings.value("intent", int(defaultCMSSettings.intent)).toInt());
+ m_colorManagementSystemSettings.isBlackPointCompensationActive = settings.value("isBlackPointCompensationActive", defaultCMSSettings.isBlackPointCompensationActive).toBool();
+ m_colorManagementSystemSettings.isWhitePaperColorTransformed = settings.value("isWhitePaperColorTransformed", defaultCMSSettings.isWhitePaperColorTransformed).toBool();
+ m_colorManagementSystemSettings.outputCS = settings.value("outputCS", defaultCMSSettings.outputCS).toString();
+ m_colorManagementSystemSettings.deviceGray = settings.value("deviceGray", defaultCMSSettings.deviceGray).toString();
+ m_colorManagementSystemSettings.deviceRGB = settings.value("deviceRGB", defaultCMSSettings.deviceRGB).toString();
+ m_colorManagementSystemSettings.deviceCMYK = settings.value("deviceCMYK", defaultCMSSettings.deviceCMYK).toString();
+ settings.endGroup();
+
emit settingsChanged();
}
@@ -74,6 +89,18 @@ void PDFViewerSettings::writeSettings(QSettings& settings)
settings.setValue("allowLaunchApplications", m_settings.m_allowLaunchApplications);
settings.setValue("allowLaunchURI", m_settings.m_allowLaunchURI);
settings.endGroup();
+
+ settings.beginGroup("ColorManagementSystemSettings");
+ settings.setValue("system", int(m_colorManagementSystemSettings.system));
+ settings.setValue("accuracy", int(m_colorManagementSystemSettings.accuracy));
+ settings.setValue("intent", int(m_colorManagementSystemSettings.intent));
+ settings.setValue("isBlackPointCompensationActive", m_colorManagementSystemSettings.isBlackPointCompensationActive);
+ settings.setValue("isWhitePaperColorTransformed", m_colorManagementSystemSettings.isWhitePaperColorTransformed);
+ settings.setValue("outputCS", m_colorManagementSystemSettings.outputCS);
+ settings.setValue("deviceGray", m_colorManagementSystemSettings.deviceGray);
+ settings.setValue("deviceRGB", m_colorManagementSystemSettings.deviceRGB);
+ settings.setValue("deviceCMYK", m_colorManagementSystemSettings.deviceCMYK);
+ settings.endGroup();
}
QString PDFViewerSettings::getDirectory() const
diff --git a/PdfForQtViewer/pdfviewersettings.h b/PdfForQtViewer/pdfviewersettings.h
index 71af27b..fe421d1 100644
--- a/PdfForQtViewer/pdfviewersettings.h
+++ b/PdfForQtViewer/pdfviewersettings.h
@@ -19,6 +19,7 @@
#define PDFVIEWERSETTINGS_H
#include "pdfrenderer.h"
+#include "pdfcms.h"
#include
@@ -40,6 +41,9 @@ public:
{
Settings();
+ bool operator==(const Settings&) const = default;
+ bool operator!=(const Settings&) const = default;
+
pdf::PDFRenderer::Features m_features;
QString m_directory;
pdf::RendererEngine m_rendererEngine;
@@ -62,7 +66,7 @@ public:
const Settings& getSettings() const { return m_settings; }
void setSettings(const Settings& settings);
- void readSettings(QSettings& settings);
+ void readSettings(QSettings& settings, const pdf::PDFCMSSettings& defaultCMSSettings);
void writeSettings(QSettings& settings);
QString getDirectory() const;
@@ -94,14 +98,17 @@ public:
int getFontCacheLimit() const { return m_settings.m_fontCacheLimit; }
int getInstancedFontCacheLimit() const { return m_settings.m_instancedFontCacheLimit; }
+ const pdf::PDFCMSSettings& getColorManagementSystemSettings() const { return m_colorManagementSystemSettings; }
+ void setColorManagementSystemSettings(const pdf::PDFCMSSettings& settings) { m_colorManagementSystemSettings = settings; }
+
signals:
void settingsChanged();
private:
Settings m_settings;
+ pdf::PDFCMSSettings m_colorManagementSystemSettings;
};
-
} // namespace pdfviewer
#endif // PDFVIEWERSETTINGS_H
diff --git a/PdfForQtViewer/pdfviewersettingsdialog.cpp b/PdfForQtViewer/pdfviewersettingsdialog.cpp
index a14c62d..3a202d2 100644
--- a/PdfForQtViewer/pdfviewersettingsdialog.cpp
+++ b/PdfForQtViewer/pdfviewersettingsdialog.cpp
@@ -29,10 +29,14 @@
namespace pdfviewer
{
-PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settings& settings, QList actions, QWidget *parent) :
+PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settings& settings,
+ const pdf::PDFCMSSettings& cmsSettings,
+ QList actions,
+ pdf::PDFCMSManager* cmsManager, QWidget *parent) :
QDialog(parent),
ui(new Ui::PDFViewerSettingsDialog),
m_settings(settings),
+ m_cmsSettings(cmsSettings),
m_actions(),
m_isLoadingData(false)
{
@@ -43,6 +47,7 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
new QListWidgetItem(QIcon(":/resources/shading.svg"), tr("Shading"), ui->optionsPagesWidget, ShadingSettings);
new QListWidgetItem(QIcon(":/resources/cache.svg"), tr("Cache"), ui->optionsPagesWidget, CacheSettings);
new QListWidgetItem(QIcon(":/resources/shortcuts.svg"), tr("Shortcuts"), ui->optionsPagesWidget, ShortcutSettings);
+ new QListWidgetItem(QIcon(":/resources/cms.svg"), tr("Colors"), ui->optionsPagesWidget, ColorManagementSystemSettings);
new QListWidgetItem(QIcon(":/resources/security.svg"), tr("Security"), ui->optionsPagesWidget, SecuritySettings);
ui->renderingEngineComboBox->addItem(tr("Software"), static_cast(pdf::RendererEngine::Software));
@@ -53,7 +58,33 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
ui->multisampleAntialiasingSamplesCountComboBox->addItem(QString::number(i), i);
}
- for (QWidget* widget : { ui->engineInfoLabel, ui->renderingInfoLabel, ui->securityInfoLabel })
+ // Load CMS data
+ ui->cmsTypeComboBox->addItem(pdf::PDFCMSManager::getSystemName(pdf::PDFCMSSettings::System::Generic), int(pdf::PDFCMSSettings::System::Generic));
+ ui->cmsTypeComboBox->addItem(pdf::PDFCMSManager::getSystemName(pdf::PDFCMSSettings::System::LittleCMS2), int(pdf::PDFCMSSettings::System::LittleCMS2));
+
+ ui->cmsRenderingIntentComboBox->addItem(tr("Auto"), int(pdf::RenderingIntent::Auto));
+ ui->cmsRenderingIntentComboBox->addItem(tr("Perceptual"), int(pdf::RenderingIntent::Perceptual));
+ ui->cmsRenderingIntentComboBox->addItem(tr("Relative colorimetric"), int(pdf::RenderingIntent::RelativeColorimetric));
+ ui->cmsRenderingIntentComboBox->addItem(tr("Absolute colorimetric"), int(pdf::RenderingIntent::AbsoluteColorimetric));
+ ui->cmsRenderingIntentComboBox->addItem(tr("Saturation"), int(pdf::RenderingIntent::Saturation));
+
+ ui->cmsAccuracyComboBox->addItem(tr("Low"), int(pdf::PDFCMSSettings::Accuracy::Low));
+ ui->cmsAccuracyComboBox->addItem(tr("Medium"), int(pdf::PDFCMSSettings::Accuracy::Medium));
+ ui->cmsAccuracyComboBox->addItem(tr("High"), int(pdf::PDFCMSSettings::Accuracy::High));
+
+ auto fillColorProfileList = [](QComboBox* comboBox, const pdf::PDFColorSpaceIdentifiers& identifiers)
+ {
+ for (const pdf::PDFColorSpaceIdentifier& identifier : identifiers)
+ {
+ comboBox->addItem(identifier.name, identifier.id);
+ }
+ };
+ fillColorProfileList(ui->cmsOutputColorProfileComboBox, cmsManager->getOutputProfiles());
+ fillColorProfileList(ui->cmsDeviceGrayColorProfileComboBox, cmsManager->getGrayProfiles());
+ fillColorProfileList(ui->cmsDeviceRGBColorProfileComboBox, cmsManager->getRGBProfiles());
+ fillColorProfileList(ui->cmsDeviceCMYKColorProfileComboBox, cmsManager->getCMYKProfiles());
+
+ for (QWidget* widget : { ui->engineInfoLabel, ui->renderingInfoLabel, ui->securityInfoLabel, ui->cmsInfoLabel })
{
widget->setMinimumWidth(widget->sizeHint().width());
}
@@ -120,6 +151,10 @@ void PDFViewerSettingsDialog::on_optionsPagesWidget_currentItemChanged(QListWidg
ui->stackedWidget->setCurrentWidget(ui->shortcutsPage);
break;
+ case ColorManagementSystemSettings:
+ ui->stackedWidget->setCurrentWidget(ui->cmsPage);
+ break;
+
case SecuritySettings:
ui->stackedWidget->setCurrentWidget(ui->securityPage);
break;
@@ -183,6 +218,47 @@ void PDFViewerSettingsDialog::loadData()
// Security
ui->allowLaunchCheckBox->setChecked(m_settings.m_allowLaunchApplications);
ui->allowRunURICheckBox->setChecked(m_settings.m_allowLaunchURI);
+
+ // CMS
+ ui->cmsTypeComboBox->setCurrentIndex(ui->cmsTypeComboBox->findData(int(m_cmsSettings.system)));
+ if (m_cmsSettings.system != pdf::PDFCMSSettings::System::Generic)
+ {
+ ui->cmsRenderingIntentComboBox->setEnabled(true);
+ ui->cmsRenderingIntentComboBox->setCurrentIndex(ui->cmsRenderingIntentComboBox->findData(int(m_cmsSettings.intent)));
+ ui->cmsAccuracyComboBox->setEnabled(true);
+ ui->cmsAccuracyComboBox->setCurrentIndex(ui->cmsAccuracyComboBox->findData(int(m_cmsSettings.accuracy)));
+ ui->cmsIsBlackPointCompensationCheckBox->setEnabled(true);
+ ui->cmsIsBlackPointCompensationCheckBox->setChecked(m_cmsSettings.isBlackPointCompensationActive);
+ ui->cmsWhitePaperColorTransformedCheckBox->setEnabled(true);
+ ui->cmsWhitePaperColorTransformedCheckBox->setChecked(m_cmsSettings.isWhitePaperColorTransformed);
+ ui->cmsOutputColorProfileComboBox->setEnabled(true);
+ ui->cmsOutputColorProfileComboBox->setCurrentIndex(ui->cmsOutputColorProfileComboBox->findData(m_cmsSettings.outputCS));
+ ui->cmsDeviceGrayColorProfileComboBox->setEnabled(true);
+ ui->cmsDeviceGrayColorProfileComboBox->setCurrentIndex(ui->cmsDeviceGrayColorProfileComboBox->findData(m_cmsSettings.deviceGray));
+ ui->cmsDeviceRGBColorProfileComboBox->setEnabled(true);
+ ui->cmsDeviceRGBColorProfileComboBox->setCurrentIndex(ui->cmsDeviceRGBColorProfileComboBox->findData(m_cmsSettings.deviceRGB));
+ ui->cmsDeviceCMYKColorProfileComboBox->setEnabled(true);
+ ui->cmsDeviceCMYKColorProfileComboBox->setCurrentIndex(ui->cmsDeviceCMYKColorProfileComboBox->findData(m_cmsSettings.deviceCMYK));
+ }
+ else
+ {
+ ui->cmsRenderingIntentComboBox->setEnabled(false);
+ ui->cmsRenderingIntentComboBox->setCurrentIndex(-1);
+ ui->cmsAccuracyComboBox->setEnabled(false);
+ ui->cmsAccuracyComboBox->setCurrentIndex(-1);
+ ui->cmsIsBlackPointCompensationCheckBox->setEnabled(false);
+ ui->cmsIsBlackPointCompensationCheckBox->setChecked(false);
+ ui->cmsWhitePaperColorTransformedCheckBox->setEnabled(false);
+ ui->cmsWhitePaperColorTransformedCheckBox->setChecked(false);
+ ui->cmsOutputColorProfileComboBox->setEnabled(false);
+ ui->cmsOutputColorProfileComboBox->setCurrentIndex(-1);
+ ui->cmsDeviceGrayColorProfileComboBox->setEnabled(false);
+ ui->cmsDeviceGrayColorProfileComboBox->setCurrentIndex(-1);
+ ui->cmsDeviceRGBColorProfileComboBox->setEnabled(false);
+ ui->cmsDeviceRGBColorProfileComboBox->setCurrentIndex(-1);
+ ui->cmsDeviceCMYKColorProfileComboBox->setEnabled(false);
+ ui->cmsDeviceCMYKColorProfileComboBox->setCurrentIndex(-1);
+ }
}
void PDFViewerSettingsDialog::saveData()
@@ -270,6 +346,42 @@ void PDFViewerSettingsDialog::saveData()
{
m_settings.m_instancedFontCacheLimit = ui->cachedInstancedFontLimitEdit->value();
}
+ else if (sender == ui->cmsTypeComboBox)
+ {
+ m_cmsSettings.system = static_cast(ui->cmsTypeComboBox->currentData().toInt());
+ }
+ else if (sender == ui->cmsRenderingIntentComboBox)
+ {
+ m_cmsSettings.intent = static_cast(ui->cmsRenderingIntentComboBox->currentData().toInt());
+ }
+ else if (sender == ui->cmsAccuracyComboBox)
+ {
+ m_cmsSettings.accuracy = static_cast(ui->cmsAccuracyComboBox->currentData().toInt());
+ }
+ else if (sender == ui->cmsIsBlackPointCompensationCheckBox)
+ {
+ m_cmsSettings.isBlackPointCompensationActive = ui->cmsIsBlackPointCompensationCheckBox->isChecked();
+ }
+ else if (sender == ui->cmsWhitePaperColorTransformedCheckBox)
+ {
+ m_cmsSettings.isWhitePaperColorTransformed = ui->cmsWhitePaperColorTransformedCheckBox->isChecked();
+ }
+ else if (sender == ui->cmsOutputColorProfileComboBox)
+ {
+ m_cmsSettings.outputCS = ui->cmsOutputColorProfileComboBox->currentData().toString();
+ }
+ else if (sender == ui->cmsDeviceGrayColorProfileComboBox)
+ {
+ m_cmsSettings.deviceGray = ui->cmsDeviceGrayColorProfileComboBox->currentData().toString();
+ }
+ else if (sender == ui->cmsDeviceRGBColorProfileComboBox)
+ {
+ m_cmsSettings.deviceRGB = ui->cmsDeviceRGBColorProfileComboBox->currentData().toString();
+ }
+ else if (sender == ui->cmsDeviceCMYKColorProfileComboBox)
+ {
+ m_cmsSettings.deviceCMYK = ui->cmsDeviceCMYKColorProfileComboBox->currentData().toString();
+ }
loadData();
}
diff --git a/PdfForQtViewer/pdfviewersettingsdialog.h b/PdfForQtViewer/pdfviewersettingsdialog.h
index cff9c62..7be8093 100644
--- a/PdfForQtViewer/pdfviewersettingsdialog.h
+++ b/PdfForQtViewer/pdfviewersettingsdialog.h
@@ -37,7 +37,17 @@ class PDFViewerSettingsDialog : public QDialog
Q_OBJECT
public:
- explicit PDFViewerSettingsDialog(const PDFViewerSettings::Settings& settings, QList actions, QWidget* parent);
+ /// Constructor
+ /// \param settings Viewer settings
+ /// \param cmsSettings Color management system settings
+ /// \param actions Actions
+ /// \param cmsManager CMS manager
+ /// \param parent Parent widget
+ explicit PDFViewerSettingsDialog(const PDFViewerSettings::Settings& settings,
+ const pdf::PDFCMSSettings& cmsSettings,
+ QList actions,
+ pdf::PDFCMSManager* cmsManager,
+ QWidget* parent);
virtual ~PDFViewerSettingsDialog() override;
virtual void accept() override;
@@ -49,10 +59,12 @@ public:
ShadingSettings,
CacheSettings,
ShortcutSettings,
+ ColorManagementSystemSettings,
SecuritySettings
};
const PDFViewerSettings::Settings& getSettings() const { return m_settings; }
+ const pdf::PDFCMSSettings& getCMSSettings() const { return m_cmsSettings; }
private slots:
void on_optionsPagesWidget_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous);
@@ -66,6 +78,7 @@ private:
Ui::PDFViewerSettingsDialog* ui;
PDFViewerSettings::Settings m_settings;
+ pdf::PDFCMSSettings m_cmsSettings;
QList m_actions;
bool m_isLoadingData;
};
diff --git a/PdfForQtViewer/pdfviewersettingsdialog.ui b/PdfForQtViewer/pdfviewersettingsdialog.ui
index 504e76a..9ef3719 100644
--- a/PdfForQtViewer/pdfviewersettingsdialog.ui
+++ b/PdfForQtViewer/pdfviewersettingsdialog.ui
@@ -6,8 +6,8 @@
0
0
- 720
- 538
+ 742
+ 573
@@ -26,7 +26,7 @@
-
- 4
+ 5
@@ -564,6 +564,144 @@
+
+
+ -
+
+
+ Color management system settings
+
+
+
-
+
+
-
+
+
+ -
+
+
+ Enabled
+
+
+
+ -
+
+
+ White paper color transformed
+
+
+
+ -
+
+
+ Device RGB color profile
+
+
+
+ -
+
+
+ Output color profile
+
+
+
+ -
+
+
+ Enabled
+
+
+
+ -
+
+
+ Device gray color profile
+
+
+
+ -
+
+
+ -
+
+
+ Rendering intent
+
+
+
+ -
+
+
+ -
+
+
+ Accuracy
+
+
+
+ -
+
+
+ Color management system
+
+
+
+ -
+
+
+ Black point compensation
+
+
+
+ -
+
+
+ Device CMYK color profile
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ <html><head/><body><p><span style=" font-weight:600;">Color management system </span>manages input and output color profiles and color transformations. It enables to perceive real colors defined in PDF document. Select 'Generic' to disable this functionality for fast color transform. <span style=" font-weight:600;">Rendering intent</span> affects how colors are transformed. Rendering intents are usually defined in content streams in PDF document, but you can override them, if you select other intent, than 'Auto'. <span style=" font-weight:600;">Accuracy </span>affects how precise the color transformation would be, at the cost of more memory consumption. <span style=" font-weight:600;">Black point compensation</span> compensates black colors out of gamut. <span style=" font-weight:600;">White paper color transformed </span>affects color of the underlying white paper - it transforms pure white from device RGB profile to output profile, if enabled.</p><p><span style=" font-weight:600;">Output color profile</span> defines output (target) rendering profile. This profile should be color space, in which your screen is displaying colors. You can also define color spaces for <span style=" font-weight:600;">gray/RGB/CMYK</span> device color spaces, which are used to transform gray/RGB/CMYK colors to the output color profile.</p></body></html>
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 41
+
+
+
+
+
+
+
+
+
diff --git a/PdfForQtViewer/resources/cms.svg b/PdfForQtViewer/resources/cms.svg
new file mode 100644
index 0000000..998597e
--- /dev/null
+++ b/PdfForQtViewer/resources/cms.svg
@@ -0,0 +1,110 @@
+
+
+
+