Krita Source Code Documentation
Loading...
Searching...
No Matches
KoColorProfileStorage.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <cmath>
10
11#include <QHash>
12#include <QReadWriteLock>
13#include <QString>
14
15#include "DebugPigment.h"
16#include "KoColorSpaceFactory.h"
17#include "KoColorProfile.h"
18#include "KoColorProfileQuery.h"
19#include "kis_assert.h"
20
21
23 QHash<QString, KoColorProfile * > profileMap;
24 QHash<QByteArray, KoColorProfile * > profileUniqueIdMap;
26 QHash<QString, QString> profileAlias;
27 QReadWriteLock lock;
28
30
32 {
33 Q_FOREACH (KoColorProfile *p, profileMap) {
34 profileUniqueIdMap.remove(p->uniqueId());
35 duplicates.removeAll(p);
36 delete p;
37 }
38 profileMap.clear();
39 Q_FOREACH (KoColorProfile *p, profileUniqueIdMap) {
40 duplicates.removeAll(p);
41 delete p;
42 }
43 profileUniqueIdMap.clear();
44 Q_FOREACH(KoColorProfile *p, duplicates) {
45 delete p;
46 }
47 duplicates.clear();
48 }
49};
50
56
60
62{
63 QWriteLocker locker(&d->lock);
64
65 if (profile->valid()) {
66 d->profileMap[profile->name()] = profile;
67 if (d->profileUniqueIdMap.contains(profile->uniqueId())) {
68 //warnPigment << "Duplicated profile" << profile->name() << profile->fileName() << d->profileUniqueIdMap[profile->uniqueId()]->fileName();
69 d->duplicates.append(d->profileUniqueIdMap[profile->uniqueId()]);
70 }
71 d->profileUniqueIdMap.insert(profile->uniqueId(), profile);
72 }
73}
74
76{
77 QWriteLocker locker(&d->lock);
78
79 d->profileMap.remove(profile->name());
80 d->profileUniqueIdMap.remove(profile->uniqueId());
81 d->duplicates.removeAll(profile);
82}
83
85{
86 QReadLocker l(&d->lock);
87 return d->profileMap.contains(profile->name());
88}
89
90void KoColorProfileStorage::addProfileAlias(const QString &name, const QString &to)
91{
92 QWriteLocker l(&d->lock);
93 d->profileAlias[name] = to;
94}
95
97{
98 QWriteLocker l(&d->lock);
99 d->profileAlias.remove(name);
100}
101
102QString KoColorProfileStorage::profileAlias(const QString &name) const
103{
104 QReadLocker l(&d->lock);
109 return d->profileMap.contains(name) ? name : d->profileAlias.value(name, name);
110}
111
113{
114 QReadLocker l(&d->lock);
119 if (d->profileMap.contains(name)) {
120 return d->profileMap[name];
121 }
122
123 return d->profileMap.value(d->profileAlias.value(name, name), 0);
124}
125
127{
128 QWriteLocker l(&lock);
129 profileUniqueIdMap.clear();
130
131 for (auto it = profileMap.constBegin();
132 it != profileMap.constEnd();
133 ++it) {
134
135 KoColorProfile *profile = it.value();
136 QByteArray id = profile->uniqueId();
137
138 if (!id.isEmpty()) {
139 profileUniqueIdMap.insert(id, profile);
140 }
141 }
142}
143
144
146{
147 QReadLocker l(&d->lock);
148 if (d->profileUniqueIdMap.isEmpty()) {
149 l.unlock();
150 d->populateUniqueIdMap();
151 l.relock();
152 }
153 return d->profileUniqueIdMap.value(id, 0);
154
155}
156
158{
160 if (!csf) return profiles;
161
162 QReadLocker l(&d->lock);
163
164 QHash<QString, KoColorProfile * >::ConstIterator it;
165 for (it = d->profileMap.constBegin(); it != d->profileMap.constEnd(); ++it) {
166 KoColorProfile * profile = it.value();
167 if (csf->profileIsCompatible(profile)) {
168 Q_ASSERT(profile);
169 // if (profile->colorSpaceSignature() == csf->colorSpaceSignature()) {
170 profiles.push_back(profile);
171 }
172 }
173 return profiles;
174}
175
177{
179
180 if (!query.isValid()) {
181 return profiles;
182 }
183
184 QReadLocker l(&d->lock);
185 for (const KoColorProfile* profile : d->profileMap) {
186 bool colorantMatch = (!query.rgbColorants.isEmpty() || query.primaries != PRIMARIES_UNSPECIFIED);
187 bool colorantTypeMatch = (query.primaries == PRIMARIES_UNSPECIFIED);
188 bool transferMatch = (query.transfer == TRC_UNSPECIFIED);
189 if (query.primaries != PRIMARIES_UNSPECIFIED) {
190 if (int(profile->getColorPrimaries()) == query.primaries) {
191 colorantTypeMatch = true;
192 }
193 }
194 if (query.transfer != TRC_UNSPECIFIED) {
195 if (int(profile->getTransferCharacteristics()) == query.transfer) {
196 transferMatch = true;
197 }
198 }
199
200 if (!query.rgbColorants.isEmpty() && query.primaries == PRIMARIES_UNSPECIFIED) {
201 KoColorimetryUtils::xyY wp = profile->getWhitePointxyY();
202 if (profile->getColorantsxyY().size() == query.rgbColorants.size()) {
203 QVector<KoColorimetryUtils::xyY> col = profile->getColorantsxyY();
204 if (col.isEmpty()) {
205 // too few colorants, skip.
206 continue;
207 }
208
209 colorantMatch = (std::fabs(wp.x - query.whitePoint.x) < error) && (std::fabs(wp.y - query.whitePoint.y) < error);
210 if (!colorantMatch) {
211 continue;
212 }
213
214 for (int i = 0; i < col.size(); i++) {
215 colorantMatch = (std::fabs(col[i].x - query.rgbColorants[i].x) < error) && (std::fabs(col[i].y - query.rgbColorants[i].y) < error);
216 if (!colorantMatch) {
217 break;
218 }
219 }
220 } else {
221 if (std::fabs(wp.x - query.whitePoint.x) < error && std::fabs(wp.y - query.whitePoint.y) < error) {
222 colorantMatch = true;
223 }
224 }
225 }
226
227 if (transferMatch && colorantMatch && colorantTypeMatch) {
228 profiles.push_back(profile);
229 }
230 }
231
232 return profiles;
233}
const Params2D p
@ PRIMARIES_UNSPECIFIED
const KoColorProfile * profileByName(const QString &name) const
QList< const KoColorProfile * > profilesFor(const KoColorSpaceFactory *csf) const
void removeProfileAlias(const QString &name)
QString profileAlias(const QString &name) const
void removeProfile(KoColorProfile *profile)
bool containsProfile(const KoColorProfile *profile)
containsProfile shows if a profile is registered in the storage
const KoColorProfile * profileByUniqueId(const QByteArray &id) const
const QScopedPointer< Private > d
void addProfileAlias(const QString &name, const QString &to)
void addProfile(KoColorProfile *profile)
The KoColorProfileQuery struct.
TransferCharacteristics transfer
CICP-compatible enum value representing the white point and primaries.
ColorPrimaries primaries
Rgb Primaries of the profile. When empty, this is a query for a greyscale profile.
bool isValid() const
CICP-compatible enum value representing the transfer function.
QList< KoColorimetryUtils::xy > rgbColorants
The desired white point of the profile.
KoColorimetryUtils::xy whitePoint
QHash< QByteArray, KoColorProfile * > profileUniqueIdMap
QList< KoColorProfile * > duplicates
QHash< QString, KoColorProfile * > profileMap
QHash< QString, QString > profileAlias
virtual QByteArray uniqueId() const =0
virtual bool valid() const =0
virtual bool profileIsCompatible(const KoColorProfile *profile) const =0