Plugin for soft-proofing

This commit is contained in:
Jakub Melka 2020-12-25 19:01:08 +01:00
parent 05db7a1d30
commit 468a492e19
18 changed files with 881 additions and 9 deletions

View File

@ -59,9 +59,13 @@ private:
RGB,
CMYK,
XYZ,
SoftProofing,
ProfileCount
};
/// Returns true, if we are doing soft-proofing
bool isSoftProofing() const;
/// Creates a profile using provided id and a list of profile descriptors.
/// If profile can't be created, then null handle is returned.
/// \param id Id of color profile
@ -455,7 +459,23 @@ cmsHTRANSFORM PDFLittleCMS::getTransformFromICCProfile(const QByteArray& iccData
if (const cmsUInt32Number inputDataFormat = getProfileDataFormat(profile))
{
cmsUInt32Number lcmsIntent = getLittleCMSRenderingIntent(effectiveRenderingIntent);
transform = cmsCreateTransform(profile, inputDataFormat, m_profiles[Output], isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, lcmsIntent, getTransformationFlags());
if (isSoftProofing())
{
cmsHPROFILE proofingProfile = m_profiles[SoftProofing];
RenderingIntent proofingIntent = m_settings.proofingIntent;
if (m_settings.proofingIntent == RenderingIntent::Auto)
{
proofingIntent = effectiveRenderingIntent;
}
transform = cmsCreateProofingTransform(profile, inputDataFormat, m_profiles[Output], isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, proofingProfile,
lcmsIntent, getLittleCMSRenderingIntent(proofingIntent), getTransformationFlags());
}
else
{
transform = cmsCreateTransform(profile, inputDataFormat, m_profiles[Output], isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, lcmsIntent, getTransformationFlags());
}
}
cmsCloseProfile(profile);
}
@ -514,8 +534,12 @@ void PDFLittleCMS::init()
m_profiles[Gray] = createProfile(m_settings.deviceGray, m_manager->getGrayProfiles());
m_profiles[RGB] = createProfile(m_settings.deviceRGB, m_manager->getRGBProfiles());
m_profiles[CMYK] = createProfile(m_settings.deviceCMYK, m_manager->getCMYKProfiles());
m_profiles[SoftProofing] = createProfile(m_settings.softProofingProfile, m_manager->getCMYKProfiles());
m_profiles[XYZ] = cmsCreateXYZProfile();
cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = { 0xFFFF };
cmsSetAlarmCodes(alarmCodes);
if (m_settings.isWhitePaperColorTransformed)
{
m_paperColor = getColorFromDeviceRGB(PDFColor(1.0f, 1.0f, 1.0f), RenderingIntent::AbsoluteColorimetric, nullptr);
@ -533,6 +557,11 @@ void PDFLittleCMS::init()
m_transformationCache.reserve(64);
}
bool PDFLittleCMS::isSoftProofing() const
{
return (m_settings.isSoftProofing || m_settings.isGamutChecking) && m_profiles[SoftProofing];
}
cmsHPROFILE PDFLittleCMS::createProfile(const QString& id, const PDFColorProfileIdentifiers& profileDescriptors) const
{
auto it = std::find_if(profileDescriptors.cbegin(), profileDescriptors.cend(), [&id](const PDFColorProfileIdentifier& identifier) { return identifier.id == id; });
@ -621,7 +650,22 @@ cmsHTRANSFORM PDFLittleCMS::getTransform(Profile profile, RenderingIntent intent
if (input && output)
{
transform = cmsCreateTransform(input, getProfileDataFormat(input), output, isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, getLittleCMSRenderingIntent(intent), getTransformationFlags());
if (isSoftProofing())
{
cmsHPROFILE proofingProfile = m_profiles[SoftProofing];
RenderingIntent proofingIntent = m_settings.proofingIntent;
if (m_settings.proofingIntent == RenderingIntent::Auto)
{
proofingIntent = intent;
}
transform = cmsCreateProofingTransform(input, getProfileDataFormat(input), output, isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, proofingProfile,
getLittleCMSRenderingIntent(intent), getLittleCMSRenderingIntent(proofingIntent), getTransformationFlags());
}
else
{
transform = cmsCreateTransform(input, getProfileDataFormat(input), output, isRGB888Buffer ? TYPE_RGB_8 : TYPE_RGB_FLT, getLittleCMSRenderingIntent(intent), getTransformationFlags());
}
}
it = m_transformationCache.insert(std::make_pair(key, transform)).first;
@ -662,6 +706,16 @@ cmsUInt32Number PDFLittleCMS::getTransformationFlags() const
break;
}
if (m_settings.isGamutChecking)
{
flags |= cmsFLAGS_GAMUTCHECK;
}
if (m_settings.isSoftProofing)
{
flags |= cmsFLAGS_SOFTPROOFING;
}
return flags;
}

