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

« back to all changes in this revision

Viewing changes to libs/pigment/KoColorSpace.cpp

  • 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:
40
40
#include "KoColorSpace_p.h"
41
41
 
42
42
KoColorSpace::KoColorSpace()
43
 
    : d (new Private())
 
43
        : d(new Private())
44
44
{
45
45
}
46
46
 
47
 
KoColorSpace::KoColorSpace(const QString &id, const QString &name, KoMixColorsOp* mixColorsOp, KoConvolutionOp* convolutionOp )
48
 
    : d (new Private())
 
47
KoColorSpace::KoColorSpace(const QString &id, const QString &name, KoMixColorsOp* mixColorsOp, KoConvolutionOp* convolutionOp)
 
48
        : d(new Private())
49
49
{
50
50
    d->id = id;
51
 
    d->idNumber = KoUniqueNumberForIdServer::instance()->numberForId( d->id );
 
51
    d->idNumber = KoUniqueNumberForIdServer::instance()->numberForId(d->id);
52
52
    d->name = name;
53
53
    d->mixColorsOp = mixColorsOp;
54
54
    d->convolutionOp = convolutionOp;
64
64
    Q_ASSERT(d->deletability != OwnedByRegistryDoNotDelete);
65
65
 
66
66
    qDeleteAll(d->compositeOps);
67
 
    foreach(KoChannelInfo * channel, d->channels)
68
 
    {
 
67
    foreach(KoChannelInfo * channel, d->channels) {
69
68
        delete channel;
70
69
    }
71
70
    if (d->deletability == NotOwnedByRegistry) {
76
75
    }
77
76
    delete d->mixColorsOp;
78
77
    delete d->convolutionOp;
 
78
    delete d->transfoToRGBA16;
 
79
    delete d->transfoFromRGBA16;
 
80
    delete d->transfoToLABA16;
 
81
    delete d->transfoFromLABA16;
79
82
    delete d;
80
83
}
81
84
 
82
 
bool KoColorSpace::operator==(const KoColorSpace& rhs) const {
 
85
bool KoColorSpace::operator==(const KoColorSpace& rhs) const
 
86
{
83
87
    const KoColorProfile* p1 = rhs.profile();
84
88
    const KoColorProfile* p2 = profile();
85
 
    return d->idNumber == rhs.d->idNumber && ((p1 == p2) || (*p1 == *p2 ));
86
 
}
87
 
 
88
 
QString KoColorSpace::id() const {return d->id;}
89
 
 
90
 
QString KoColorSpace::name() const {return d->name;}
 
89
    return d->idNumber == rhs.d->idNumber && ((p1 == p2) || (*p1 == *p2));
 
90
}
 
91
 
 
92
QString KoColorSpace::id() const
 
93
{
 
94
    return d->id;
 
95
}
 
96
 
 
97
QString KoColorSpace::name() const
 
98
{
 
99
    return d->name;
 
100
}
91
101
 
92
102
QList<KoChannelInfo *> KoColorSpace::channels() const
93
103
{
96
106
 
97
107
QBitArray KoColorSpace::channelFlags(bool color, bool alpha, bool substance, bool substrate) const
98
108
{
99
 
    QBitArray ba( d->channels.size() );
100
 
    if ( !color && !alpha && !substance && !substrate ) return ba;
 
109
    QBitArray ba(d->channels.size());
 
110
    if (!color && !alpha && !substance && !substrate) return ba;
101
111
 
102
 
    for ( int i = 0; i < d->channels.size(); ++i ) {
103
 
        KoChannelInfo * channel = d->channels.at( i );
104
 
        if ( ( color && channel->channelType() == KoChannelInfo::COLOR ) ||
105
 
             ( alpha && channel->channelType() == KoChannelInfo::ALPHA ) ||
106
 
             ( substrate && channel->channelType() == KoChannelInfo::SUBSTRATE ) ||
107
 
             ( substance && channel->channelType() == KoChannelInfo::SUBSTANCE ) )
108
 
            ba.setBit( i, true );
 
112
    for (int i = 0; i < d->channels.size(); ++i) {
 
113
        KoChannelInfo * channel = d->channels.at(i);
 
114
        if ((color && channel->channelType() == KoChannelInfo::COLOR) ||
 
115
                (alpha && channel->channelType() == KoChannelInfo::ALPHA) ||
 
116
                (substrate && channel->channelType() == KoChannelInfo::SUBSTRATE) ||
 
117
                (substance && channel->channelType() == KoChannelInfo::SUBSTANCE))
 
118
            ba.setBit(channel->index(), true);
109
119
    }
110
120
    return ba;
111
121
}
112
122
 
113
 
QBitArray KoColorSpace::setChannelFlagsToPixelOrder(const QBitArray & origChannelFlags) const
114
 
{
115
 
    if ( origChannelFlags.isEmpty() ) return origChannelFlags;
116
 
 
117
 
    QBitArray orderedChannelFlags( origChannelFlags.size() );
118
 
    for ( int i = 0; i < origChannelFlags.size(); ++i ) {
119
 
 
120
 
        KoChannelInfo * channel = d->channels.at( i );
121
 
        orderedChannelFlags.setBit( channel->pos(), origChannelFlags.testBit( i ) );
122
 
    }
123
 
    return orderedChannelFlags;
124
 
}
125
 
 
126
 
QBitArray KoColorSpace::setChannelFlagsToColorSpaceOrder( const QBitArray & origChannelFlags ) const
127
 
{
128
 
    if ( origChannelFlags.isEmpty() ) return origChannelFlags;
129
 
 
130
 
    QBitArray orderedChannelFlags( origChannelFlags.size() );
131
 
    for ( int i = 0; i < orderedChannelFlags.size(); ++i )
132
 
    {
133
 
        KoChannelInfo * channel = d->channels.at( i );
134
 
        orderedChannelFlags.setBit( i, origChannelFlags.testBit( channel->pos() ) );
135
 
    }
136
 
    return orderedChannelFlags;
137
 
}
138
 
 
139
123
void KoColorSpace::addChannel(KoChannelInfo * ci)
140
124
{
141
125
    d->channels.push_back(ci);
159
143
}
160
144
 
161
145
 
162
 
KoMixColorsOp* KoColorSpace::mixColorsOp() const {
 
146
KoMixColorsOp* KoColorSpace::mixColorsOp() const
 
147
{
163
148
    return d->mixColorsOp;
164
149
}
165
150
 
166
151
 
167
 
KoConvolutionOp* KoColorSpace::convolutionOp() const {
 
152
KoConvolutionOp* KoColorSpace::convolutionOp() const
 
153
{
168
154
    return d->convolutionOp;
169
155
}
170
156
 
171
157
const KoCompositeOp * KoColorSpace::compositeOp(const QString & id) const
172
158
{
173
 
    if ( d->compositeOps.contains( id ) )
174
 
        return d->compositeOps.value( id );
 
159
    if (d->compositeOps.contains(id))
 
160
        return d->compositeOps.value(id);
175
161
    else {
176
162
        warnPigment << "Asking for non-existent composite operation " << id << ", returning " << COMPOSITE_OVER;
177
 
        return d->compositeOps.value( COMPOSITE_OVER );
 
163
        return d->compositeOps.value(COMPOSITE_OVER);
178
164
    }
179
165
}
180
166
 
181
167
void KoColorSpace::addCompositeOp(const KoCompositeOp * op)
182
168
{
183
 
    if ( op->colorSpace()->id() == id()) {
184
 
        d->compositeOps.insert( op->id(), const_cast<KoCompositeOp*>( op ) );
 
169
    if (op->colorSpace()->id() == id()) {
 
170
        d->compositeOps.insert(op->id(), const_cast<KoCompositeOp*>(op));
185
171
    }
186
172
}
187
173
 
188
174
const KoColorConversionTransformation* KoColorSpace::toLabA16Converter() const
189
175
{
190
 
    if(!d->transfoToLABA16)
191
 
    {
192
 
        d->transfoToLABA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(this, KoColorSpaceRegistry::instance()->lab16("") ) ;
 
176
    if (!d->transfoToLABA16) {
 
177
        d->transfoToLABA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(this, KoColorSpaceRegistry::instance()->lab16("")) ;
193
178
    }
194
179
    return d->transfoToLABA16;
195
180
}
196
181
 
197
182
const KoColorConversionTransformation* KoColorSpace::fromLabA16Converter() const
198
183
{
199
 
    if(!d->transfoFromLABA16)
200
 
    {
201
 
        d->transfoFromLABA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter( KoColorSpaceRegistry::instance()->lab16("") , this ) ;
 
184
    if (!d->transfoFromLABA16) {
 
185
        d->transfoFromLABA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(KoColorSpaceRegistry::instance()->lab16("") , this) ;
202
186
    }
203
187
    return d->transfoFromLABA16;
204
188
}
205
189
const KoColorConversionTransformation* KoColorSpace::toRgbA16Converter() const
206
190
{
207
 
    if(!d->transfoToRGBA16)
208
 
    {
209
 
        d->transfoToRGBA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter( this, KoColorSpaceRegistry::instance()->rgb16("") ) ;
 
191
    if (!d->transfoToRGBA16) {
 
192
        d->transfoToRGBA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(this, KoColorSpaceRegistry::instance()->rgb16("")) ;
210
193
    }
211
194
    return d->transfoToRGBA16;
212
195
}
213
196
const KoColorConversionTransformation* KoColorSpace::fromRgbA16Converter() const
214
197
{
215
 
    if(!d->transfoFromRGBA16)
216
 
    {
217
 
        d->transfoFromRGBA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter( KoColorSpaceRegistry::instance()->rgb16("") , this ) ;
 
198
    if (!d->transfoFromRGBA16) {
 
199
        d->transfoFromRGBA16 = KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(KoColorSpaceRegistry::instance()->rgb16("") , this) ;
218
200
    }
219
201
    return d->transfoFromRGBA16;
220
202
}
221
203
 
222
204
void KoColorSpace::toLabA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
223
205
{
224
 
    toLabA16Converter()->transform( src, dst, nPixels);
 
206
    toLabA16Converter()->transform(src, dst, nPixels);
225
207
}
226
208
 
227
209
void KoColorSpace::fromLabA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
228
210
{
229
 
    fromLabA16Converter()->transform( src, dst, nPixels);
 
211
    fromLabA16Converter()->transform(src, dst, nPixels);
230
212
}
231
213
 
232
214
void KoColorSpace::toRgbA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
233
215
{
234
 
    toRgbA16Converter()->transform( src, dst, nPixels);
 
216
    toRgbA16Converter()->transform(src, dst, nPixels);
235
217
}
236
218
 
237
219
void KoColorSpace::fromRgbA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
238
220
{
239
 
    fromRgbA16Converter()->transform( src, dst, nPixels);
 
221
    fromRgbA16Converter()->transform(src, dst, nPixels);
240
222
}
241
223
 
242
224
KoColorConversionTransformation* KoColorSpace::createColorConverter(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent) const
243
225
{
244
 
    if( *this == *dstColorSpace)
245
 
    {
 
226
    if (*this == *dstColorSpace) {
246
227
        return new KoCopyColorConversionTransformation(this);
247
228
    } else {
248
 
        return KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter( this, dstColorSpace, renderingIntent);
 
229
        return KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(this, dstColorSpace, renderingIntent);
249
230
    }
250
231
}
251
232
 
252
233
bool KoColorSpace::convertPixelsTo(const quint8 * src,
253
 
        quint8 * dst,
254
 
        const KoColorSpace * dstColorSpace,
255
 
        quint32 numPixels,
256
 
        KoColorConversionTransformation::Intent renderingIntent) const
 
234
                                   quint8 * dst,
 
235
                                   const KoColorSpace * dstColorSpace,
 
236
                                   quint32 numPixels,
 
237
                                   KoColorConversionTransformation::Intent renderingIntent) const
257
238
{
258
 
    if( *this == *dstColorSpace)
259
 
    {
260
 
        memcpy( dst, src, numPixels * sizeof(quint8) * pixelSize());
 
239
    if (*this == *dstColorSpace) {
 
240
        memcpy(dst, src, numPixels * sizeof(quint8) * pixelSize());
261
241
    } else {
262
242
        KoCachedColorConversionTransformation cct = KoColorSpaceRegistry::instance()->colorConversionCache()->cachedConverter(this, dstColorSpace, renderingIntent);
263
243
        cct.transformation()->transform(src, dst, numPixels);
279
259
                          const QString & op,
280
260
                          const QBitArray & channelFlags) const
281
261
{
282
 
    if ( d->compositeOps.contains( op ) ) {
283
 
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value( op ), channelFlags);
284
 
    }
285
 
    else {
286
 
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value( COMPOSITE_OVER ), channelFlags);
 
262
    if (d->compositeOps.contains(op)) {
 
263
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value(op), channelFlags);
 
264
    } else {
 
265
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value(COMPOSITE_OVER), channelFlags);
287
266
    }
288
267
 
289
268
}
300
279
                          qint32 cols,
301
280
                          const QString& op) const
302
281
{
303
 
    if ( d->compositeOps.contains( op ) ) {
304
 
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value( op ));
305
 
    }
306
 
    else {
307
 
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value( COMPOSITE_OVER ) );
 
282
    if (d->compositeOps.contains(op)) {
 
283
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value(op));
 
284
    } else {
 
285
        bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value(COMPOSITE_OVER));
308
286
    }
309
287
}
310
288
 
321
299
                          const KoCompositeOp * op,
322
300
                          const QBitArray & channelFlags) const
323
301
{
324
 
    Q_ASSERT_X(*op->colorSpace() == *this, "KoColorSpace::bitBlt", QString("Composite op is for color space %1 (%2) while this is %3 (%4)" ).arg( op->colorSpace()->id() ).arg(op->colorSpace()->profile()->name()).arg(id()).arg(profile()->name()).toLatin1() );
 
302
    Q_ASSERT_X(*op->colorSpace() == *this, "KoColorSpace::bitBlt", QString("Composite op is for color space %1 (%2) while this is %3 (%4)").arg(op->colorSpace()->id()).arg(op->colorSpace()->profile()->name()).arg(id()).arg(profile()->name()).toLatin1());
325
303
 
326
304
    if (rows <= 0 || cols <= 0)
327
305
        return;
328
306
 
329
307
    if (!(*this == *srcSpace)) {
330
308
 
331
 
        quint32 conversionBufferStride = cols * pixelSize();
332
 
        QVector<quint8> * conversionCache = 
333
 
            threadLocalConversionCache(rows * conversionBufferStride);
 
309
        quint32 conversionBufferStride = cols * pixelSize();
 
310
        QVector<quint8> * conversionCache =
 
311
            threadLocalConversionCache(rows * conversionBufferStride);
334
312
 
335
 
        quint8* conversionData = conversionCache->data();
 
313
        quint8* conversionData = conversionCache->data();
336
314
 
337
315
        for (qint32 row = 0; row < rows; row++) {
338
316
            srcSpace->convertPixelsTo(src + row * srcRowStride,
339
317
                                      conversionData + row * conversionBufferStride,
340
 
                                      this, cols);
 
318
                                      this, cols);
341
319
        }
342
320
 
343
 
        op->composite( dst, dstRowStride,
344
 
                       conversionData, conversionBufferStride,
345
 
                       srcAlphaMask, maskRowStride,
346
 
                       rows,  cols,
347
 
                       opacity, channelFlags );
 
321
        op->composite(dst, dstRowStride,
 
322
                      conversionData, conversionBufferStride,
 
323
                      srcAlphaMask, maskRowStride,
 
324
                      rows,  cols,
 
325
                      opacity, channelFlags);
 
326
    } else {
 
327
        op->composite(dst, dstRowStride,
 
328
                      src, srcRowStride,
 
329
                      srcAlphaMask, maskRowStride,
 
330
                      rows,  cols,
 
331
                      opacity, channelFlags);
 
332
    }
348
333
 
349
 
    }
350
 
    else {
351
 
        op->composite( dst, dstRowStride,
352
 
                       src, srcRowStride,
353
 
                       srcAlphaMask, maskRowStride,
354
 
                       rows,  cols,
355
 
                       opacity, channelFlags );
356
 
    }
357
334
}
358
335
 
359
336
// XXX: I don't want this code duplication, but also don't want an
377
354
        return;
378
355
 
379
356
    if (this != srcSpace) {
380
 
        quint32 conversionBufferStride = cols * pixelSize();
381
 
        QVector<quint8> * conversionCache = 
382
 
            threadLocalConversionCache(rows * conversionBufferStride);
 
357
        quint32 conversionBufferStride = cols * pixelSize();
 
358
        QVector<quint8> * conversionCache =
 
359
            threadLocalConversionCache(rows * conversionBufferStride);
383
360
 
384
361
        quint8* conversionData = conversionCache->data();
385
362
 
389
366
                                      cols);
390
367
        }
391
368
 
392
 
        op->composite( dst, dstRowStride,
393
 
                       conversionData, conversionBufferStride,
394
 
                       srcAlphaMask, maskRowStride,
395
 
                       rows,  cols,
396
 
                       opacity);
397
 
 
398
 
    }
