~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to libs/pigment/KoLcmsColorSpace.h

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (c) 2002 Patrick Julien  <freak@codepimps.org>
3
 
 *  Copyright (c) 2005-2006 Casper Boemann <cbr@boemann.dk>
4
 
 *  Copyright (c) 2004,2006-2007 Cyrille Berger <cberger@cberger.net>
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public License
17
 
 * along with this library; see the file COPYING.LIB.  If not, write to
18
 
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
 
 * Boston, MA 02110-1301, USA.
20
 
 */
21
 
 
22
 
#ifndef KOLCMSCOLORSPACE_H_
23
 
#define KOLCMSCOLORSPACE_H_
24
 
 
25
 
#include <kconfig.h>
26
 
#include <kglobal.h>
27
 
 
28
 
#include <colorprofiles/KoLcmsColorProfileContainer.h>
29
 
#include <KoColorSpaceAbstract.h>
30
 
#include <KoColorSpaceRegistry.h>
31
 
 
32
 
#include "pigment_export.h"
33
 
class qDebug;
34
 
 
35
 
class KoLcmsInfo {
36
 
    struct Private {
37
 
        DWORD cmType;  // The colorspace type as defined by littlecms
38
 
        icColorSpaceSignature colorSpaceSignature; // The colorspace signature as defined in icm/icc files
39
 
    };
40
 
public:
41
 
    KoLcmsInfo(DWORD cmType, icColorSpaceSignature colorSpaceSignature) : d(new Private)
42
 
    {
43
 
        d->cmType = cmType;
44
 
        d->colorSpaceSignature = colorSpaceSignature;
45
 
    }
46
 
    virtual ~KoLcmsInfo()
47
 
    {
48
 
        delete d;
49
 
    }
50
 
    virtual quint32 colorSpaceType() const
51
 
    {
52
 
        return d->cmType;
53
 
    }
54
 
 
55
 
    virtual icColorSpaceSignature colorSpaceSignature() const
56
 
    {
57
 
        return d->colorSpaceSignature;
58
 
    }
59
 
private:
60
 
    Private* const d;
61
 
};
62
 
 
63
 
struct PIGMENTCMS_EXPORT KoLcmsDefaultTransformations {
64
 
    cmsHTRANSFORM toRGB;
65
 
    cmsHTRANSFORM fromRGB;
66
 
    static cmsHPROFILE s_RGBProfile;
67
 
    static QMap< QString, QMap< KoLcmsColorProfileContainer*, KoLcmsDefaultTransformations* > > s_transformations;
68
 
};
69
 
 
70
 
/**
71
 
 * This is the base class for all colorspaces that are based on the lcms library, for instance
72
 
 * RGB 8bits and 16bits, CMYK 8bits and 16bits, LAB...
73
 
 */
74
 
template<class _CSTraits>
75
 
class KoLcmsColorSpace : public KoColorSpaceAbstract<_CSTraits>, public KoLcmsInfo {
76
 
    struct KoLcmsColorTransformation : public KoColorTransformation
77
 
    {
78
 
        KoLcmsColorTransformation(const KoColorSpace* colorSpace) : KoColorTransformation(), m_colorSpace(colorSpace)
79
 
        {
80
 
            csProfile = 0;
81
 
            cmstransform = 0;
82
 
            profiles[0] = 0;
83
 
            profiles[1] = 0;
84
 
            profiles[2] = 0;
85
 
        }
86
 
 
87
 
        ~KoLcmsColorTransformation() {
88
 
 
89
 
            if (cmstransform)
90
 
                cmsDeleteTransform(cmstransform);
91
 
            if (profiles[0] && profiles[0] != csProfile)
92
 
                cmsCloseProfile(profiles[0]);
93
 
            if(profiles[1] && profiles[1] != csProfile)
94
 
                cmsCloseProfile(profiles[1]);
95
 
            if(profiles[2] && profiles[2] != csProfile)
96
 
                cmsCloseProfile(profiles[2]);
97
 
        }
98
 
 
99
 
        virtual void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const
100
 
        {
101
 
            cmsDoTransform(cmstransform, const_cast<quint8 *>(src), dst, nPixels);
102
 
            qint32 numPixels = nPixels;
103
 
            qint32 pixelSize = m_colorSpace->pixelSize();
104
 
            while (numPixels > 0) {
105
 
                quint8 alpha = m_colorSpace->alpha(src);
106
 
                m_colorSpace->setAlpha(dst, alpha, 1);
107
 
 
108
 
                src += pixelSize;
109
 
                dst += pixelSize;
110
 
                numPixels--;
111
 
            }
112
 
        }
113
 
 
114
 
        const KoColorSpace* m_colorSpace;
115
 
        cmsHPROFILE csProfile;
116
 
        cmsHPROFILE profiles[3];
117
 
        cmsHTRANSFORM cmstransform;
118
 
    };
119
 
 
120
 
