97
107
QBitArray KoColorSpace::channelFlags(bool color, bool alpha, bool substance, bool substrate) const
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;
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);
113
QBitArray KoColorSpace::setChannelFlagsToPixelOrder(const QBitArray & origChannelFlags) const
115
if ( origChannelFlags.isEmpty() ) return origChannelFlags;
117
QBitArray orderedChannelFlags( origChannelFlags.size() );
118
for ( int i = 0; i < origChannelFlags.size(); ++i ) {
120
KoChannelInfo * channel = d->channels.at( i );
121
orderedChannelFlags.setBit( channel->pos(), origChannelFlags.testBit( i ) );
123
return orderedChannelFlags;
126
QBitArray KoColorSpace::setChannelFlagsToColorSpaceOrder( const QBitArray & origChannelFlags ) const
128
if ( origChannelFlags.isEmpty() ) return origChannelFlags;
130
QBitArray orderedChannelFlags( origChannelFlags.size() );
131
for ( int i = 0; i < orderedChannelFlags.size(); ++i )
133
KoChannelInfo * channel = d->channels.at( i );
134
orderedChannelFlags.setBit( i, origChannelFlags.testBit( channel->pos() ) );
136
return orderedChannelFlags;
139
123
void KoColorSpace::addChannel(KoChannelInfo * ci)
141
125
d->channels.push_back(ci);
162
KoMixColorsOp* KoColorSpace::mixColorsOp() const {
146
KoMixColorsOp* KoColorSpace::mixColorsOp() const
163
148
return d->mixColorsOp;
167
KoConvolutionOp* KoColorSpace::convolutionOp() const {
152
KoConvolutionOp* KoColorSpace::convolutionOp() const
168
154
return d->convolutionOp;
171
157
const KoCompositeOp * KoColorSpace::compositeOp(const QString & id) const
173
if ( d->compositeOps.contains( id ) )
174
return d->compositeOps.value( id );
159
if (d->compositeOps.contains(id))
160
return d->compositeOps.value(id);
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);
181
167
void KoColorSpace::addCompositeOp(const KoCompositeOp * op)
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));
188
174
const KoColorConversionTransformation* KoColorSpace::toLabA16Converter() const
190
if(!d->transfoToLABA16)
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("")) ;
194
179
return d->transfoToLABA16;
197
182
const KoColorConversionTransformation* KoColorSpace::fromLabA16Converter() const
199
if(!d->transfoFromLABA16)
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) ;
203
187
return d->transfoFromLABA16;
205
189
const KoColorConversionTransformation* KoColorSpace::toRgbA16Converter() const
207
if(!d->transfoToRGBA16)
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("")) ;
211
194
return d->transfoToRGBA16;
213
196
const KoColorConversionTransformation* KoColorSpace::fromRgbA16Converter() const
215
if(!d->transfoFromRGBA16)
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) ;
219
201
return d->transfoFromRGBA16;
222
204
void KoColorSpace::toLabA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
224
toLabA16Converter()->transform( src, dst, nPixels);
206
toLabA16Converter()->transform(src, dst, nPixels);
227
209
void KoColorSpace::fromLabA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
229
fromLabA16Converter()->transform( src, dst, nPixels);
211
fromLabA16Converter()->transform(src, dst, nPixels);
232
214
void KoColorSpace::toRgbA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
234
toRgbA16Converter()->transform( src, dst, nPixels);
216
toRgbA16Converter()->transform(src, dst, nPixels);
237
219
void KoColorSpace::fromRgbA16(const quint8 * src, quint8 * dst, quint32 nPixels) const
239
fromRgbA16Converter()->transform( src, dst, nPixels);
221
fromRgbA16Converter()->transform(src, dst, nPixels);
242
224
KoColorConversionTransformation* KoColorSpace::createColorConverter(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent) const
244
if( *this == *dstColorSpace)
226
if (*this == *dstColorSpace) {
246
227
return new KoCopyColorConversionTransformation(this);
248
return KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter( this, dstColorSpace, renderingIntent);
229
return KoColorSpaceRegistry::instance()->colorConversionSystem()->createColorConverter(this, dstColorSpace, renderingIntent);
252
233
bool KoColorSpace::convertPixelsTo(const quint8 * src,
254
const KoColorSpace * dstColorSpace,
256
KoColorConversionTransformation::Intent renderingIntent) const
235
const KoColorSpace * dstColorSpace,
237
KoColorConversionTransformation::Intent renderingIntent) const
258
if( *this == *dstColorSpace)
260
memcpy( dst, src, numPixels * sizeof(quint8) * pixelSize());
239
if (*this == *dstColorSpace) {
240
memcpy(dst, src, numPixels * sizeof(quint8) * pixelSize());
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
282
if ( d->compositeOps.contains( op ) ) {
283
bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value( op ), channelFlags);
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);
265
bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value(COMPOSITE_OVER), channelFlags);
301
280
const QString& op) const
303
if ( d->compositeOps.contains( op ) ) {
304
bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value( op ));
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));
285
bitBlt(dst, dststride, srcSpace, src, srcRowStride, srcAlphaMask, maskRowStride, opacity, rows, cols, d->compositeOps.value(COMPOSITE_OVER));
321
299
const KoCompositeOp * op,
322
300
const QBitArray & channelFlags) const
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());
326
304
if (rows <= 0 || cols <= 0)
329
307
if (!(*this == *srcSpace)) {
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);
335
quint8* conversionData = conversionCache->data();
313
quint8* conversionData = conversionCache->data();
337
315
for (qint32 row = 0; row < rows; row++) {
338
316
srcSpace->convertPixelsTo(src + row * srcRowStride,
339
317
conversionData + row * conversionBufferStride,
343
op->composite( dst, dstRowStride,
344
conversionData, conversionBufferStride,
345
srcAlphaMask, maskRowStride,
347
opacity, channelFlags );
321
op->composite(dst, dstRowStride,
322
conversionData, conversionBufferStride,
323
srcAlphaMask, maskRowStride,
325
opacity, channelFlags);
327
op->composite(dst, dstRowStride,
329
srcAlphaMask, maskRowStride,
331
opacity, channelFlags);
351
op->composite( dst, dstRowStride,
353
srcAlphaMask, maskRowStride,
355
opacity, channelFlags );
359
336
// XXX: I don't want this code duplication, but also don't want an
392
op->composite( dst, dstRowStride,
393
conversionData, conversionBufferStride,
394
srcAlphaMask, maskRowStride,
400
op->composite( dst, dstRowStride,
402
srcAlphaMask, maskRowStride,
369
op->composite(dst, dstRowStride,
370
conversionData, conversionBufferStride,
371
srcAlphaMask, maskRowStride,
376
op->composite(dst, dstRowStride,
378
srcAlphaMask, maskRowStride,
408
385
QVector<quint8> * KoColorSpace::threadLocalConversionCache(quint32 size) const
410
387
QVector<quint8> * ba = 0;
411
if ( !d->conversionCache.hasLocalData() ) {
412
ba = new QVector<quint8>( size, '0' );
413
d->conversionCache.setLocalData( ba );
388
if (!d->conversionCache.hasLocalData()) {
389
ba = new QVector<quint8>(size, '0');
390
d->conversionCache.setLocalData(ba);
416
392
ba = d->conversionCache.localData();
417
if ( ( quint8 )ba->size() < size )
393
if ((quint8)ba->size() < size)
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
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))
431
return factory->createTransformation( this, parameters);
405
if (models.isEmpty() || models.contains(model)) {
406
return factory->createTransformation(this, parameters);
433
408
// Find the best solution
434
409
// TODO use the color conversion cache