00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <qimage.h>
00020
00021 #include <kdebug.h>
00022 #include <kconfig.h>
00023
00024 #include "kis_abstract_colorspace.h"
00025 #include "kis_global.h"
00026 #include "kis_profile.h"
00027 #include "kis_id.h"
00028 #include "kis_integer_maths.h"
00029 #include "kis_color_conversions.h"
00030 #include "kis_colorspace_factory_registry.h"
00031 #include "kis_channelinfo.h"
00032
00033 class KisColorAdjustmentImpl : public KisColorAdjustment
00034 {
00035 public:
00036
00037 KisColorAdjustmentImpl() : KisColorAdjustment()
00038 {
00039 csProfile = 0;
00040 transform = 0;
00041 profiles[0] = 0;
00042 profiles[1] = 0;
00043 profiles[2] = 0;
00044 };
00045
00046 ~KisColorAdjustmentImpl() {
00047
00048 if (transform)
00049 cmsDeleteTransform(transform);
00050 if (profiles[0] && profiles[0] != csProfile)
00051 cmsCloseProfile(profiles[0]);
00052 if(profiles[1] && profiles[1] != csProfile)
00053 cmsCloseProfile(profiles[1]);
00054 if(profiles[2] && profiles[2] != csProfile)
00055 cmsCloseProfile(profiles[2]);
00056 }
00057
00058 cmsHPROFILE csProfile;
00059 cmsHPROFILE profiles[3];
00060 cmsHTRANSFORM transform;
00061 };
00062
00063 KisAbstractColorSpace::KisAbstractColorSpace(const KisID& id,
00064 DWORD cmType,
00065 icColorSpaceSignature colorSpaceSignature,
00066 KisColorSpaceFactoryRegistry * parent,
00067 KisProfile *p)
00068 : m_parent( parent )
00069 , m_profile( p )
00070 , m_id( id )
00071 , m_cmType( cmType )
00072 , m_colorSpaceSignature( colorSpaceSignature )
00073 {
00074 m_alphaPos = -1;
00075 m_alphaSize = -1;
00076 m_qcolordata = 0;
00077 m_lastUsedDstColorSpace = 0;
00078 m_lastUsedTransform = 0;
00079 m_lastRGBProfile = 0;
00080 m_lastToRGB = 0;
00081 m_lastFromRGB = 0;
00082 m_defaultFromRGB = 0;
00083 m_defaultToRGB = 0;
00084 m_defaultFromLab = 0;
00085 m_defaultToLab = 0;
00086 }
00087
00088 void KisAbstractColorSpace::init()
00089 {
00090
00091 m_qcolordata = new Q_UINT8[3];
00092 Q_CHECK_PTR(m_qcolordata);
00093
00094 if (m_profile == 0) return;
00095
00096
00097 m_lastFromRGB = cmsCreate_sRGBProfile();
00098
00099 m_defaultFromRGB = cmsCreateTransform(m_lastFromRGB, TYPE_BGR_8,
00100 m_profile->profile(), m_cmType,
00101 INTENT_PERCEPTUAL, 0);
00102
00103 m_defaultToRGB = cmsCreateTransform(m_profile->profile(), m_cmType,
00104 m_lastFromRGB, TYPE_BGR_8,
00105 INTENT_PERCEPTUAL, 0);
00106
00107 cmsHPROFILE hLab = cmsCreateLabProfile(NULL);
00108
00109 m_defaultFromLab = cmsCreateTransform(hLab, TYPE_Lab_16, m_profile->profile(), m_cmType,
00110 INTENT_PERCEPTUAL, 0);
00111
00112 m_defaultToLab = cmsCreateTransform(m_profile->profile(), m_cmType, hLab, TYPE_Lab_16,
00113 INTENT_PERCEPTUAL, 0);
00114 }
00115
00116 KisAbstractColorSpace::~KisAbstractColorSpace()
00117 {
00118 }
00119
00120
00121
00122 void KisAbstractColorSpace::fromQColor(const QColor& color, Q_UINT8 *dst, KisProfile * profile)
00123 {
00124 m_qcolordata[2] = color.red();
00125 m_qcolordata[1] = color.green();
00126 m_qcolordata[0] = color.blue();
00127
00128
00129 if (profile == 0) {
00130
00131 if (!m_defaultFromRGB) return;
00132
00133 cmsDoTransform(m_defaultFromRGB, m_qcolordata, dst, 1);
00134 }
00135 else {
00136 if (m_lastFromRGB == 0 || (m_lastFromRGB != 0 && m_lastRGBProfile != profile->profile())) {
00137 m_lastFromRGB = cmsCreateTransform(profile->profile(), TYPE_BGR_8,
00138 m_profile->profile(), m_cmType,
00139 INTENT_PERCEPTUAL, 0);
00140 m_lastRGBProfile = profile->profile();
00141
00142 }
00143 cmsDoTransform(m_lastFromRGB, m_qcolordata, dst, 1);
00144 }
00145
00146 setAlpha(dst, OPACITY_OPAQUE, 1);
00147 }
00148
00149 void KisAbstractColorSpace::fromQColor(const QColor& color, Q_UINT8 opacity, Q_UINT8 *dst, KisProfile * profile)
00150 {
00151 fromQColor(color, dst, profile);
00152 setAlpha(dst, opacity, 1);
00153 }
00154
00155 void KisAbstractColorSpace::toQColor(const Q_UINT8 *src, QColor *c, KisProfile * profile)
00156 {
00157 if (profile == 0) {
00158
00159 if (!m_defaultToRGB) return;
00160 cmsDoTransform(m_defaultToRGB, const_cast <Q_UINT8 *>(src), m_qcolordata, 1);
00161 }
00162 else {
00163 if (m_lastToRGB == 0 || (m_lastToRGB != 0 && m_lastRGBProfile != profile->profile())) {
00164 m_lastToRGB = cmsCreateTransform(m_profile->profile(), m_cmType,
00165 profile->profile(), TYPE_BGR_8,
00166 INTENT_PERCEPTUAL, 0);
00167 m_lastRGBProfile = profile->profile();
00168 }
00169 cmsDoTransform(m_lastToRGB, const_cast <Q_UINT8 *>(src), m_qcolordata, 1);
00170 }
00171 c->setRgb(m_qcolordata[2], m_qcolordata[1], m_qcolordata[0]);
00172 }
00173
00174 void KisAbstractColorSpace::toQColor(const Q_UINT8 *src, QColor *c, Q_UINT8 *opacity, KisProfile * profile)
00175 {
00176 toQColor(src, c, profile);
00177 *opacity = getAlpha(src);
00178 }
00179
00180 void KisAbstractColorSpace::getSingleChannelPixel(Q_UINT8 *dstPixel, const Q_UINT8 *srcPixel, Q_UINT32 channelIndex)
00181 {
00182 if (channelIndex < m_channels.count()) {
00183
00184 fromQColor(Qt::black, OPACITY_TRANSPARENT, dstPixel);
00185
00186 const KisChannelInfo *channelInfo = m_channels[channelIndex];
00187 memcpy(dstPixel + channelInfo->pos(), srcPixel + channelInfo->pos(), channelInfo->size());
00188 }
00189 }
00190
00191 bool KisAbstractColorSpace::convertPixelsTo(const Q_UINT8 * src,
00192 Q_UINT8 * dst,
00193 KisColorSpace * dstColorSpace,
00194 Q_UINT32 numPixels,
00195 Q_INT32 renderingIntent)
00196 {
00197 if (dstColorSpace->colorSpaceType() == colorSpaceType()
00198 && dstColorSpace->getProfile() == getProfile())
00199 {
00200 if (src!= dst)
00201 memcpy (dst, src, numPixels * pixelSize());
00202
00203 return true;
00204 }
00205
00206 cmsHTRANSFORM tf = 0;
00207
00208 Q_INT32 srcPixelSize = pixelSize();
00209 Q_INT32 dstPixelSize = dstColorSpace->pixelSize();
00210
00211 if (m_lastUsedTransform != 0 && m_lastUsedDstColorSpace != 0) {
00212 if (dstColorSpace->colorSpaceType() == m_lastUsedDstColorSpace->colorSpaceType() &&
00213 dstColorSpace->getProfile() == m_lastUsedDstColorSpace->getProfile()) {
00214 tf = m_lastUsedTransform;
00215 }
00216 }
00217
00218 if (!tf && m_profile && dstColorSpace->getProfile()) {
00219
00220 if (!m_transforms.contains(dstColorSpace)) {
00221 tf = createTransform(dstColorSpace,
00222 m_profile,
00223 dstColorSpace->getProfile(),
00224 renderingIntent);
00225 if (tf) {
00226
00227 m_transforms[dstColorSpace] = tf;
00228 }
00229 }
00230 else {
00231 tf = m_transforms[dstColorSpace];
00232 }
00233
00234 if ( tf ) {
00235 m_lastUsedTransform = tf;
00236 m_lastUsedDstColorSpace = dstColorSpace;
00237 }
00238 }
00239
00240 if (tf) {
00241
00242 cmsDoTransform(tf, const_cast<Q_UINT8 *>(src), dst, numPixels);
00243
00244
00245 while (numPixels > 0) {
00246 Q_UINT8 alpha = getAlpha(src);
00247 dstColorSpace->setAlpha(dst, alpha, 1);
00248
00249 src += srcPixelSize;
00250 dst += dstPixelSize;
00251 numPixels--;
00252 }
00253
00254 return true;
00255 }
00256
00257
00258 while (numPixels > 0) {
00259 QColor color;
00260 Q_UINT8 opacity;
00261
00262 toQColor(src, &color, &opacity);
00263 dstColorSpace->fromQColor(color, opacity, dst);
00264
00265 src += srcPixelSize;
00266 dst += dstPixelSize;
00267 numPixels--;
00268 }
00269
00270 return true;
00271 }
00272
00273
00274 KisColorAdjustment *KisAbstractColorSpace::createBrightnessContrastAdjustment(Q_UINT16 *transferValues)
00275 {
00276 if (!m_profile) return 0;
00277
00278 LPGAMMATABLE transferFunctions[3];
00279 transferFunctions[0] = cmsBuildGamma(256, 1.0);
00280 transferFunctions[1] = cmsBuildGamma(256, 1.0);
00281 transferFunctions[2] = cmsBuildGamma(256, 1.0);
00282
00283 for(int i =0; i < 256; i++)
00284 transferFunctions[0]->GammaTable[i] = transferValues[i];
00285
00286 KisColorAdjustmentImpl *adj = new KisColorAdjustmentImpl;
00287 adj->profiles[1] = cmsCreateLinearizationDeviceLink(icSigLabData, transferFunctions);
00288 cmsSetDeviceClass(adj->profiles[1], icSigAbstractClass);
00289
00290 adj->profiles[0] = m_profile->profile();
00291 adj->profiles[2] = m_profile->profile();
00292 adj->transform = cmsCreateMultiprofileTransform(adj->profiles, 3, m_cmType, m_cmType, INTENT_PERCEPTUAL, 0);
00293 adj->csProfile = m_profile->profile();
00294 return adj;
00295 }
00296
00297 typedef struct {
00298 double Saturation;
00299
00300 } BCHSWADJUSTS, *LPBCHSWADJUSTS;
00301
00302
00303 static int desaturateSampler(register WORD In[], register WORD Out[], register LPVOID )
00304 {
00305 cmsCIELab LabIn, LabOut;
00306 cmsCIELCh LChIn, LChOut;
00307
00308
00309 cmsLabEncoded2Float(&LabIn, In);
00310
00311 cmsLab2LCh(&LChIn, &LabIn);
00312
00313
00314 LChOut.L = LChIn.L;
00315 LChOut.C = 0;
00316 LChOut.h = LChIn.h;
00317
00318 cmsLCh2Lab(&LabOut, &LChOut);
00319
00320
00321 cmsFloat2LabEncoded(Out, &LabOut);
00322
00323 return TRUE;
00324 }
00325
00326 KisColorAdjustment *KisAbstractColorSpace::createDesaturateAdjustment()
00327 {
00328 if (!m_profile) return 0;
00329
00330 KisColorAdjustmentImpl *adj = new KisColorAdjustmentImpl;
00331
00332 adj->profiles[0] = m_profile->profile();
00333 adj->profiles[2] = m_profile->profile();
00334 adj->csProfile = m_profile->profile();
00335
00336 LPLUT Lut;
00337 BCHSWADJUSTS bchsw;
00338
00339 bchsw.Saturation = -25;
00340
00341 adj->profiles[1] = _cmsCreateProfilePlaceholder();
00342 if (!adj->profiles[1])
00343 return NULL;
00344
00345 cmsSetDeviceClass(adj->profiles[1], icSigAbstractClass);
00346 cmsSetColorSpace(adj->profiles[1], icSigLabData);
00347 cmsSetPCS(adj->profiles[1], icSigLabData);
00348
00349 cmsSetRenderingIntent(adj->profiles[1], INTENT_PERCEPTUAL);
00350
00351
00352 Lut = cmsAllocLUT();
00353
00354 cmsAlloc3DGrid(Lut, 32, 3, 3);
00355
00356 if (!cmsSample3DGrid(Lut, desaturateSampler, static_cast<LPVOID>(&bchsw), 0)) {
00357
00358 cmsFreeLUT(Lut);
00359 cmsCloseProfile(adj->profiles[1]);
00360 return NULL;
00361 }
00362
00363
00364
00365 cmsAddTag(adj->profiles[1], icSigDeviceMfgDescTag, (LPVOID) "(krita internal)");
00366 cmsAddTag(adj->profiles[1], icSigProfileDescriptionTag, (LPVOID) "krita saturation abstract profile");
00367 cmsAddTag(adj->profiles[1], icSigDeviceModelDescTag, (LPVOID) "saturation built-in");
00368
00369 cmsAddTag(adj->profiles[1], icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
00370
00371 cmsAddTag(adj->profiles[1], icSigAToB0Tag, (LPVOID) Lut);
00372
00373
00374 cmsFreeLUT(Lut);
00375
00376 adj->transform = cmsCreateMultiprofileTransform(adj->profiles, 3, m_cmType, m_cmType, INTENT_PERCEPTUAL, 0);
00377
00378 return adj;
00379 }
00380
00381 KisColorAdjustment *KisAbstractColorSpace::createPerChannelAdjustment(Q_UINT16 **transferValues)
00382 {
00383 if (!m_profile) return 0;
00384
00385 LPGAMMATABLE *transferFunctions = new LPGAMMATABLE[nColorChannels()+1];
00386
00387 for(uint ch=0; ch < nColorChannels(); ch++) {
00388 transferFunctions[ch] = cmsBuildGamma(256, 1.0);
00389 for(uint i =0; i < 256; i++) {
00390 transferFunctions[ch]->GammaTable[i] = transferValues[ch][i];
00391 }
00392 }
00393
00394 KisColorAdjustmentImpl *adj = new KisColorAdjustmentImpl;
00395 adj->profiles[0] = cmsCreateLinearizationDeviceLink(colorSpaceSignature(), transferFunctions);
00396 adj->profiles[1] = NULL;
00397 adj->profiles[2] = NULL;
00398 adj->csProfile = m_profile->profile();
00399 adj->transform = cmsCreateTransform(adj->profiles[0], m_cmType, NULL, m_cmType, INTENT_PERCEPTUAL, 0);
00400
00401 delete [] transferFunctions;
00402
00403 return adj;
00404 }
00405
00406
00407 void KisAbstractColorSpace::applyAdjustment(const Q_UINT8 *src, Q_UINT8 *dst, KisColorAdjustment *adjustment, Q_INT32 nPixels)
00408 {
00409 KisColorAdjustmentImpl * adj = dynamic_cast<KisColorAdjustmentImpl*>(adjustment);
00410 if (adj)
00411 cmsDoTransform(adj->transform, const_cast<Q_UINT8 *>(src), dst, nPixels);
00412 }
00413
00414
00415 void KisAbstractColorSpace::invertColor(Q_UINT8 * src, Q_INT32 nPixels)
00416 {
00417 QColor c;
00418 Q_UINT8 opacity;
00419 Q_UINT32 psize = pixelSize();
00420
00421 while (nPixels--)
00422 {
00423 toQColor(src, &c, &opacity);
00424 c.setRgb(Q_UINT8_MAX - c.red(), Q_UINT8_MAX - c.green(), Q_UINT8_MAX - c.blue());
00425 fromQColor( c, opacity, src);
00426
00427 src += psize;
00428 }
00429 }
00430
00431 Q_UINT8 KisAbstractColorSpace::difference(const Q_UINT8* src1, const Q_UINT8* src2)
00432 {
00433 if (m_defaultToLab) {
00434
00435 Q_UINT8 lab1[8], lab2[8];
00436 cmsCIELab labF1, labF2;
00437
00438 if (getAlpha(src1) == OPACITY_TRANSPARENT || getAlpha(src2) == OPACITY_TRANSPARENT)
00439 return (getAlpha(src1) == getAlpha(src2) ? 0 : 255);
00440
00441 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8*>( src1 ), lab1, 1);
00442 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8*>( src2 ), lab2, 1);
00443 cmsLabEncoded2Float(&labF1, (WORD *)lab1);
00444 cmsLabEncoded2Float(&labF2, (WORD *)lab2);
00445 double diff = cmsDeltaE(&labF1, &labF2);
00446 if(diff>255)
00447 return 255;
00448 else
00449 return Q_INT8(diff);
00450 }
00451 else {
00452 QColor c1;
00453 Q_UINT8 opacity1;
00454 toQColor(src1, &c1, &opacity1);
00455
00456 QColor c2;
00457 Q_UINT8 opacity2;
00458 toQColor(src2, &c2, &opacity2);
00459
00460 Q_UINT8 red = abs(c1.red() - c2.red());
00461 Q_UINT8 green = abs(c1.green() - c2.green());
00462 Q_UINT8 blue = abs(c1.blue() - c2.blue());
00463 return QMAX(red, QMAX(green, blue));
00464 }
00465 }
00466
00467 void KisAbstractColorSpace::mixColors(const Q_UINT8 **colors, const Q_UINT8 *weights, Q_UINT32 nColors, Q_UINT8 *dst) const
00468 {
00469 Q_UINT32 totalRed = 0, totalGreen = 0, totalBlue = 0, newAlpha = 0;
00470
00471 QColor c;
00472 Q_UINT8 opacity;
00473
00474 while (nColors--)
00475 {
00476
00477 const_cast<KisAbstractColorSpace *>(this)->toQColor(*colors, &c, &opacity);
00478
00479 Q_UINT32 alphaTimesWeight = UINT8_MULT(opacity, *weights);
00480
00481 totalRed += c.red() * alphaTimesWeight;
00482 totalGreen += c.green() * alphaTimesWeight;
00483 totalBlue += c.blue() * alphaTimesWeight;
00484 newAlpha += alphaTimesWeight;
00485
00486 weights++;
00487 colors++;
00488 }
00489
00490 Q_ASSERT(newAlpha <= 255);
00491
00492 if (newAlpha > 0) {
00493 totalRed = UINT8_DIVIDE(totalRed, newAlpha);
00494 totalGreen = UINT8_DIVIDE(totalGreen, newAlpha);
00495 totalBlue = UINT8_DIVIDE(totalBlue, newAlpha);
00496 }
00497
00498
00499 totalRed += 0x80;
00500
00501 Q_UINT32 dstRed = ((totalRed >> 8) + totalRed) >> 8;
00502 Q_ASSERT(dstRed <= 255);
00503
00504 totalGreen += 0x80;
00505 Q_UINT32 dstGreen = ((totalGreen >> 8) + totalGreen) >> 8;
00506 Q_ASSERT(dstGreen <= 255);
00507
00508 totalBlue += 0x80;
00509 Q_UINT32 dstBlue = ((totalBlue >> 8) + totalBlue) >> 8;
00510 Q_ASSERT(dstBlue <= 255);
00511
00512 const_cast<KisAbstractColorSpace *>(this)->fromQColor(QColor(dstRed, dstGreen, dstBlue), newAlpha, dst);
00513 }
00514
00515 void KisAbstractColorSpace::convolveColors(Q_UINT8** colors, Q_INT32 * kernelValues, KisChannelInfo::enumChannelFlags channelFlags,
00516 Q_UINT8 *dst, Q_INT32 factor, Q_INT32 offset, Q_INT32 nColors) const
00517 {
00518 Q_INT32 totalRed = 0, totalGreen = 0, totalBlue = 0, totalAlpha = 0;
00519
00520 QColor dstColor;
00521 Q_UINT8 dstOpacity;
00522
00523 const_cast<KisAbstractColorSpace *>(this)->toQColor(dst, &dstColor, &dstOpacity);
00524
00525 while (nColors--)
00526 {
00527 Q_INT32 weight = *kernelValues;
00528
00529 if (weight != 0) {
00530 QColor c;
00531 Q_UINT8 opacity;
00532 const_cast<KisAbstractColorSpace *>(this)->toQColor( *colors, &c, &opacity );
00533 totalRed += c.red() * weight;
00534 totalGreen += c.green() * weight;
00535 totalBlue += c.blue() * weight;
00536 totalAlpha += opacity * weight;
00537 }
00538 colors++;
00539 kernelValues++;
00540 }
00541
00542
00543 if (channelFlags & KisChannelInfo::FLAG_COLOR) {
00544 const_cast<KisAbstractColorSpace *>(this)->fromQColor(QColor(CLAMP((totalRed / factor) + offset, 0, Q_UINT8_MAX),
00545 CLAMP((totalGreen / factor) + offset, 0, Q_UINT8_MAX),
00546 CLAMP((totalBlue / factor) + offset, 0, Q_UINT8_MAX)),
00547 dstOpacity,
00548 dst);
00549 }
00550 if (channelFlags & KisChannelInfo::FLAG_ALPHA) {
00551 const_cast<KisAbstractColorSpace *>(this)->fromQColor(dstColor, CLAMP((totalAlpha/ factor) + offset, 0, Q_UINT8_MAX), dst);
00552 }
00553
00554 }
00555
00556 void KisAbstractColorSpace::darken(const Q_UINT8 * src, Q_UINT8 * dst, Q_INT32 shade, bool compensate, double compensation, Q_INT32 nPixels) const
00557 {
00558 if (m_defaultToLab) {
00559 Q_UINT16 * labcache = new Q_UINT16[nPixels * 4];
00560 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8*>( src ), reinterpret_cast<Q_UINT8*>( labcache ), nPixels );
00561 for ( int i = 0; i < nPixels * 4; ++i ) {
00562 if ( compensate ) {
00563 labcache[i] = static_cast<Q_UINT16>( ( labcache[i] * shade ) / ( compensation * 255 ) );
00564 }
00565 else {
00566 labcache[i] = static_cast<Q_UINT16>( labcache[i] * shade / 255 );
00567 }
00568 }
00569 cmsDoTransform( m_defaultFromLab, reinterpret_cast<Q_UINT8*>( labcache ), dst, nPixels );
00570
00571
00572 for ( int i = 0; i < nPixels; ++i ) {
00573 Q_UINT8 alpha = getAlpha( src );
00574 setAlpha( dst, alpha, 1 );
00575 }
00576 delete [] labcache;
00577 }
00578 else {
00579
00580 QColor c;
00581 Q_INT32 psize = pixelSize();
00582
00583 for (int i = 0; i < nPixels; ++i) {
00584
00585 const_cast<KisAbstractColorSpace *>(this)->toQColor(src + (i * psize), &c);
00586 Q_INT32 r, g, b;
00587
00588 if (compensate) {
00589 r = static_cast<Q_INT32>( QMIN(255, (c.red() * shade) / (compensation * 255)));
00590 g = static_cast<Q_INT32>( QMIN(255, (c.green() * shade) / (compensation * 255)));
00591 b = static_cast<Q_INT32>( QMIN(255, (c.blue() * shade) / (compensation * 255)));
00592 }
00593 else {
00594 r = static_cast<Q_INT32>( QMIN(255, (c.red() * shade / 255)));
00595 g = static_cast<Q_INT32>( QMIN(255, (c.green() * shade / 255)));
00596 b = static_cast<Q_INT32>( QMIN(255, (c.blue() * shade / 255)));
00597 }
00598 c.setRgb(r, g, b);
00599
00600 const_cast<KisAbstractColorSpace *>(this)->fromQColor( c, dst + (i * psize));
00601 }
00602 }
00603 }
00604
00605 Q_UINT8 KisAbstractColorSpace::intensity8(const Q_UINT8 * src) const
00606 {
00607 QColor c;
00608 Q_UINT8 opacity;
00609 const_cast<KisAbstractColorSpace *>(this)->toQColor(src, &c, &opacity);
00610 return static_cast<Q_UINT8>((c.red() * 0.30 + c.green() * 0.59 + c.blue() * 0.11) + 0.5);
00611
00612 }
00613
00614
00615 KisID KisAbstractColorSpace::mathToolboxID() const
00616 {
00617 return KisID("Basic");
00618 }
00619
00620 void KisAbstractColorSpace::bitBlt(Q_UINT8 *dst,
00621 Q_INT32 dststride,
00622 KisColorSpace * srcSpace,
00623 const Q_UINT8 *src,
00624 Q_INT32 srcRowStride,
00625 const Q_UINT8 *srcAlphaMask,
00626 Q_INT32 maskRowStride,
00627 Q_UINT8 opacity,
00628 Q_INT32 rows,
00629 Q_INT32 cols,
00630 const KisCompositeOp& op)
00631 {
00632 if (rows <= 0 || cols <= 0)
00633 return;
00634
00635 if (this != srcSpace) {
00636 Q_UINT32 len = pixelSize() * rows * cols;
00637
00638
00639 if (!m_conversionCache.resize( len, QGArray::SpeedOptim )) {
00640 kdWarning() << "Could not allocate enough memory for the conversion!\n";
00641
00642 abort();
00643 }
00644
00645 for (Q_INT32 row = 0; row < rows; row++) {
00646 srcSpace->convertPixelsTo(src + row * srcRowStride,
00647 m_conversionCache.data() + row * cols * pixelSize(), this,
00648 cols);
00649 }
00650
00651
00652 srcRowStride = cols * pixelSize();
00653
00654 bitBlt(dst,
00655 dststride,
00656 m_conversionCache.data(),
00657 srcRowStride,
00658 srcAlphaMask,
00659 maskRowStride,
00660 opacity,
00661 rows,
00662 cols,
00663 op);
00664
00665 }
00666 else {
00667 bitBlt(dst,
00668 dststride,
00669 src,
00670 srcRowStride,
00671 srcAlphaMask,
00672 maskRowStride,
00673 opacity,
00674 rows,
00675 cols,
00676 op);
00677 }
00678 }
00679
00680 QImage KisAbstractColorSpace::convertToQImage(const Q_UINT8 *data, Q_INT32 width, Q_INT32 height,
00681 KisProfile *dstProfile,
00682 Q_INT32 renderingIntent, float )
00683
00684 {
00685 QImage img = QImage(width, height, 32, 0, QImage::LittleEndian);
00686 img.setAlphaBuffer( true );
00687
00688 KisColorSpace * dstCS;
00689
00690 if (dstProfile)
00691 dstCS = m_parent->getColorSpace(KisID("RGBA",""),dstProfile->productName());
00692 else
00693 dstCS = m_parent->getRGB8();
00694
00695 if (data)
00696 convertPixelsTo(const_cast<Q_UINT8 *>(data), img.bits(), dstCS, width * height, renderingIntent);
00697
00698 return img;
00699 }
00700
00701
00702 cmsHTRANSFORM KisAbstractColorSpace::createTransform(KisColorSpace * dstColorSpace,
00703 KisProfile * srcProfile,
00704 KisProfile * dstProfile,
00705 Q_INT32 renderingIntent)
00706 {
00707 KConfig * cfg = KGlobal::config();
00708 bool bpCompensation = cfg->readBoolEntry("useBlackPointCompensation", false);
00709
00710 int flags = 0;
00711
00712 if (bpCompensation) {
00713 flags = cmsFLAGS_BLACKPOINTCOMPENSATION;
00714 }
00715
00716 if (dstColorSpace && dstProfile && srcProfile ) {
00717 cmsHTRANSFORM tf = cmsCreateTransform(srcProfile->profile(),
00718 colorSpaceType(),
00719 dstProfile->profile(),
00720 dstColorSpace->colorSpaceType(),
00721 renderingIntent,
00722 flags);
00723
00724 return tf;
00725 }
00726 return 0;
00727 }
00728
00729 void KisAbstractColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride, const Q_UINT8 * , Q_INT32 , Q_INT32 rows, Q_INT32 numColumns, Q_UINT8 opacity)
00730 {
00731 Q_UINT8 *dst = dstRowStart;
00732 const Q_UINT8 *src = srcRowStart;
00733 Q_INT32 bytesPerPixel = pixelSize();
00734
00735 while (rows > 0) {
00736 memcpy(dst, src, numColumns * bytesPerPixel);
00737
00738 if (opacity != OPACITY_OPAQUE) {
00739 multiplyAlpha(dst, opacity, numColumns);
00740 }
00741
00742 dst += dstRowStride;
00743 src += srcRowStride;
00744 --rows;
00745 }
00746 }
00747