    struct Private {
121
 
        mutable quint8 * qcolordata; // A small buffer for conversion from and to qcolor.
122
 
        KoLcmsDefaultTransformations* defaultTransformations;
123
 
 
124
 
        mutable cmsHPROFILE   lastRGBProfile;  // Last used profile to transform to/from RGB
125
 
        mutable cmsHTRANSFORM lastToRGB;       // Last used transform to transform to RGB
126
 
        mutable cmsHTRANSFORM lastFromRGB;     // Last used transform to transform from RGB
127
 
        KoLcmsColorProfileContainer *  profile;
128
 
        KoColorProfile* colorProfile;
129
 
    };
130
 
 
131
 
protected:
132
 
 
133
 
    KoLcmsColorSpace(const QString &id, const QString &name,  DWORD cmType,
134
 
                     icColorSpaceSignature colorSpaceSignature,
135
 
                     KoColorProfile *p)
136
 
        : KoColorSpaceAbstract<_CSTraits>(id, name), KoLcmsInfo( cmType, colorSpaceSignature)
137
 
        , d( new Private())
138
 
 
139
 
    {
140
 
        Q_ASSERT(p); // No profile means the lcms color space can't work
141
 
        Q_ASSERT(profileIsCompatible(p));
142
 
        d->profile = asLcmsProfile(p);
143
 
        Q_ASSERT( d->profile );
144
 
        d->colorProfile = p;
145
 
        d->qcolordata = 0;
146
 
        d->lastRGBProfile = 0;
147
 
        d->lastToRGB = 0;
148
 
        d->lastFromRGB = 0;
149
 
        d->defaultTransformations = 0;
150
 
    }
151
 
 
152
 
    virtual ~KoLcmsColorSpace()
153
 
    {
154
 
/*            cmsCloseProfile(d->lastFromRGB);
155
 
              cmsDeleteTransform( d->defaultFromRGB );
156
 
              cmsDeleteTransform( d->defaultToRGB );*/
157
 
        delete d->colorProfile;
158
 
        delete[] d->qcolordata;
159
 
        delete d;
160
 
    }
161
 
 
162
 
    void init()
163
 
    {
164
 
        // Default pixel buffer for QColor conversion
165
 
        d->qcolordata = new quint8[3];
166
 
        Q_CHECK_PTR(d->qcolordata);
167
 
 
168
 
        Q_ASSERT(d->profile );
169
 
 
170
 
        if( KoLcmsDefaultTransformations::s_RGBProfile == 0 )
171
 
        {
172
 
            KoLcmsDefaultTransformations::s_RGBProfile = cmsCreate_sRGBProfile();
173
 
        }
174
 
        d->defaultTransformations = KoLcmsDefaultTransformations::s_transformations[ this->id() ][ d->profile ];
175
 
        if( not d->defaultTransformations )
176
 
        {
177
 
            d->defaultTransformations = new KoLcmsDefaultTransformations;
178
 
            d->defaultTransformations->fromRGB = cmsCreateTransform(KoLcmsDefaultTransformations::s_RGBProfile,
179
 
                                                                    TYPE_BGR_8,
180
 
                                                                    d->profile->lcmsProfile(),
181
 
                                                                    this->colorSpaceType(),
182
 
                                                                    INTENT_PERCEPTUAL,
183
 
                                                                    0);
184
 
            d->defaultTransformations->toRGB = cmsCreateTransform(d->profile->lcmsProfile(), this->colorSpaceType(),
185
 
                                                                  KoLcmsDefaultTransformations::s_RGBProfile, TYPE_BGR_8,
186
 
                                                                  INTENT_PERCEPTUAL, 0);
187
 
            KoLcmsDefaultTransformations::s_transformations[ this->id() ][ d->profile ] = d->defaultTransformations;
188
 
        }
189
 
        // For conversions from default rgb
190
 
//             d->lastFromRGB = cmsCreate_sRGBProfile();
191
 
//
192
 
//             d->defaultFromRGB = cmsCreateTransform(d->lastFromRGB, TYPE_BGR_8,
193
 
//                     d->profile->lcmsProfile(), this->colorSpaceType(),
194
 
//                     INTENT_PERCEPTUAL, 0);
195
 
//
196
 
//             d->defaultToRGB =  cmsCreateTransform(d->profile->lcmsProfile(), this->colorSpaceType(),
197
 
//                     d->lastFromRGB, TYPE_BGR_8,
198
 
//                     INTENT_PERCEPTUAL, 0);
199
 
 
200
 
    }
201
 
public:
202
 
 
203
 