View File

@ -60,13 +60,17 @@ struct PDFCMSSettings
System system = System::Generic;
Accuracy accuracy = Accuracy::Medium;
RenderingIntent intent = RenderingIntent::Auto;
RenderingIntent proofingIntent = RenderingIntent::RelativeColorimetric;
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)
QString profileDirectory; ///< Directory containing color profiles
bool isGamutChecking = false;
bool isSoftProofing = 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)
QString softProofingProfile; ///< Identifiers for soft proofing profile
QString profileDirectory; ///< Directory containing color profiles
};
/// Color management system base class. It contains functions to transform

View File

@ -23,6 +23,7 @@ namespace pdf
PDFPlugin::PDFPlugin(QObject* parent) :
QObject(parent),
m_widget(nullptr),
m_cmsManager(nullptr),
m_document(nullptr)
{
@ -33,6 +34,11 @@ void PDFPlugin::setWidget(PDFWidget* widget)
m_widget = widget;
}
void PDFPlugin::setCMSManager(PDFCMSManager* manager)
{
m_cmsManager = manager;
}
void PDFPlugin::setDocument(const PDFModifiedDocument& document)
{
m_document = document;

View File

@ -30,6 +30,7 @@ class QAction;
namespace pdf
{
class PDFWidget;
class PDFCMSManager;
struct Pdf4QtLIBSHARED_EXPORT PDFPluginInfo
{
@ -51,11 +52,13 @@ public:
explicit PDFPlugin(QObject* parent);
virtual void setWidget(PDFWidget* widget);
virtual void setCMSManager(PDFCMSManager* manager);
virtual void setDocument(const PDFModifiedDocument& document);
virtual std::vector<QAction*> getActions() const;
protected:
PDFWidget* m_widget;
PDFCMSManager* m_cmsManager;
PDFDocument* m_document;
};

View File

@ -1686,6 +1686,7 @@ void PDFProgramController::loadPlugins()
for (const auto& plugin : m_loadedPlugins)
{
plugin.second->setWidget(m_pdfWidget);
plugin.second->setCMSManager(m_CMSManager);
std::vector<QAction*> actions = plugin.second->getActions();
if (!actions.empty())

View File

@ -26,7 +26,7 @@
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>11</number>
<number>5</number>
</property>
<widget class="QWidget" name="enginePage">
<layout class="QVBoxLayout" name="enginePageLayout">

View File

@ -19,6 +19,7 @@
TEMPLATE = subdirs
SUBDIRS += \
DimensionsPlugin
DimensionsPlugin \
SoftProofingPlugin

View File

@ -0,0 +1,7 @@
{
"Name" : "SoftProofing",
"Author" : "Jakub Melka",
"Version" : "1.0.0",
"License" : "LGPL v3",
"Description" : "Perform soft-proofing / gamut checking with CMYK profiles on a document."
}

View File

@ -0,0 +1,52 @@
# Copyright (C) 2020 Jakub Melka
#
# This file is part of Pdf4Qt.
#
# Pdf4Qt 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.
#
# Pdf4Qt 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 Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
TEMPLATE = lib
DEFINES += SOFTPROOFINGPLUGIN_LIBRARY
QT += gui widgets
LIBS += -L$$OUT_PWD/../..
LIBS += -lPdf4QtLib
QMAKE_CXXFLAGS += /std:c++latest /utf-8
INCLUDEPATH += $$PWD/../../Pdf4QtLib/Sources
DESTDIR = $$OUT_PWD/../../pdfplugins
CONFIG += c++11
SOURCES += \
softproofingplugin.cpp \
settingsdialog.cpp
HEADERS += \
softproofingplugin.h \
settingsdialog.h
CONFIG += force_debug_info
DISTFILES += \
SoftProofingPlugin.json
RESOURCES += \
icons.qrc
FORMS += \
settingsdialog.ui

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/pdfplugins/softproofing">
<file>gamut-checking.svg</file>
<file>soft-proofing.svg</file>
<file>settings.svg</file>
</qresource>
</RCC>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,58 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of Pdf4Qt.
//
// Pdf4Qt 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.
//
// Pdf4Qt 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 Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#include "settingsdialog.h"
#include "ui_settingsdialog.h"
#include "pdfwidgetutils.h"
SettingsDialog::SettingsDialog(QWidget* parent, const pdf::PDFCMSSettings& settings, const pdf::PDFCMSManager* manager) :
QDialog(parent),
ui(new Ui::SettingsDialog),
m_settings(settings)
{
ui->setupUi(this);
ui->cmsProofingIntentComboBox->addItem(tr("Auto"), int(pdf::RenderingIntent::Auto));
ui->cmsProofingIntentComboBox->addItem(tr("Perceptual"), int(pdf::RenderingIntent::Perceptual));
ui->cmsProofingIntentComboBox->addItem(tr("Relative colorimetric"), int(pdf::RenderingIntent::RelativeColorimetric));
ui->cmsProofingIntentComboBox->addItem(tr("Absolute colorimetric"), int(pdf::RenderingIntent::AbsoluteColorimetric));
ui->cmsProofingIntentComboBox->addItem(tr("Saturation"), int(pdf::RenderingIntent::Saturation));
for (const pdf::PDFColorProfileIdentifier& identifier : manager->getCMYKProfiles())
{
ui->cmsProofingColorProfileComboBox->addItem(identifier.name, identifier.id);
}
ui->cmsProofingIntentComboBox->setCurrentIndex(ui->cmsProofingIntentComboBox->findData(int(m_settings.proofingIntent)));
ui->cmsProofingColorProfileComboBox->setCurrentIndex(ui->cmsProofingColorProfileComboBox->findData(m_settings.softProofingProfile));
setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(320, 160)));
}
SettingsDialog::~SettingsDialog()
{
delete ui;
}
void SettingsDialog::accept()
{
m_settings.proofingIntent = static_cast<pdf::RenderingIntent>(ui->cmsProofingIntentComboBox->currentData().toInt());
m_settings.softProofingProfile = ui->cmsProofingColorProfileComboBox->currentData().toString();
QDialog::accept();
}

View File

@ -0,0 +1,51 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of Pdf4Qt.
//
// Pdf4Qt 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.
//
// Pdf4Qt 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 Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include "softproofingplugin.h"
#include "pdfcms.h"
#include <QDialog>
class QComboBox;
namespace Ui
{
class SettingsDialog;
}
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget* parent, const pdf::PDFCMSSettings& settings, const pdf::PDFCMSManager* manager);
virtual ~SettingsDialog() override;
virtual void accept() override;
const pdf::PDFCMSSettings& getSettings() const { return m_settings; }
private:
Ui::SettingsDialog* ui;
pdf::PDFCMSSettings m_settings;
};
#endif // SETTINGSDIALOG_H

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsDialog</class>
<widget class="QDialog" name="SettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>254</width>
<height>165</height>
</rect>
</property>
<property name="windowTitle">
<string>Soft Proofing Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="softProofingGroupBox">
<property name="title">
<string>Soft Proofing Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="cmsOutputProfileLabel">
<property name="text">
<string>Proofing profile</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cmsProofingColorProfileComboBox"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="cmsProofingIntentLabel">
<property name="text">
<string>Proofing intent</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cmsProofingIntentComboBox"/>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,141 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of Pdf4Qt.
//
// Pdf4Qt 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.
//
// Pdf4Qt 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 Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#include "softproofingplugin.h"
#include "settingsdialog.h"
#include "pdfcms.h"
#include "pdfutils.h"
#include "pdfdrawwidget.h"
#include <QAction>
namespace pdfplugin
{
SoftProofingPlugin::SoftProofingPlugin() :
pdf::PDFPlugin(nullptr),
m_enableSoftProofingAction(nullptr),
m_enableGamutCheckingAction(nullptr),
m_showSettingsAction(nullptr),
m_isLoadingGUI(false)
{
}
void SoftProofingPlugin::setWidget(pdf::PDFWidget* widget)
{
Q_ASSERT(!m_widget);
BaseClass::setWidget(widget);
m_enableSoftProofingAction = new QAction(QIcon(":/pdfplugins/softproofing/soft-proofing.svg"), tr("Soft Proofing"), this);
m_enableGamutCheckingAction = new QAction(QIcon(":/pdfplugins/softproofing/gamut-checking.svg"), tr("Gamut Checking"), this);
m_showSettingsAction = new QAction(QIcon(":/pdfplugins/softproofing/settings.svg"), tr("Soft Proofing Settings"), this);
m_enableSoftProofingAction->setCheckable(true);
m_enableGamutCheckingAction->setCheckable(true);
m_enableSoftProofingAction->setObjectName("actionSoftProofing_EnableSoftProofing");
m_enableGamutCheckingAction->setObjectName("actionSoftProofing_EnableGamutChecking");
m_showSettingsAction->setObjectName("actionSoftProofing_ShowSettings");
connect(m_enableSoftProofingAction, &QAction::triggered, this, &SoftProofingPlugin::onSoftProofingTriggered);
connect(m_enableGamutCheckingAction, &QAction::triggered, this, &SoftProofingPlugin::onGamutCheckingTriggered);
connect(m_showSettingsAction, &QAction::triggered, this, &SoftProofingPlugin::onSettingsTriggered);
updateActions();
}
void SoftProofingPlugin::setCMSManager(pdf::PDFCMSManager* manager)
{
BaseClass::setCMSManager(manager);
connect(manager, &pdf::PDFCMSManager::colorManagementSystemChanged, this, &SoftProofingPlugin::updateActions);
}
void SoftProofingPlugin::setDocument(const pdf::PDFModifiedDocument& document)
{
BaseClass::setDocument(document);
if (document.hasReset())
{
updateActions();
}
}
std::vector<QAction*> SoftProofingPlugin::getActions() const
{
return { m_enableSoftProofingAction, m_enableGamutCheckingAction, m_showSettingsAction };
}
void SoftProofingPlugin::onSoftProofingTriggered()
{
if (m_isLoadingGUI)
{
// We are just updating gui, do nothing
return;
}
pdf::PDFCMSSettings settings = m_cmsManager->getSettings();
settings.isSoftProofing = m_enableSoftProofingAction->isChecked();
m_cmsManager->setSettings(settings);
}
void SoftProofingPlugin::onGamutCheckingTriggered()
{
if (m_isLoadingGUI)
{
// We are just updating gui, do nothing
return;
}
pdf::PDFCMSSettings settings = m_cmsManager->getSettings();
settings.isGamutChecking = m_enableGamutCheckingAction->isChecked();
m_cmsManager->setSettings(settings);
}
void SoftProofingPlugin::onSettingsTriggered()
{
SettingsDialog settingsDialog(m_widget, m_cmsManager->getSettings(), m_cmsManager);
if (settingsDialog.exec() == SettingsDialog::Accepted)
{
m_cmsManager->setSettings(settingsDialog.getSettings());
}
}
void SoftProofingPlugin::updateActions()
{
pdf::PDFTemporaryValueChange guard(&m_isLoadingGUI, true);
if (m_enableSoftProofingAction)
{
m_enableSoftProofingAction->setEnabled(m_widget);
m_enableSoftProofingAction->setChecked(m_cmsManager && m_cmsManager->getSettings().isSoftProofing);
}
if (m_enableGamutCheckingAction)
{
m_enableGamutCheckingAction->setEnabled(m_widget);
m_enableGamutCheckingAction->setChecked(m_cmsManager && m_cmsManager->getSettings().isGamutChecking);
}
if (m_showSettingsAction)
{
m_showSettingsAction->setEnabled(m_widget);
}
}
}

View File

@ -0,0 +1,60 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of Pdf4Qt.
//
// Pdf4Qt 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.
//
// Pdf4Qt 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 Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#ifndef SOFTPROOFINGPLUGIN_H
#define SOFTPROOFINGPLUGIN_H
#include "pdfplugin.h"
#include <QObject>
namespace pdfplugin
{
class SoftProofingPlugin : public pdf::PDFPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "Pdf4Qt.SoftProofingPlugin" FILE "SoftProofingPlugin.json")
private:
using BaseClass = pdf::PDFPlugin;
public:
SoftProofingPlugin();
virtual void setWidget(pdf::PDFWidget* widget) override;
virtual void setCMSManager(pdf::PDFCMSManager* manager) override;
virtual void setDocument(const pdf::PDFModifiedDocument& document) override;
virtual std::vector<QAction*> getActions() const override;
private:
void onSoftProofingTriggered();
void onGamutCheckingTriggered();
void onSettingsTriggered();
void updateActions();
QAction* m_enableSoftProofingAction;
QAction* m_enableGamutCheckingAction;
QAction* m_showSettingsAction;
bool m_isLoadingGUI;
};
} // namespace pdfplugin
#endif // SOFTPROOFINGPLUGIN_H