Krita Source Code Documentation
Loading...
Searching...
No Matches
LcmsEnginePlugin.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2003 Patrick Julien <freak@codepimps.org>
3 * SPDX-FileCopyrightText: 2004, 2010 Cyrille Berger <cberger@cberger.net>
4 * SPDX-FileCopyrightText: 2011 Srikanth Tiyyagura <srikanth.tulasiram@gmail.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7*/
8#include "LcmsEnginePlugin.h"
9
10#include <QApplication>
11#include <QDebug>
12#include <QDir>
13#include <QStringList>
14
15#include <klocalizedstring.h>
16#include <kpluginfactory.h>
17
19#include <KoColorSpace.h>
20#include <KoColorSpaceEngine.h>
22#include <KoResourcePaths.h>
23#include <kis_assert.h>
24#include <kis_debug.h>
25
26#include "IccColorSpaceEngine.h"
27#include <KoColorProfileQuery.h>
29
33
37
41
45
49
53
54#include <KoConfig.h>
55
56#ifdef HAVE_OPENEXR
57# include <half.h>
58# ifdef HAVE_LCMS24
62# endif
63#endif
64
65#if defined(HAVE_LCMS_FAST_FLOAT_PLUGIN)
66#include <lcms2_fast_float.h>
67#endif
68
69void lcms2LogErrorHandlerFunction(cmsContext /*ContextID*/, cmsUInt32Number ErrorCode, const char *Text)
70{
71 errorPigment << "Lcms2 error: " << ErrorCode << Text;
72}
73
74K_PLUGIN_FACTORY_WITH_JSON(PluginFactory, "kolcmsengine.json", registerPlugin<LcmsEnginePlugin>();)
75
76LcmsEnginePlugin::LcmsEnginePlugin(QObject *parent, const QVariantList &)
77 : QObject(parent)
78{
79 KoResourcePaths::addAssetType("icc_profiles", "data", "/color/icc");
80 KoResourcePaths::addAssetType("icc_profiles", "data", "/profiles/");
81
82 // Set the lmcs error reporting function
83 cmsSetLogErrorHandler(&lcms2LogErrorHandlerFunction);
84
86
87 // Initialise color engine
89
90 QStringList profileFilenames;
91 profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.icm", KoResourcePaths::Recursive);
92 profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.ICM", KoResourcePaths::Recursive);
93 profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.ICC", KoResourcePaths::Recursive);
94 profileFilenames += KoResourcePaths::findAllAssets("icc_profiles", "*.icc", KoResourcePaths::Recursive);
95
96 QStringList iccProfileDirs;
97
98#ifdef Q_OS_MAC
99 iccProfileDirs.append(QDir::homePath() + "/Library/ColorSync/Profiles/");
100 iccProfileDirs.append("/System/Library/ColorSync/Profiles/");
101 iccProfileDirs.append("/Library/ColorSync/Profiles/");
102#endif
103#ifdef Q_OS_WIN
104 QString winPath = QString::fromUtf8(qgetenv("windir"));
105 winPath.replace('\\','/');
106 iccProfileDirs.append(winPath + "/System32/Spool/Drivers/Color/");
107
108#endif
109#ifdef Q_OS_LINUX
110 iccProfileDirs.append(QDir::homePath() + "./share/color/icc");
111#endif
112
113 QStringList blackList = QStringList() << "panhexro.icm"
114 << "ctpctdmed.icc";
115
116
117 Q_FOREACH(const QString &iccProfiledir, iccProfileDirs) {
118 QDir profileDir(iccProfiledir);
119 Q_FOREACH(const QString &entry, profileDir.entryList(QStringList() << "*.icm" << "*.icc" << "*.ICM" << "*.ICC", QDir::NoDotAndDotDot | QDir::Files | QDir::Readable)) {
120 if (blackList.contains(entry.toLower())) continue;
121 profileFilenames << iccProfiledir + "/" + entry;
122 }
123 }
124
125 // Load the profiles
126 if (!profileFilenames.empty()) {
127 for (QStringList::Iterator it = profileFilenames.begin(); it != profileFilenames.end(); ++it) {
128
129 KoColorProfile *profile = new IccColorProfile(*it);
130 Q_CHECK_PTR(profile);
131
132 profile->load();
133 if (profile->valid()) {
134 //qDebug() << "Valid profile : " << profile->fileName() << profile->name();
135 registry->addProfileToMap(profile);
136 } else {
137 qDebug() << "Invalid profile : " << *it;
138 delete profile;
139 }
140 }
141 }
142
143 // ------------------- LAB ---------------------------------
144
145 KoColorProfile *labProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreateLab4Profile(0));
146 registry->addProfile(labProfile);
147
148 registry->add(new LabU8ColorSpaceFactory());
149 registry->add(new LabU16ColorSpaceFactory());
150 registry->add(new LabF32ColorSpaceFactory());
151
154 (KoID("LABAU8HISTO", i18n("L*a*b*/8 Histogram")), LABAColorModelID.id(), Integer8BitsColorDepthID.id()));
155
158 (KoID("LABAU16HISTO", i18n("L*a*b*/16 Histogram")), LABAColorModelID.id(), Integer16BitsColorDepthID.id()));
159
162 (KoID("LABAF32HISTO", i18n("L*a*b*/32 Histogram")), LABAColorModelID.id(), Float32BitsColorDepthID.id()));
163
164 // ------------------- RGB ---------------------------------
165
166 KoColorProfile *rgbProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreate_sRGBProfile());
167 registry->addProfile(rgbProfile);
168
170 query.hdrReferenceWhite = std::make_optional(203.0);
171
172 KoColorProfile *rec2100pq203nits = new IccColorProfile(query);
173 registry->addProfile(rec2100pq203nits);
174
175 query.hdrReferenceWhite = std::make_optional(80.0);
176 KoColorProfile *rec2100pq80nits = new IccColorProfile(query);
177 registry->addProfile(rec2100pq80nits);
178
186 const QString legacyRec2020PQProfileName = "High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF";
187 registry->addProfileAlias(legacyRec2020PQProfileName, rec2100pq203nits->name());
188
189 registry->add(new RgbU8ColorSpaceFactory());
190 registry->add(new RgbU16ColorSpaceFactory());
191 #ifdef HAVE_LCMS24
192 #ifdef HAVE_OPENEXR
193 registry->add(new RgbF16ColorSpaceFactory());
194 #endif
195 #endif
196 registry->add(new RgbF32ColorSpaceFactory());
197
200 (KoID("RGBU8HISTO", i18n("RGBA/8 Histogram")), RGBAColorModelID.id(), Integer8BitsColorDepthID.id()));
201
204 (KoID("RGBU16HISTO", i18n("RGBA/16 Histogram")), RGBAColorModelID.id(), Integer16BitsColorDepthID.id()));
205
206#ifdef HAVE_LCMS24
207#ifdef HAVE_OPENEXR
210 (KoID("RGBF16HISTO", i18n("RGBA/F16 Histogram")), RGBAColorModelID.id(), Float16BitsColorDepthID.id()));
211#endif
212#endif
213
216 (KoID("RGF328HISTO", i18n("RGBA/F32 Histogram")), RGBAColorModelID.id(), Float32BitsColorDepthID.id()));
217
218 // ------------------- GRAY ---------------------------------
219
220 cmsToneCurve *Gamma = cmsBuildGamma(0, 2.2);
221 cmsHPROFILE hProfile = cmsCreateGrayProfile(cmsD50_xyY(), Gamma);
222 cmsFreeToneCurve(Gamma);
224 registry->addProfile(defProfile);
225
226 registry->add(new GrayAU8ColorSpaceFactory());
227 registry->add(new GrayAU16ColorSpaceFactory());
228#ifdef HAVE_LCMS24
229#ifdef HAVE_OPENEXR
230 registry->add(new GrayF16ColorSpaceFactory());
231#endif
232#endif
233 registry->add(new GrayF32ColorSpaceFactory());
234
237 (KoID("GRAYA8HISTO", i18n("GRAY/8 Histogram")), GrayAColorModelID.id(), Integer8BitsColorDepthID.id()));
238
241 (KoID("GRAYA16HISTO", i18n("GRAY/16 Histogram")), GrayAColorModelID.id(), Integer16BitsColorDepthID.id()));
242#ifdef HAVE_LCMS24
243#ifdef HAVE_OPENEXR
246 (KoID("GRAYF16HISTO", i18n("GRAYF/F16 Histogram")), GrayAColorModelID.id(), Float16BitsColorDepthID.id()));
247#endif
248#endif
249
252 (KoID("GRAYAF32HISTO", i18n("GRAY/F32 float Histogram")), GrayAColorModelID.id(), Float32BitsColorDepthID.id()));
253
254 // ------------------- CMYK ---------------------------------
255
256 registry->add(new CmykU8ColorSpaceFactory());
257 registry->add(new CmykU16ColorSpaceFactory());
258 registry->add(new CmykF32ColorSpaceFactory());
259
262 (KoID("CMYK8HISTO", i18n("CMYK/8 Histogram")), CMYKAColorModelID.id(), Integer8BitsColorDepthID.id()));
263
266 (KoID("CMYK16HISTO", i18n("CMYK/16 Histogram")), CMYKAColorModelID.id(), Integer16BitsColorDepthID.id()));
267
270 (KoID("CMYKF32HISTO", i18n("CMYK/F32 Histogram")), CMYKAColorModelID.id(), Float32BitsColorDepthID.id()));
271
272 // ------------------- XYZ ---------------------------------
273
274 KoColorProfile *xyzProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreateXYZProfile());
275 registry->addProfile(xyzProfile);
276
277 registry->add(new XyzU8ColorSpaceFactory());
278 registry->add(new XyzU16ColorSpaceFactory());
279#ifdef HAVE_LCMS24
280#ifdef HAVE_OPENEXR
281 registry->add(new XyzF16ColorSpaceFactory());
282#endif
283#endif
284 registry->add(new XyzF32ColorSpaceFactory());
285
288 (KoID("XYZ8HISTO", i18n("XYZ/8 Histogram")), XYZAColorModelID.id(), Integer8BitsColorDepthID.id()));
289
292 (KoID("XYZ16HISTO", i18n("XYZ/16 Histogram")), XYZAColorModelID.id(), Integer16BitsColorDepthID.id()));
293
294#ifdef HAVE_LCMS24
295#ifdef HAVE_OPENEXR
298 (KoID("XYZF16HISTO", i18n("XYZ/F16 Histogram")), XYZAColorModelID.id(), Float16BitsColorDepthID.id()));
299#endif
300#endif
301
304 (KoID("XYZF32HISTO", i18n("XYZF32 Histogram")), XYZAColorModelID.id(), Float32BitsColorDepthID.id()));
305
306 // ------------------- YCBCR ---------------------------------
307
308 // KoColorProfile *yCbCrProfile = LcmsColorProfileContainer::createFromLcmsProfile(cmsCreateYCBCRProfile());
309 // registry->addProfile(yCbCrProfile);
310
311 registry->add(new YCbCrU8ColorSpaceFactory());
312 registry->add(new YCbCrU16ColorSpaceFactory());
313 registry->add(new YCbCrF32ColorSpaceFactory());
314
317 (KoID("YCBCR8HISTO", i18n("YCbCr/8 Histogram")), YCbCrAColorModelID.id(), Integer8BitsColorDepthID.id()));
318
321 (KoID("YCBCR16HISTO", i18n("YCbCr/16 Histogram")), YCbCrAColorModelID.id(), Integer16BitsColorDepthID.id()));
322
325 (KoID("YCBCRF32HISTO", i18n("YCbCr/F32 Histogram")), YCbCrAColorModelID.id(), Float32BitsColorDepthID.id()));
326
327 // Add profile alias for default profile from lcms1
328 registry->addProfileAlias("sRGB built-in - (lcms internal)", "sRGB built-in");
329 registry->addProfileAlias("gray built-in - (lcms internal)", "gray built-in");
330 registry->addProfileAlias("Lab identity built-in - (lcms internal)", "Lab identity built-in");
331 registry->addProfileAlias("XYZ built-in - (lcms internal)", "XYZ identity built-in");
332
333#if defined(HAVE_LCMS_FAST_FLOAT_PLUGIN)
334 cmsPlugin(cmsFastFloatExtensions());
335#endif
336}
337
338#include <LcmsEnginePlugin.moc>
#define errorPigment
QList< QString > QStringList
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID YCbCrAColorModelID("YCbCrA", ki18n("YCbCr/Alpha"))
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID XYZAColorModelID("XYZA", ki18n("XYZ/Alpha"))
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const KoID CMYKAColorModelID("CMYKA", ki18n("CMYK/Alpha"))
const KoID LABAColorModelID("LABA", ki18n("L*a*b*/Alpha"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
@ PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
@ TRC_ITU_R_BT_2100_0_PQ
void lcms2LogErrorHandlerFunction(cmsContext, cmsUInt32Number ErrorCode, const char *Text)
static KoColorSpaceEngineRegistry * instance()
static KoHistogramProducerFactoryRegistry * instance()
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
static void addAssetType(const QString &type, const char *basetype, const QString &relativeName, bool priority=true)
static QStringList findAllAssets(const QString &type, const QString &filter=QString(), SearchOptions options=NoSearchOptions)
static IccColorProfile * createFromLcmsProfile(const cmsHPROFILE profile)
LcmsEnginePlugin(QObject *parent, const QVariantList &)
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
The KoColorProfileQuery struct.
std::optional< double > hdrReferenceWhite
CICP-compatible enum value representing the transfer function.
virtual bool load()
virtual bool valid() const =0
void addProfileAlias(const QString &name, const QString &to)
static KoColorSpaceRegistry * instance()
void add(KoColorSpaceFactory *item)
void addProfileToMap(KoColorProfile *p)
void addProfile(KoColorProfile *profile)