    virtual bool hasHighDynamicRange() const { return false; }
204
 
    virtual const KoColorProfile * profile() const { return d->colorProfile; }
205
 
    virtual KoColorProfile * profile() { return d->colorProfile; }
206
 
 
207
 
    virtual bool profileIsCompatible(const KoColorProfile* profile) const
208
 
    {
209
 
        const KoIccColorProfile* p = dynamic_cast<const KoIccColorProfile*>(profile);
210
 
        return (p && p->asLcms()->colorSpaceSignature() == colorSpaceSignature());
211
 
    }
212
 
 
213
 
    virtual void fromQColor(const QColor& color, quint8 *dst, const KoColorProfile * koprofile=0) const
214
 
    {
215
 
        d->qcolordata[2] = color.red();
216
 
        d->qcolordata[1] = color.green();
217
 
        d->qcolordata[0] = color.blue();
218
 
 
219
 
        KoLcmsColorProfileContainer* profile = asLcmsProfile(koprofile);
220
 
        if (profile == 0) {
221
 
            // Default sRGB
222
 
            Q_ASSERT(d->defaultTransformations and d->defaultTransformations->fromRGB);
223
 
 
224
 
            cmsDoTransform(d->defaultTransformations->fromRGB, d->qcolordata, dst, 1);
225
 
        }
226
 
        else {
227
 
            if (d->lastFromRGB == 0 || (d->lastFromRGB != 0 && d->lastRGBProfile != profile->lcmsProfile())) {
228
 
                d->lastFromRGB = cmsCreateTransform(profile->lcmsProfile(), TYPE_BGR_8,
229
 
                                                    d->profile->lcmsProfile(), this->colorSpaceType(),
230
 
                                                    INTENT_PERCEPTUAL, 0);
231
 
                d->lastRGBProfile = profile->lcmsProfile();
232
 
 
233
 
            }
234
 
            cmsDoTransform(d->lastFromRGB, d->qcolordata, dst, 1);
235
 
        }
236
 
 
237
 
        this->setAlpha(dst, color.alpha() , 1);
238
 
    }
239
 
 
240
 
    virtual void toQColor(const quint8 *src, QColor *c, const KoColorProfile * koprofile =0) const
241
 
    {
242
 
        KoLcmsColorProfileContainer* profile = asLcmsProfile(koprofile);
243
 
        if (profile == 0) {
244
 
            // Default sRGB transform
245
 
            Q_ASSERT(d->defaultTransformations and d->defaultTransformations->toRGB);
246
 
            cmsDoTransform(d->defaultTransformations->toRGB, const_cast <quint8 *>(src), d->qcolordata, 1);
247
 
        }
248
 
        else {
249
 
            if (d->lastToRGB == 0 || (d->lastToRGB != 0 && d->lastRGBProfile != profile->lcmsProfile())) {
250
 
                d->lastToRGB = cmsCreateTransform(d->profile->lcmsProfile(), this->colorSpaceType(),
251
 
                                                  profile->lcmsProfile(), TYPE_BGR_8,
252
 
                                                  INTENT_PERCEPTUAL, 0);
253
 
                d->lastRGBProfile = profile->lcmsProfile();
254
 
            }
255
 
            cmsDoTransform(d->lastToRGB, const_cast <quint8 *>(src), d->qcolordata, 1);
256
 
        }
257
 
        c->setRgb(d->qcolordata[2], d->qcolordata[1], d->qcolordata[0]);
258
 
        c->setAlpha( this->alpha(src) );
259
 
    }
260
 
 
261
 
    virtual KoColorTransformation *createBrightnessContrastAdjustment(const quint16 *transferValues) const
262
 
