~smartboyhw/ubuntu/raring/calligra/2.6.0-0ubuntu1

« back to all changes in this revision

Viewing changes to krita/plugins/colorspaces/ctlcs/KoCtlColorProfile.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2012-10-23 21:09:16 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20121023210916-m82w6zxnxhaxz7va
Tags: 1:2.5.90-0ubuntu1
* New upstream alpha release (LP: #1070436)
  - Add libkactivities-dev and libopenimageio-dev to build-depends
  - Add kubuntu_build_calligraactive.diff to build calligraactive by default
  - Add package for calligraauthor and move files that are shared between
    calligrawords and calligraauthor to calligrawords-common
* Document the patches
* Remove numbers from patches so they follow the same naming scheme as
  the rest of our patches.
* calligra-data breaks replaces krita-data (<< 1:2.5.3) (LP: #1071686)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (c) 2008,2010 Cyrille Berger <cberger@cberger.net>
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public License
15
 
 * along with this library; see the file COPYING.LIB.  If not, write to
16
 
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 
 * Boston, MA 02110-1301, USA.
18
 
*/
19
 
 
20
 
#include "KoCtlColorProfile.h"
21
 
 
22
 
#include <math.h>
23
 
 
24
 
#include "DebugPigment.h"
25
 
 
26
 
#include <QDomDocument>
27
 
#include <QFile>
28
 
#include <QMutexLocker>
29
 
 
30
 
#include <QString>
31
 
 
32
 
#include <KoChannelInfo.h>
33
 
#include <KoColorSpace.h>
34
 
#include <KoColorModelStandardIds.h>
35
 
#include <KoColorSpaceRegistry.h>
36
 
#include <KoCtlColorConversionTransformation.h>
37
 
#include <KoUniqueNumberForIdServer.h>
38
 
 
39
 
#include <GTLCore/Version.h>
40
 
 
41
 
#if GTL_CORE_VERSION_MAJOR == 0 && GTL_CORE_VERSION_MINOR == 9 && GTL_CORE_VERSION_REVISION > 12
42
 
#include <GTLCore/CompilationMessages.h>
43
 
#endif
44
 
 
45
 
#include <GTLCore/PixelDescription.h>
46
 
#include <GTLCore/String.h>
47
 
#include <GTLCore/Type.h>
48
 
#include <GTLCore/Value.h>
49
 
#include <OpenCTL/Program.h>
50
 
#include <OpenCTL/Module.h>
51
 
#include "KoCtlMutex.h"
52
 
#include "KoCtlParser.h"
53
 
#include "KoCtlUtils.h"
54
 
 
55
 
#include "kis_debug.h"
56
 
#include <kis_gtl_lock.h>
57
 
 
58
 
struct ConversionInfo {
59
 
    QString sourceColorModelID;
60
 
    QString sourceColorDepthID;
61
 
    QString sourceProfile;
62
 
    QString destinationColorModelID;
63
 
    QString destinationColorDepthID;
64
 
    QString destinationProfile;
65
 
    QString function;
66
 
};
67
 
 
68
 
struct KoCtlColorProfile::Private {
69
 
    OpenCTL::Module* module;
70
 
    QList<ConversionInfo> conversionInfos;
71
 
    QString colorModelID;
72
 
    quint32 colorModelIDNumber;
73
 
    QString colorDepthID;
74
 
    quint32 colorDepthIDNumber;
75
 
    qreal exposure;
76
 
    qreal middleGrayScaleFactor;
77
 
    QString profileSource;
78
 
    bool loadFromSource(KoCtlColorProfile* self);
79
 
};
80
 
 
81
 
KoCtlColorProfile::KoCtlColorProfile() : KoColorProfile(), d(new Private)
82
 
{
83
 
    d->module = 0;
84
 
    d->middleGrayScaleFactor = 0.0883883;
85
 
    d->exposure = pow(2, 2.47393) * d->middleGrayScaleFactor;
86
 
}
87
 
 
88
 
KoCtlColorProfile* KoCtlColorProfile::fromFile(QString fileName)
89
 
{
90
 
    KoCtlColorProfile* profile = new KoCtlColorProfile;
91
 
    profile->setFileName(fileName);
92
 
    return profile;
93
 
}
94
 
 
95
 
KoCtlColorProfile* KoCtlColorProfile::fromString(QString string)
96
 
{
97
 
    KoCtlColorProfile* profile = new KoCtlColorProfile;
98
 
    profile->d->profileSource = string;
99
 
    if (profile->d->loadFromSource(profile)) {
100
 
        return profile;
101
 
    } else {
102
 
        delete profile;
103
 
        return 0;
104
 
    }
105
 
}
106
 
 
107
 
KoCtlColorProfile::KoCtlColorProfile(const KoCtlColorProfile& rhs) : KoColorProfile(rhs), d(new Private(*rhs.d))
108
 
{
109
 
 
110
 
}
111
 
 
112
 
KoCtlColorProfile::~KoCtlColorProfile()
113
 
{
114
 
    delete d->module;
115
 
    delete d;
116
 
}
117
 
 
118
 
KoColorProfile* KoCtlColorProfile::clone() const
119
 
{
120
 
    return new KoCtlColorProfile(*this);
121
 
}
122
 
 
123
 
bool KoCtlColorProfile::valid() const
124
 
{
125
 
    dbgPigment << d->colorModelID.isNull() << " " << d->colorDepthID.isNull() << " isCompiled: " << d->module->isCompiled();
126
 
    return (d->module && d->module->isCompiled() && !d->colorModelID.isNull() && !d->colorDepthID.isNull());
127
 
}
128
 
 
129
 
bool KoCtlColorProfile::isSuitableForOutput() const
130
 
{
131
 
    return true;
132
 
}
133
 
 
134
 
bool KoCtlColorProfile::isSuitableForPrinting() const
135
 
{
136
 
    return true;
137
 
}
138
 
 
139
 
bool KoCtlColorProfile::isSuitableForDisplay() const
140
 
{
141
 
    return true;
142
 
}
143
 
 
144
 
OpenCTL::Program* KoCtlColorProfile::createColorConversionProgram(const KoColorSpace* _srcCs, const KoColorSpace* _dstCs) const
145
 
{
146
 
    KisGtlLocker gtlLocker;
147
 
    QString srcModelId = _srcCs->colorModelId().id();
148
 
    QString srcDepthId = _srcCs->colorDepthId().id();
149
 
    QString dstModelId = _dstCs->colorModelId().id();
150
 
    QString dstDepthId = _dstCs->colorDepthId().id();
151
 
    foreach(ConversionInfo info, d->conversionInfos) {
152
 
        if (info.sourceColorModelID == srcModelId
153
 
                && (info.sourceColorDepthID == srcDepthId || (info.sourceColorDepthID == "F"
154
 
                        && (srcDepthId == Float16BitsColorDepthID.id() || srcDepthId == Float32BitsColorDepthID.id())))
155
 
                && info.destinationColorModelID == dstModelId
156
 
                && (info.destinationColorDepthID == dstDepthId || (info.destinationColorDepthID == "F"
157
 
                        && (dstDepthId == Float16BitsColorDepthID.id() || dstDepthId == Float32BitsColorDepthID.id())))) {
158
 
            GTLCore::PixelDescription srcPixelDescription = createPixelDescription(_srcCs);
159
 
            GTLCore::PixelDescription dstPixelDescription = createPixelDescription(_dstCs);
160
 
            return new OpenCTL::Program(info.function.toAscii().data(), d->module, srcPixelDescription, dstPixelDescription);
161
 
        }
162
 
    }
163
 
    return 0;
164
 
}
165
 
 
166
 
QList<KoColorConversionTransformationFactory*> KoCtlColorProfile::createColorConversionTransformationFactories() const
167
 
{
168
 
    dbgPlugins << "createColorConversionTransformationFactories() " << d->conversionInfos.size();
169
 
    QList<KoColorConversionTransformationFactory*> factories;
170
 
    foreach(ConversionInfo info, d->conversionInfos) {
171
 
        dbgPlugins << info.destinationColorModelID << " " << info.destinationColorDepthID << " " << info.destinationProfile << " " << info.sourceColorModelID << " " << info.sourceColorDepthID << " " << info.sourceProfile << " " << info.function;
172
 
        if (info.sourceColorDepthID == "F" && info.destinationColorDepthID == "F") {
173
 
            factories.push_back(
174
 
                new KoCtlColorConversionTransformationFactory(
175
 
                    info.sourceColorModelID, Float16BitsColorDepthID.id(), info.sourceProfile,
176
 
                    info.destinationColorModelID, Float16BitsColorDepthID.id(), info.destinationProfile));
177
 
            factories.push_back(
178
 
                new KoCtlColorConversionTransformationFactory(
179
 
                    info.sourceColorModelID, Float32BitsColorDepthID.id(), info.sourceProfile,
180
 
                    info.destinationColorModelID, Float32BitsColorDepthID.id(), info.destinationProfile));
181
 
        } else if (info.sourceColorDepthID == "F") {
182
 
            factories.push_back(
183
 
                new KoCtlColorConversionTransformationFactory(
184
 
                    info.sourceColorModelID, Float16BitsColorDepthID.id(),
185
 
                    info.sourceProfile, info.destinationColorModelID, info.destinationColorDepthID,
186
 
                    info.destinationProfile));
187
 
            factories.push_back(
188
 
                new KoCtlColorConversionTransformationFactory(
189
 
                    info.sourceColorModelID, Float32BitsColorDepthID.id(),
190
 
                    info.sourceProfile, info.destinationColorModelID, info.destinationColorDepthID,
191
 
                    info.destinationProfile));
192
 
        } else if (info.destinationColorDepthID == "F") {
193
 
            factories.push_back(
194
 
                new KoCtlColorConversionTransformationFactory(
195
 
                    info.sourceColorModelID, info.sourceColorDepthID,
196
 
                    info.sourceProfile, info.destinationColorModelID, Float16BitsColorDepthID.id(),
197
 
                    info.destinationProfile));
198
 
            factories.push_back(
199
 
                new KoCtlColorConversionTransformationFactory(
200
 
                    info.sourceColorModelID, info.sourceColorDepthID,
201
 
                    info.sourceProfile, info.destinationColorModelID, Float32BitsColorDepthID.id(),
202
 
                    info.destinationProfile));
203
 
        } else {
204
 
            factories.push_back(
205
 
                new KoCtlColorConversionTransformationFactory(
206
 
                    info.sourceColorModelID, info.sourceColorDepthID,
207
 
                    info.sourceProfile, info.destinationColorModelID, info.destinationColorDepthID,
208
 
                    info.destinationProfile));
209
 
        }
210
 
    }
211
 
    return factories;
212
 
}
213
 
 
214
 
bool KoCtlColorProfile::operator==(const KoColorProfile& p) const
215
 
{
216
 
    const KoCtlColorProfile* ctlp = dynamic_cast<const KoCtlColorProfile*>(&p);
217
 
    if (ctlp) {
218
 
        return ctlp->name() == name() && ctlp->d->colorModelIDNumber == d->colorModelIDNumber && ctlp->d->colorDepthIDNumber == d->colorDepthIDNumber;
219
 
    } else {
220
 
        return false;
221
 
    }
222
 
}
223
 
 
224
 
QString KoCtlColorProfile::colorModel() const
225
 
{
226
 
    return d->colorModelID;
227
 
}
228
 
 
229
 
QString KoCtlColorProfile::colorDepth() const
230
 
{
231
 
    return d->colorDepthID;
232
 
}
233
 
 
234
 
void KoCtlColorProfile::decodeTransformations(QDomElement& elt)
235
 
{
236
 
    dbgPlugins << "decodeTransformations " << elt.tagName();
237
 
    for (QDomNode nt = elt.firstChild(); !nt.isNull(); nt = nt.nextSibling()) {
238
 
        QDomElement et = nt.toElement();
239
 
        if (!et.isNull()) {
240
 
            dbgPigment << et.tagName();
241
 
            if (et.tagName() == "conversions") {
242
 
                decodeConversions(et);
243
 
            }
244
 
        }
245
 
    }
246
 
}
247
 
 
248
 
void KoCtlColorProfile::decodeConversions(QDomElement& elt)
249
 
{
250
 
    dbgPlugins << "decodeConversions " << elt.tagName() << " " << elt.childNodes().count();
251
 
    for (QDomNode n = elt.firstChild(); !n.isNull(); n = n.nextSibling()) {
252
 
        QDomElement e = n.toElement();
253
 
        if (!e.isNull()) {
254
 
            dbgPigment << e.tagName();
255
 
            if (e.tagName() == "conversion") {
256
 
                QDomElement eIn = e.firstChildElement("input");
257
 
                QDomElement eOut = e.firstChildElement("output");
258
 
                if (!eIn.isNull() && !eOut.isNull()) {
259
 
                    ConversionInfo ci;
260
 
                    ci.function = e.attribute("function");
261
 
                    ci.sourceColorModelID = eIn.attribute("colorModel");
262
 
                    ci.sourceColorDepthID = KoCtlParser::generateDepthID(eIn.attribute("depth"), eIn.attribute("type")).id();
263
 
                    ci.sourceProfile = eIn.attribute("profile");
264
 
                    ci.destinationColorModelID = eOut.attribute("colorModel");
265
 
                    ci.destinationColorDepthID = KoCtlParser::generateDepthID(eOut.attribute("depth"), eOut.attribute("type")).id();
266
 
                    ci.destinationProfile = eOut.attribute("profile");
267
 
                    if (ci.sourceColorModelID == colorModel() && ci.sourceColorDepthID == colorDepth() && ci.sourceProfile.isEmpty()) {
268
 
                        ci.sourceProfile = name();
269
 
                        d->conversionInfos.push_back(ci);
270
 
                    } else if (ci.destinationColorModelID == colorModel() && ci.destinationColorDepthID == colorDepth() && ci.destinationProfile.isEmpty()) {
271
 
                        ci.destinationProfile = name();
272
 
                        d->conversionInfos.push_back(ci);
273
 
                    } else {
274
 
                        Q_ASSERT(ci.destinationProfile == name() || ci.sourceProfile == name());
275
 
                        d->conversionInfos.push_back(ci);
276
 
                    }
277
 
                } else {
278
 
                    dbgPigment << "Invalid conversion, missing <input> or <output> or both";
279
 
                }
280
 
            }
281
 
        }
282
 
    }
283
 
    dbgPigment << d->conversionInfos.size() << " convertions were found";
284
 
}
285
 
 
286
 
bool KoCtlColorProfile::load()
287
 
{
288
 
    QFile file(fileName());
289
 
    if (!file.open(QIODevice::ReadOnly)) {
290
 
        dbgPigment << "Can't open file : " << fileName();
291
 
        return false;
292
 
    }
293
 
    d->profileSource = file.readAll();
294
 
    file.close();
295
 
    return d->loadFromSource(this);
296
 
}
297
 
 
298
 
bool KoCtlColorProfile::Private::loadFromSource(KoCtlColorProfile* self)
299
 
{
300
 
    QDomDocument doc;
301
 
    QString errorMsg;
302
 
    int errorLine;
303
 
    if (!doc.setContent(profileSource, &errorMsg, &errorLine)) {
304
 
        dbgPigment << "Can't parse profile : " << self->fileName() << " Error at line " << errorLine << " " << errorMsg;
305
 
        return false;
306
 
    }
307
 
    QDomElement docElem = doc.documentElement();
308
 
    if (docElem.tagName() != "ctlprofile") {
309
 
        dbgPigment << "Not a ctlprofile, root tag was : " << docElem.tagName();
310
 
        return false;
311
 
    }
312
 
    QDomNode n = docElem.firstChild();
313
 
    while (!n.isNull()) {
314
 
        QDomElement e = n.toElement();
315
 
        if (!e.isNull()) {
316
 
            dbgPigment << e.tagName();
317
 
            if (e.tagName() == "info") {
318
 
                self->setName(e.attribute("name"));
319
 
                colorDepthID = KoCtlParser::generateDepthID(e.attribute("depth"), e.attribute("type")).id();
320
 
                colorDepthIDNumber = KoUniqueNumberForIdServer::instance()->numberForId(colorDepthID);
321
 
                colorModelID = e.attribute("colorModel");
322
 
                colorModelIDNumber = KoUniqueNumberForIdServer::instance()->numberForId(colorModelID);
323
 
                dbgPigment << "colorModel = " << e.attribute("colorModel");
324
 
            } else if (e.tagName() == "program") {
325
 
                QDomNode nCDATA = e.firstChild();
326
 
                if (!nCDATA.isNull()) {
327
 
                    QMutexLocker lock(ctlMutex);
328
 
                    QDomCDATASection CDATA = nCDATA.toCDATASection();
329
 
                    dbgPigment << CDATA.data();
330
 
                    module = new OpenCTL::Module();
331
 
                    module->setSource(self->name().toAscii().data(), CDATA.data().toAscii().data());
332
 
                    module->compile();
333
 
#if GTL_CORE_VERSION_MAJOR == 0 && GTL_CORE_VERSION_MINOR == 9 && GTL_CORE_VERSION_REVISION > 12
334
 
                    if (!module->isCompiled()) {
335
 
                        dbgKrita << module->compilationMessages().toString().c_str();
336
 
                    }
337
 
#endif
338
 
                }
339
 
            } else if (e.tagName() == "transformations") {
340
 
                self->decodeTransformations(e);
341
 
            }
342
 
        }
343
 
        n = n.nextSibling();
344
 
    }
345
 
    return true;
346
 
}
347
 
 
348
 
bool KoCtlColorProfile::save(const QString &fileName)
349
 
{
350
 
    QFile file(fileName);
351
 
    if (!file.open(QIODevice::WriteOnly)) {
352
 
        dbgPigment << "Can't open file : " << fileName;
353
 
        return false;
354
 
    }
355
 
    file.write(d->profileSource.toUtf8());
356
 
    file.close();
357
 
    return true;
358
 
}
359
 
 
360
 
QByteArray KoCtlColorProfile::rawData() const
361
 
{
362
 
    return d->profileSource.toUtf8();
363
 
}
364
 
 
365
 
QVariant KoCtlColorProfile::property(const QString& _name) const
366
 
{
367
 
    if (_name == "exposure") {
368
 
        return d->exposure;
369
 
    } else {
370
 
        dbgPigment << "Not CTL property " << _name;
371
 
        return KoColorProfile::property(_name);
372
 
    }
373
 
}
374
 
 
375
 
void KoCtlColorProfile::setProperty(const QString& _name, const QVariant& _variant)
376
 
{
377
 
    if (_name == "exposure") {
378
 
        d->exposure = pow(2, _variant.toDouble() + 2.47393) * d->middleGrayScaleFactor;
379
 
    } else {
380
 
        dbgPigment << "Not CTL property " << _name;
381
 
        return KoColorProfile::setProperty(_name, _variant);
382
 
    }
383
 
}