399
 
    else {
400
 
        op->composite( dst, dstRowStride,
401
 
                       src, srcRowStride,
402
 
                       srcAlphaMask, maskRowStride,
403
 
                       rows, cols,
404
 
                       opacity);
405
 
    }
 
369
        op->composite(dst, dstRowStride,
 
370
                      conversionData, conversionBufferStride,
 
371
                      srcAlphaMask, maskRowStride,
 
372
                      rows,  cols,
 
373
                      opacity);
 
374
 
 
375
    } else {
 
376
        op->composite(dst, dstRowStride,
 
377
                      src, srcRowStride,
 
378
                      srcAlphaMask, maskRowStride,
 
379
                      rows, cols,
 
380
                      opacity);
 
381
    }
 
382
 
406
383
}
407
384
 
408
385
QVector<quint8> * KoColorSpace::threadLocalConversionCache(quint32 size) const
409
386
{
410
387
    QVector<quint8> * ba = 0;
411
 
    if ( !d->conversionCache.hasLocalData() ) {
412
 
        ba = new QVector<quint8>( size, '0' );
413
 
        d->conversionCache.setLocalData( ba );
414
 
    }
415
 
    else {
 
388
    if (!d->conversionCache.hasLocalData()) {
 
389
        ba = new QVector<quint8>(size, '0');
 
390
        d->conversionCache.setLocalData(ba);
 
391
    } else {
416
392
        ba = d->conversionCache.localData();
417
 
        if ( ( quint8 )ba->size() < size )
418
 
            ba->resize( size );
 
393
        if ((quint8)ba->size() < size)
 
394
            ba->resize(size);
419
395
    }
420
396
    return ba;
421
397
}
422
398
 
423
 
KoColorTransformation* KoColorSpace::createColorTransformation( const QString & id, const QHash<QString, QVariant> & parameters) const
 
399
KoColorTransformation* KoColorSpace::createColorTransformation(const QString & id, const QHash<QString, QVariant> & parameters) const
424
400
{
425
 
    KoColorTransformationFactory* factory = KoColorTransformationFactoryRegistry::instance()->get( id );
426
 
    if(!factory) return 0;
427
 
    QPair<KoID, KoID> model( colorModelId(), colorDepthId() );
 
401
    KoColorTransformationFactory* factory = KoColorTransformationFactoryRegistry::instance()->get(id);
 
402
    if (!factory) return 0;
 
403
    QPair<KoID, KoID> model(colorModelId(), colorDepthId());
428
404
    QList< QPair<KoID, KoID> > models = factory->supportedModels();
429
 
    if(models.contains(model))
430
 
    {
431
 
        return factory->createTransformation( this, parameters);
 
405
    if (models.isEmpty() || models.contains(model)) {
 
406
        return factory->createTransformation(this, parameters);
432
407
    } else {
433
408
        // Find the best solution
434
409
        // TODO use the color conversion cache
438
413
        Q_ASSERT(csToFallBack);
439
414
        Q_ASSERT(fallBackToCs);
440
415
        KoColorTransformation* transfo = factory->createTransformation(fallBackToCs->srcColorSpace(), parameters);
441
 
        return new KoFallBackColorTransformation( csToFallBack, fallBackToCs, transfo);
 
416
        return new KoFallBackColorTransformation(csToFallBack, fallBackToCs, transfo);
442
417
    }
443
418
}
444
419
 
445
420
QImage KoColorSpace::convertToQImage(const quint8 *data, qint32 width, qint32 height,
446
 
        const KoColorProfile *dstProfile,
447
 
        KoColorConversionTransformation::Intent renderingIntent) const
 
421
                                     const KoColorProfile *dstProfile,
 
422
                                     KoColorConversionTransformation::Intent renderingIntent) const
448
423
 
449
424
{
450
425
    QImage img = QImage(width, height, QImage::Format_ARGB32);
456
431
 
457
432
    return img;
458
433
}
459