    {
263
 
        if (!d->profile) return 0;
264
 
 
265
 
        LPGAMMATABLE transferFunctions[3];
266
 
        transferFunctions[0] = cmsBuildGamma(256, 1.0);
267
 
        transferFunctions[1] = cmsBuildGamma(256, 1.0);
268
 
        transferFunctions[2] = cmsBuildGamma(256, 1.0);
269
 
 
270
 
        for(int i =0; i < 256; i++)
271
 
            transferFunctions[0]->GammaTable[i] = transferValues[i];
272
 
 
273
 
        KoLcmsColorTransformation *adj = new KoLcmsColorTransformation(this);
274
 
        adj->profiles[1] = cmsCreateLinearizationDeviceLink(icSigLabData, transferFunctions);
275
 
        cmsSetDeviceClass(adj->profiles[1], icSigAbstractClass);
276
 
 
277
 
        adj->profiles[0] = d->profile->lcmsProfile();
278
 
        adj->profiles[2] = d->profile->lcmsProfile();
279
 
        adj->cmstransform  = cmsCreateMultiprofileTransform(adj->profiles, 3, this->colorSpaceType(), this->colorSpaceType(), INTENT_PERCEPTUAL, cmsFLAGS_NOWHITEONWHITEFIXUP);
280
 
        adj->csProfile = d->profile->lcmsProfile();
281
 
        return adj;
282
 
    }
283
 
 
284
 
 
285
 
    virtual KoColorTransformation *createDesaturateAdjustment() const
286
 
