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::toLabA16(const Q_UINT8 * src, Q_UINT8 * dst, const Q_UINT32 nPixels) const
00181 {
00182 if ( m_defaultToLab == 0 ) return;
00183
00184 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8 *>( src ), dst, nPixels );
00185 }
00186
00187 void KisAbstractColorSpace::fromLabA16(const Q_UINT8 * src, Q_UINT8 * dst, const Q_UINT32 nPixels) const
00188 {
00189 if ( m_defaultFromLab == 0 ) return;
00190
00191 cmsDoTransform( m_defaultFromLab, const_cast<Q_UINT8 *>( src ), dst, nPixels );
00192 }
00193
00194
00195 void KisAbstractColorSpace::getSingleChannelPixel(Q_UINT8 *dstPixel, const Q_UINT8 *srcPixel, Q_UINT32 channelIndex)
00196 {
00197 if (channelIndex < m_channels.count()) {
00198
00199 fromQColor(Qt::black, OPACITY_TRANSPARENT, dstPixel);
00200
00201 const KisChannelInfo *channelInfo = m_channels[channelIndex];
00202 memcpy(dstPixel + channelInfo->pos(), srcPixel + channelInfo->pos(), channelInfo->size());
00203 }
00204 }
00205
00206 bool KisAbstractColorSpace::convertPixelsTo(const Q_UINT8 * src,
00207 Q_UINT8 * dst,
00208 KisColorSpace * dstColorSpace,
00209 Q_UINT32 numPixels,
00210 Q_INT32 renderingIntent)
00211 {
00212 if (dstColorSpace->colorSpaceType() == colorSpaceType()
00213 && dstColorSpace->getProfile() == getProfile())
00214 {
00215 if (src!= dst)
00216 memcpy (dst, src, numPixels * pixelSize());
00217
00218 return true;
00219 }
00220
00221 cmsHTRANSFORM tf = 0;
00222
00223 Q_INT32 srcPixelSize = pixelSize();
00224 Q_INT32 dstPixelSize = dstColorSpace->pixelSize();
00225
00226 if (m_lastUsedTransform != 0 && m_lastUsedDstColorSpace != 0) {
00227 if (dstColorSpace->colorSpaceType() == m_lastUsedDstColorSpace->colorSpaceType() &&
00228 dstColorSpace->getProfile() == m_lastUsedDstColorSpace->getProfile()) {
00229 tf = m_lastUsedTransform;
00230 }
00231 }
00232
00233 if (!tf && m_profile && dstColorSpace->getProfile()) {
00234
00235 if (!m_transforms.contains(dstColorSpace)) {
00236 tf = createTransform(dstColorSpace,
00237 m_profile,
00238 dstColorSpace->getProfile(),
00239 renderingIntent);
00240 if (tf) {
00241
00242 m_transforms[dstColorSpace] = tf;
00243 }
00244 }
00245 else {
00246 tf = m_transforms[dstColorSpace];
00247 }
00248
00249 if ( tf ) {
00250 m_lastUsedTransform = tf;
00251 m_lastUsedDstColorSpace = dstColorSpace;
00252 }
00253 }
00254
00255 if (tf) {
00256
00257 cmsDoTransform(tf, const_cast<Q_UINT8 *>(src), dst, numPixels);
00258
00259
00260 while (numPixels > 0) {
00261 Q_UINT8 alpha = getAlpha(src);
00262 dstColorSpace->setAlpha(dst, alpha, 1);
00263
00264 src += srcPixelSize;
00265 dst += dstPixelSize;
00266 numPixels--;
00267 }
00268
00269 return true;
00270 }
00271
00272
00273 while (numPixels > 0) {
00274 QColor color;
00275 Q_UINT8 opacity;
00276
00277 toQColor(src, &color, &opacity);
00278 dstColorSpace->fromQColor(color, opacity, dst);
00279
00280 src += srcPixelSize;
00281 dst += dstPixelSize;
00282 numPixels--;
00283 }
00284
00285 return true;
00286 }
00287
00288
00289 KisColorAdjustment *KisAbstractColorSpace::createBrightnessContrastAdjustment(Q_UINT16 *transferValues)
00290 {
00291 if (!m_profile) return 0;
00292
00293 LPGAMMATABLE transferFunctions[3];
00294 transferFunctions[0] = cmsBuildGamma(256, 1.0);
00295 transferFunctions[1] = cmsBuildGamma(256, 1.0);
00296 transferFunctions[2] = cmsBuildGamma(256, 1.0);
00297
00298 for(int i =0; i < 256; i++)
00299 transferFunctions[0]->GammaTable[i] = transferValues[i];
00300
00301 KisColorAdjustmentImpl *adj = new KisColorAdjustmentImpl;
00302 adj->profiles[1] = cmsCreateLinearizationDeviceLink(icSigLabData, transferFunctions);
00303 cmsSetDeviceClass(adj->profiles[1], icSigAbstractClass);
00304
00305 adj->profiles[0] = m_profile->profile();
00306 adj->profiles[2] = m_profile->profile();
00307 adj->transform = cmsCreateMultiprofileTransform(adj->profiles, 3, m_cmType, m_cmType, INTENT_PERCEPTUAL, 0);
00308 adj->csProfile = m_profile->profile();
00309 return adj;
00310 }
00311
00312 typedef struct {
00313 double Saturation;
00314
00315 } BCHSWADJUSTS, *LPBCHSWADJUSTS;
00316
00317
00318 static int desaturateSampler(register WORD In[], register WORD Out[], register LPVOID )
00319 {
00320 cmsCIELab LabIn, LabOut;
00321 cmsCIELCh LChIn, LChOut;
00322
00323
00324 cmsLabEncoded2Float(&LabIn, In);
00325
00326 cmsLab2LCh(&LChIn, &LabIn);
00327
00328
00329 LChOut.L = LChIn.L;
00330 LChOut.C = 0;
00331 LChOut.h = LChIn.h;
00332
00333 cmsLCh2Lab(&LabOut, &LChOut);
00334
00335
00336 cmsFloat2LabEncoded(Out, &LabOut);
00337
00338 return TRUE;
00339 }
00340
00341 KisColorAdjustment *KisAbstractColorSpace::createDesaturateAdjustment()
00342 {
00343 if (!m_profile) return 0;
00344
00345 KisColorAdjustmentImpl *adj = new KisColorAdjustmentImpl;
00346
00347 adj->profiles[0] = m_profile->profile();
00348 adj->profiles[2] = m_profile->profile();
00349 adj->csProfile = m_profile->profile();
00350
00351 LPLUT Lut;
00352 BCHSWADJUSTS bchsw;
00353
00354 bchsw.Saturation = -25;
00355
00356 adj->profiles[1] = _cmsCreateProfilePlaceholder();
00357 if (!adj->profiles[1])
00358 return NULL;
00359
00360 cmsSetDeviceClass(adj->profiles[1], icSigAbstractClass);
00361 cmsSetColorSpace(adj->profiles[1], icSigLabData);
00362 cmsSetPCS(adj->profiles[1], icSigLabData);
00363
00364 cmsSetRenderingIntent(adj->profiles[1], INTENT_PERCEPTUAL);
00365
00366
00367 Lut = cmsAllocLUT();
00368
00369 cmsAlloc3DGrid(Lut, 32, 3, 3);
00370
00371 if (!cmsSample3DGrid(Lut, desaturateSampler, static_cast<LPVOID>(&bchsw), 0)) {
00372
00373 cmsFreeLUT(Lut);
00374 cmsCloseProfile(adj->profiles[1]);
00375 return NULL;
00376 }
00377
00378
00379
00380 cmsAddTag(adj->profiles[1], icSigDeviceMfgDescTag, (LPVOID) "(krita internal)");
00381 cmsAddTag(adj->profiles[1], icSigProfileDescriptionTag, (LPVOID) "krita saturation abstract profile");
00382 cmsAddTag(adj->profiles[1], icSigDeviceModelDescTag, (LPVOID) "saturation built-in");
00383
00384 cmsAddTag(adj->profiles[1], icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
00385
00386 cmsAddTag(adj->profiles[1], icSigAToB0Tag, (LPVOID) Lut);
00387
00388
00389 cmsFreeLUT(Lut);
00390
00391 adj->transform = cmsCreateMultiprofileTransform(adj->profiles, 3, m_cmType, m_cmType, INTENT_PERCEPTUAL, 0);
00392
00393 return adj;
00394 }
00395
00396 KisColorAdjustment *KisAbstractColorSpace::createPerChannelAdjustment(Q_UINT16 **transferValues)
00397 {
00398 if (!m_profile) return 0;
00399
00400 LPGAMMATABLE *transferFunctions = new LPGAMMATABLE[nColorChannels()+1];
00401
00402 for(uint ch=0; ch < nColorChannels(); ch++) {
00403 transferFunctions[ch] = cmsBuildGamma(256, 1.0);
00404 for(uint i =0; i < 256; i++) {
00405 transferFunctions[ch]->GammaTable[i] = transferValues[ch][i];
00406 }
00407 }
00408
00409 KisColorAdjustmentImpl *adj = new KisColorAdjustmentImpl;
00410 adj->profiles[0] = cmsCreateLinearizationDeviceLink(colorSpaceSignature(), transferFunctions);
00411 adj->profiles[1] = NULL;
00412 adj->profiles[2] = NULL;
00413 adj->csProfile = m_profile->profile();
00414 adj->transform = cmsCreateTransform(adj->profiles[0], m_cmType, NULL, m_cmType, INTENT_PERCEPTUAL, 0);
00415
00416 delete [] transferFunctions;
00417
00418 return adj;
00419 }
00420
00421
00422 void KisAbstractColorSpace::applyAdjustment(const Q_UINT8 *src, Q_UINT8 *dst, KisColorAdjustment *adjustment, Q_INT32 nPixels)
00423 {
00424 KisColorAdjustmentImpl * adj = dynamic_cast<KisColorAdjustmentImpl*>(adjustment);
00425 if (adj)
00426 cmsDoTransform(adj->transform, const_cast<Q_UINT8 *>(src), dst, nPixels);
00427 }
00428
00429
00430 void KisAbstractColorSpace::invertColor(Q_UINT8 * src, Q_INT32 nPixels)
00431 {
00432 QColor c;
00433 Q_UINT8 opacity;
00434 Q_UINT32 psize = pixelSize();
00435
00436 while (nPixels--)
00437 {
00438 toQColor(src, &c, &opacity);
00439 c.setRgb(Q_UINT8_MAX - c.red(), Q_UINT8_MAX - c.green(), Q_UINT8_MAX - c.blue());
00440 fromQColor( c, opacity, src);
00441
00442 src += psize;
00443 }
00444 }
00445
00446 Q_UINT8 KisAbstractColorSpace::difference(const Q_UINT8* src1, const Q_UINT8* src2)
00447 {
00448 if (m_defaultToLab) {
00449
00450 Q_UINT8 lab1[8], lab2[8];
00451 cmsCIELab labF1, labF2;
00452
00453 if (getAlpha(src1) == OPACITY_TRANSPARENT || getAlpha(src2) == OPACITY_TRANSPARENT)
00454 return (getAlpha(src1) == getAlpha(src2) ? 0 : 255);
00455
00456 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8*>( src1 ), lab1, 1);
00457 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8*>( src2 ), lab2, 1);
00458 cmsLabEncoded2Float(&labF1, (WORD *)lab1);
00459 cmsLabEncoded2Float(&labF2, (WORD *)lab2);
00460 double diff = cmsDeltaE(&labF1, &labF2);
00461 if(diff>255)
00462 return 255;
00463 else
00464 return Q_INT8(diff);
00465 }
00466 else {
00467 QColor c1;
00468 Q_UINT8 opacity1;
00469 toQColor(src1, &c1, &opacity1);
00470
00471 QColor c2;
00472 Q_UINT8 opacity2;
00473 toQColor(src2, &c2, &opacity2);
00474
00475 Q_UINT8 red = abs(c1.red() - c2.red());
00476 Q_UINT8 green = abs(c1.green() - c2.green());
00477 Q_UINT8 blue = abs(c1.blue() - c2.blue());
00478 return QMAX(red, QMAX(green, blue));
00479 }
00480 }
00481
00482 void KisAbstractColorSpace::mixColors(const Q_UINT8 **colors, const Q_UINT8 *weights, Q_UINT32 nColors, Q_UINT8 *dst) const
00483 {
00484 Q_UINT32 totalRed = 0, totalGreen = 0, totalBlue = 0, newAlpha = 0;
00485
00486 QColor c;
00487 Q_UINT8 opacity;
00488
00489 while (nColors--)
00490 {
00491
00492 const_cast<KisAbstractColorSpace *>(this)->toQColor(*colors, &c, &opacity);
00493
00494 Q_UINT32 alphaTimesWeight = UINT8_MULT(opacity, *weights);
00495
00496 totalRed += c.red() * alphaTimesWeight;
00497 totalGreen += c.green() * alphaTimesWeight;
00498 totalBlue += c.blue() * alphaTimesWeight;
00499 newAlpha += alphaTimesWeight;
00500
00501 weights++;
00502 colors++;
00503 }
00504
00505 Q_ASSERT(newAlpha <= 255);
00506
00507 if (newAlpha > 0) {
00508 totalRed = UINT8_DIVIDE(totalRed, newAlpha);
00509 totalGreen = UINT8_DIVIDE(totalGreen, newAlpha);
00510 totalBlue = UINT8_DIVIDE(totalBlue, newAlpha);
00511 }
00512
00513
00514 totalRed += 0x80;
00515
00516 Q_UINT32 dstRed = ((totalRed >> 8) + totalRed) >> 8;
00517 Q_ASSERT(dstRed <= 255);
00518
00519 totalGreen += 0x80;
00520 Q_UINT32 dstGreen = ((totalGreen >> 8) + totalGreen) >> 8;
00521 Q_ASSERT(dstGreen <= 255);
00522
00523 totalBlue += 0x80;
00524 Q_UINT32 dstBlue = ((totalBlue >> 8) + totalBlue) >> 8;
00525 Q_ASSERT(dstBlue <= 255);
00526
00527 const_cast<KisAbstractColorSpace *>(this)->fromQColor(QColor(dstRed, dstGreen, dstBlue), newAlpha, dst);
00528 }
00529
00530 void KisAbstractColorSpace::convolveColors(Q_UINT8** colors, Q_INT32 * kernelValues, KisChannelInfo::enumChannelFlags channelFlags,
00531 Q_UINT8 *dst, Q_INT32 factor, Q_INT32 offset, Q_INT32 nColors) const
00532 {
00533 Q_INT32 totalRed = 0, totalGreen = 0, totalBlue = 0, totalAlpha = 0;
00534
00535 QColor dstColor;
00536 Q_UINT8 dstOpacity;
00537
00538 const_cast<KisAbstractColorSpace *>(this)->toQColor(dst, &dstColor, &dstOpacity);
00539
00540 while (nColors--)
00541 {
00542 Q_INT32 weight = *kernelValues;
00543
00544 if (weight != 0) {
00545 QColor c;
00546 Q_UINT8 opacity;
00547 const_cast<KisAbstractColorSpace *>(this)->toQColor( *colors, &c, &opacity );
00548 totalRed += c.red() * weight;
00549 totalGreen += c.green() * weight;
00550 totalBlue += c.blue() * weight;
00551 totalAlpha += opacity * weight;
00552 }
00553 colors++;
00554 kernelValues++;
00555 }
00556
00557
00558 if (channelFlags & KisChannelInfo::FLAG_COLOR) {
00559 const_cast<KisAbstractColorSpace *>(this)->fromQColor(QColor(CLAMP((totalRed / factor) + offset, 0, Q_UINT8_MAX),
00560 CLAMP((totalGreen / factor) + offset, 0, Q_UINT8_MAX),
00561 CLAMP((totalBlue / factor) + offset, 0, Q_UINT8_MAX)),
00562 dstOpacity,
00563 dst);
00564 }
00565 if (channelFlags & KisChannelInfo::FLAG_ALPHA) {
00566 const_cast<KisAbstractColorSpace *>(this)->fromQColor(dstColor, CLAMP((totalAlpha/ factor) + offset, 0, Q_UINT8_MAX), dst);
00567 }
00568
00569 }
00570
00571 void KisAbstractColorSpace::darken(const Q_UINT8 * src, Q_UINT8 * dst, Q_INT32 shade, bool compensate, double compensation, Q_INT32 nPixels) const
00572 {
00573 if (m_defaultToLab) {
00574 Q_UINT16 * labcache = new Q_UINT16[nPixels * 4];
00575 cmsDoTransform( m_defaultToLab, const_cast<Q_UINT8*>( src ), reinterpret_cast<Q_UINT8*>( labcache ), nPixels );
00576 for ( int i = 0; i < nPixels * 4; ++i ) {
00577 if ( compensate ) {
00578 labcache[i] = static_cast<Q_UINT16>( ( labcache[i] * shade ) / ( compensation * 255 ) );
00579 }
00580 else {
00581 labcache[i] = static_cast<Q_UINT16>( labcache[i] * shade / 255 );
00582 }
00583 }
00584 cmsDoTransform( m_defaultFromLab, reinterpret_cast<Q_UINT8*>( labcache ), dst, nPixels );
00585
00586
00587 for ( int i = 0; i < nPixels; ++i ) {
00588 Q_UINT8 alpha = getAlpha( src );
00589 setAlpha( dst, alpha, 1 );
00590 }
00591 delete [] labcache;
00592 }
00593 else {
00594
00595 QColor c;
00596 Q_INT32 psize = pixelSize();
00597
00598 for (int i = 0; i < nPixels; ++i) {
00599
00600 const_cast<KisAbstractColorSpace *>(this)->toQColor(src + (i * psize), &c);
00601 Q_INT32 r, g, b;
00602
00603 if (compensate) {
00604 r = static_cast<Q_INT32>( QMIN(255, (c.red() * shade) / (compensation * 255)));
00605 g = static_cast<Q_INT32>( QMIN(255, (c.green() * shade) / (compensation * 255)));
00606 b = static_cast<Q_INT32>( QMIN(255, (c.blue() * shade) / (compensation * 255)));
00607 }
00608 else {
00609 r = static_cast<Q_INT32>( QMIN(255, (c.red() * shade / 255)));
00610 g = static_cast<Q_INT32>( QMIN(255, (c.green() * shade / 255)));
00611 b = static_cast<Q_INT32>( QMIN(255, (c.blue() * shade / 255)));
00612 }
00613 c.setRgb(r, g, b);
00614
00615 const_cast<KisAbstractColorSpace *>(this)->fromQColor( c, dst + (i * psize));
00616 }
00617 }
00618 }
00619
00620 Q_UINT8 KisAbstractColorSpace::intensity8(const Q_UINT8 * src) const
00621 {
00622 QColor c;
00623 Q_UINT8 opacity;
00624 const_cast<KisAbstractColorSpace *>(this)->toQColor(src, &c, &opacity);
00625 return static_cast<Q_UINT8>((c.red() * 0.30 + c.green() * 0.59 + c.blue() * 0.11) + 0.5);
00626
00627 }
00628
00629
00630 KisID KisAbstractColorSpace::mathToolboxID() const
00631 {
00632 return KisID("Basic");
00633 }
00634
00635 void KisAbstractColorSpace::bitBlt(Q_UINT8 *dst,
00636 Q_INT32 dststride,
00637 KisColorSpace * srcSpace,
00638 const Q_UINT8 *src,
00639 Q_INT32 srcRowStride,
00640 const Q_UINT8 *srcAlphaMask,
00641 Q_INT32 maskRowStride,
00642 Q_UINT8 opacity,
00643 Q_INT32 rows,
00644 Q_INT32 cols,
00645 const KisCompositeOp& op)
00646 {
00647 if (rows <= 0 || cols <= 0)
00648 return;
00649
00650 if (this != srcSpace) {
00651 Q_UINT32 len = pixelSize() * rows * cols;
00652
00653
00654 if (!m_conversionCache.resize( len, QGArray::SpeedOptim )) {
00655 kdWarning() << "Could not allocate enough memory for the conversion!\n";
00656
00657 abort();
00658 }
00659
00660 for (Q_INT32 row = 0; row < rows; row++) {
00661 srcSpace->convertPixelsTo(src + row * srcRowStride,
00662 m_conversionCache.data() + row * cols * pixelSize(), this,
00663 cols);
00664 }
00665
00666
00667 srcRowStride = cols * pixelSize();
00668
00669 bitBlt(dst,
00670 dststride,
00671 m_conversionCache.data(),
00672 srcRowStride,
00673 srcAlphaMask,
00674 maskRowStride,
00675 opacity,
00676 rows,
00677 cols,
00678 op);
00679
00680 }
00681 else {
00682 bitBlt(dst,
00683 dststride,
00684 src,
00685 srcRowStride,
00686 srcAlphaMask,
00687 maskRowStride,
00688 opacity,
00689 rows,
00690 cols,
00691 op);
00692 }
00693 }
00694
00695 QImage KisAbstractColorSpace::convertToQImage(const Q_UINT8 *data, Q_INT32 width, Q_INT32 height,
00696 KisProfile *dstProfile,
00697 Q_INT32 renderingIntent, float )
00698
00699 {
00700 QImage img = QImage(width, height, 32, 0, QImage::LittleEndian);
00701 img.setAlphaBuffer( true );
00702
00703 KisColorSpace * dstCS;
00704
00705 if (dstProfile)
00706 dstCS = m_parent->getColorSpace(KisID("RGBA",""),dstProfile->productName());
00707 else
00708 dstCS = m_parent->getRGB8();
00709
00710 if (data)
00711 convertPixelsTo(const_cast<Q_UINT8 *>(data), img.bits(), dstCS, width * height, renderingIntent);
00712
00713 return img;
00714 }
00715
00716
00717 cmsHTRANSFORM KisAbstractColorSpace::createTransform(KisColorSpace * dstColorSpace,
00718 KisProfile * srcProfile,
00719 KisProfile * dstProfile,
00720 Q_INT32 renderingIntent)
00721 {
00722 KConfig * cfg = KGlobal::config();
00723 bool bpCompensation = cfg->readBoolEntry("useBlackPointCompensation", false);
00724
00725 int flags = 0;
00726
00727 if (bpCompensation) {
00728 flags = cmsFLAGS_BLACKPOINTCOMPENSATION;
00729 }
00730
00731 if (dstColorSpace && dstProfile && srcProfile ) {
00732 cmsHTRANSFORM tf = cmsCreateTransform(srcProfile->profile(),
00733 colorSpaceType(),
00734 dstProfile->profile(),
00735 dstColorSpace->colorSpaceType(),
00736 renderingIntent,
00737 flags);
00738
00739 return tf;
00740 }
00741 return 0;
00742 }
00743
00744 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)
00745 {
00746 Q_UINT8 *dst = dstRowStart;
00747 const Q_UINT8 *src = srcRowStart;
00748 Q_INT32 bytesPerPixel = pixelSize();
00749
00750 while (rows > 0) {
00751 memcpy(dst, src, numColumns * bytesPerPixel);
00752
00753 if (opacity != OPACITY_OPAQUE) {
00754 multiplyAlpha(dst, opacity, numColumns);
00755 }
00756
00757 dst += dstRowStride;
00758 src += srcRowStride;
00759 --rows;
00760 }
00761 }
00762