    {
287
 
        if (!d->profile) return 0;
288
 
 
289
 
        KoLcmsColorTransformation *adj = new KoLcmsColorTransformation(this);
290
 
 
291
 
        adj->profiles[0] = d->profile->lcmsProfile();
292
 
        adj->profiles[2] = d->profile->lcmsProfile();
293
 
        adj->csProfile = d->profile->lcmsProfile();
294
 
 
295
 
        LPLUT Lut;
296
 
        BCHSWADJUSTS bchsw;
297
 
 
298
 
        bchsw.Saturation = -25;
299
 
 
300
 
        adj->profiles[1] = _cmsCreateProfilePlaceholder();
301
 
        if (!adj->profiles[1]) { // can't allocate
302
 
            delete adj;
303
 
            return NULL;
304
 
        }
305
 
 
306
 
        cmsSetDeviceClass(adj->profiles[1], icSigAbstractClass);
307
 
        cmsSetColorSpace(adj->profiles[1], icSigLabData);
308
 
        cmsSetPCS(adj->profiles[1], icSigLabData);
309
 
 
310
 
        cmsSetRenderingIntent(adj->profiles[1], INTENT_PERCEPTUAL);
311
 
 
312
 
        // Creates a LUT with 3D grid only
313
 
        Lut = cmsAllocLUT();
314
 
 
315
 
        cmsAlloc3DGrid(Lut, 32, 3, 3);
316
 
 
317
 
        if (!cmsSample3DGrid(Lut, desaturateSampler, static_cast<LPVOID>(&bchsw), 0)) {
318
 
            // Shouldn't reach here
319
 
            cmsFreeLUT(Lut);
320
 
            cmsCloseProfile(adj->profiles[1]);
321
 
            delete adj;
322
 
            return NULL;
323
 
        }
324
 
 
325
 
        // Create tags
326
 
 
327
 
        cmsAddTag(adj->profiles[1], icSigDeviceMfgDescTag,      (LPVOID) "(krita internal)");
328
 
        cmsAddTag(adj->profiles[1], icSigProfileDescriptionTag, (LPVOID) "krita saturation abstract profile");
329
 
        cmsAddTag(adj->profiles[1], icSigDeviceModelDescTag,    (LPVOID) "saturation built-in");
330
 
 
331
 
        cmsAddTag(adj->profiles[1], icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
332
 
 
333
 
        cmsAddTag(adj->profiles[1], icSigAToB0Tag, (LPVOID) Lut);
334
 
 
335
 
        // LUT is already on virtual profile
336
 
        cmsFreeLUT(Lut);
337
 
 
338
 
        adj->cmstransform  = cmsCreateMultiprofileTransform(adj->profiles, 3, this->colorSpaceType(), this->colorSpaceType(), INTENT_PERCEPTUAL, cmsFLAGS_NOWHITEONWHITEFIXUP);
339
 
 
340
 
        return adj;
341
 
    }
342
 
 
343
 
    virtual KoColorTransformation *createPerChannelAdjustment(const quint16 * const*transferValues) const
344
 
    {
345
 
        if (!d->profile) return 0;
346
 
 
347
 
        LPGAMMATABLE *transferFunctions = new LPGAMMATABLE[ _CSTraits::channels_nb +1];
348
 
 
349
 
        for(uint ch=0; ch < this->colorChannelCount(); ch++) {
350
 
            transferFunctions[ch] = cmsBuildGamma(256, 1.0);
351
 
            for(uint i =0; i < 256; i++) {
352
 
                transferFunctions[ch]->GammaTable[i] = transferValues[ch][i];
353
 
            }
354
 
        }
355
 
 
356
 
        KoLcmsColorTransformation *adj = new KoLcmsColorTransformation(this);
357
 
        adj->profiles[0] = cmsCreateLinearizationDeviceLink(this->colorSpaceSignature(), transferFunctions);
358
 
        adj->profiles[1] = NULL;
359
 
        adj->profiles[2] = NULL;
360
 
        adj->csProfile = d->profile->lcmsProfile();
361
 
        adj->cmstransform  = cmsCreateTransform(adj->profiles[0], this->colorSpaceType(), NULL, this->colorSpaceType(), INTENT_PERCEPTUAL, 0);
362
 
 
363
 
        delete [] transferFunctions;
364
 
 
365
 
        return adj;
366
 
    }
367
 
 
368
 
    virtual quint8 difference(const quint8* src1, const quint8* src2) const
369
 
    {
370
 
        quint8 lab1[8], lab2[8];
371
 
        cmsCIELab labF1, labF2;
372
 
 
373
 
        if (this->alpha(src1) == OPACITY_TRANSPARENT || this->alpha(src2) == OPACITY_TRANSPARENT)
374
 
            return (this->alpha(src1) == this->alpha(src2) ? 0 : 255);
375
 
        Q_ASSERT(this->toLabA16Converter());
376
 
        this->toLabA16Converter()->transform( src1, lab1, 1),
377
 
            this->toLabA16Converter()->transform( src2, lab2, 1),
378
 
            cmsLabEncoded2Float(&labF1, (WORD *)lab1);
379
 
        cmsLabEncoded2Float(&labF2, (WORD *)lab2);
380
 
        qreal diff = cmsDeltaE(&labF1, &labF2);
381
 
        if(diff>255)
382
 
            return 255;
383
 
        else
384
 
            return qint8(diff);
385
 
    }
386
 
 
387
 
private:
388
 
 
389
 
    inline KoLcmsColorProfileContainer* lcmsProfile() const {
390
 
        return d->profile;
391
 
    }
392
 
 
393
 
    inline static KoLcmsColorProfileContainer* asLcmsProfile(const KoColorProfile* p)
394
 
    {
395
 
        if(!p) return 0;
396
 
 
397
 
        const KoIccColorProfile* iccp = dynamic_cast<const KoIccColorProfile*>(p);
398
 
 
399
 
        if( !iccp )
400
 
        {
401
 
            return 0;
402
 
        }
403
 
 
404
 
        Q_ASSERT(iccp->asLcms());
405
 
 
406
 
        return iccp->asLcms();
407
 
    }
408
 
 
409
 
    typedef struct {
410
 
        qreal Saturation;
411
 
 
412
 
    } BCHSWADJUSTS, *LPBCHSWADJUSTS;
413
 
 
414
 
 
415
 
    static int desaturateSampler(register WORD In[], register WORD Out[], register LPVOID /*Cargo*/)
416
 
    {
417
 
        cmsCIELab LabIn, LabOut;
418
 
        cmsCIELCh LChIn, LChOut;
419
 
        //LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo;
420
 
 
421
 
        cmsLabEncoded2Float(&LabIn, In);
422
 
 
423
 
        cmsLab2LCh(&LChIn, &LabIn);
424
 
 
425
 
        // Do some adjusts on LCh
426
 
        LChOut.L = LChIn.L;
427
 
        LChOut.C = 0;//LChIn.C + bchsw->Saturation;
428
 
        LChOut.h = LChIn.h;
429
 
 
430
 
        cmsLCh2Lab(&LabOut, &LChOut);
431
 
 
432
 
        // Back to encoded
433
 
        cmsFloat2LabEncoded(Out, &LabOut);
434
 
 
435
 
        return true;
436
 
    }
437
 
    Private * const d;
438
 
};
439
 
 
440
 
class PIGMENTCMS_EXPORT KoLcmsColorSpaceFactory : public KoColorSpaceFactory, private KoLcmsInfo {
441
 
public:
442
 
    KoLcmsColorSpaceFactory(DWORD cmType, icColorSpaceSignature colorSpaceSignature) : KoLcmsInfo(cmType, colorSpaceSignature)
443
 
    {
444
 
    }
445
 
    virtual bool profileIsCompatible(const KoColorProfile* profile) const
446
 
    {
447
 
        const KoIccColorProfile* p = dynamic_cast<const KoIccColorProfile*>(profile);
448
 
        return (p && p->asLcms()->colorSpaceSignature() == colorSpaceSignature());
449
 
    }
450
 
    virtual QString colorSpaceEngine() const { return "icc"; }
451
 
    virtual bool isHdr() const { return false; }
452
 
    virtual QList<KoColorConversionTransformationFactory*> colorConversionLinks() const;
453
 
};
454
 
 
455
 
#endif