Warning, file /office/calligra/libs/pigment/KoColor.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> 0003 * Copyright (C) 2007 Thomas Zander <zander@kde.org> 0004 * Copyright (C) 2007 Cyrille Berger <cberger@cberger.net> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoColor.h" 0023 0024 #include <QColor> 0025 0026 #include <QDomDocument> 0027 0028 #include "DebugPigment.h" 0029 0030 #include "KoColorModelStandardIds.h" 0031 #include "KoColorProfile.h" 0032 #include "KoColorSpace.h" 0033 #include "KoColorSpaceRegistry.h" 0034 #include "KoChannelInfo.h" 0035 0036 0037 class Q_DECL_HIDDEN KoColor::Private 0038 { 0039 public: 0040 Private() : data(0), colorSpace(0) {} 0041 0042 ~Private() { 0043 delete [] data; 0044 } 0045 0046 quint8 * data; 0047 const KoColorSpace * colorSpace; 0048 }; 0049 0050 KoColor::KoColor() 0051 : d(new Private()) 0052 { 0053 d->colorSpace = KoColorSpaceRegistry::instance()->rgb16(0); 0054 d->data = new quint8[d->colorSpace->pixelSize()]; 0055 d->colorSpace->fromQColor(Qt::black, d->data); 0056 d->colorSpace->setOpacity(d->data, OPACITY_OPAQUE_U8, 1); 0057 } 0058 0059 KoColor::KoColor(const KoColorSpace * colorSpace) 0060 : d(new Private()) 0061 { 0062 Q_ASSERT(colorSpace); 0063 d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); 0064 d->data = new quint8[d->colorSpace->pixelSize()]; 0065 memset(d->data, 0, d->colorSpace->pixelSize()); 0066 } 0067 0068 KoColor::~KoColor() 0069 { 0070 delete d; 0071 } 0072 0073 KoColor::KoColor(const QColor & color, const KoColorSpace * colorSpace) 0074 : d(new Private()) 0075 { 0076 Q_ASSERT(color.isValid()); 0077 Q_ASSERT(colorSpace); 0078 d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); 0079 0080 d->data = new quint8[colorSpace->pixelSize()]; 0081 memset(d->data, 0, d->colorSpace->pixelSize()); 0082 0083 d->colorSpace->fromQColor(color, d->data); 0084 } 0085 0086 KoColor::KoColor(const quint8 * data, const KoColorSpace * colorSpace) 0087 : d(new Private()) 0088 { 0089 Q_ASSERT(colorSpace); 0090 Q_ASSERT(data); 0091 d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); 0092 d->data = new quint8[colorSpace->pixelSize()]; 0093 memset(d->data, 0, d->colorSpace->pixelSize()); 0094 memmove(d->data, data, colorSpace->pixelSize()); 0095 } 0096 0097 0098 KoColor::KoColor(const KoColor &src, const KoColorSpace * colorSpace) 0099 : d(new Private()) 0100 { 0101 Q_ASSERT(colorSpace); 0102 d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); 0103 d->data = new quint8[colorSpace->pixelSize()]; 0104 memset(d->data, 0, d->colorSpace->pixelSize()); 0105 0106 src.colorSpace()->convertPixelsTo(src.d->data, d->data, colorSpace, 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); 0107 } 0108 0109 KoColor::KoColor(const KoColor & rhs) 0110 : d(new Private()) 0111 { 0112 d->colorSpace = rhs.colorSpace(); 0113 Q_ASSERT(*d->colorSpace == *KoColorSpaceRegistry::instance()->permanentColorspace(d->colorSpace)); 0114 if (d->colorSpace && rhs.d->data) { 0115 d->data = new quint8[d->colorSpace->pixelSize()]; 0116 memcpy(d->data, rhs.d->data, d->colorSpace->pixelSize()); 0117 } 0118 } 0119 0120 KoColor & KoColor::operator=(const KoColor & rhs) 0121 { 0122 if (this == &rhs) return *this; 0123 0124 delete [] d->data; 0125 d->data = 0; 0126 d->colorSpace = rhs.colorSpace(); 0127 0128 if (rhs.d->colorSpace && rhs.d->data) { 0129 Q_ASSERT(d->colorSpace == KoColorSpaceRegistry::instance()->permanentColorspace(d->colorSpace)); // here we want to do a check on pointer, since d->colorSpace is supposed to already be a permanent one 0130 d->data = new quint8[d->colorSpace->pixelSize()]; 0131 memcpy(d->data, rhs.d->data, d->colorSpace->pixelSize()); 0132 } 0133 return * this; 0134 } 0135 0136 bool KoColor::operator==(const KoColor &other) const 0137 { 0138 if (!(*colorSpace() == *other.colorSpace())) 0139 return false; 0140 return memcmp(d->data, other.d->data, d->colorSpace->pixelSize()) == 0; 0141 } 0142 0143 void KoColor::convertTo(const KoColorSpace * cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) 0144 { 0145 //dbgPigment <<"Our colormodel:" << d->colorSpace->id().name() 0146 // << ", new colormodel: " << cs->id().name() << "\n"; 0147 0148 if (*d->colorSpace == *cs) 0149 return; 0150 0151 quint8 * data = new quint8[cs->pixelSize()]; 0152 memset(data, 0, cs->pixelSize()); 0153 0154 d->colorSpace->convertPixelsTo(d->data, data, cs, 1, renderingIntent, conversionFlags); 0155 0156 delete [] d->data; 0157 d->data = data; 0158 d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(cs); 0159 } 0160 0161 void KoColor::convertTo(const KoColorSpace * cs) 0162 { 0163 convertTo(cs, 0164 KoColorConversionTransformation::internalRenderingIntent(), 0165 KoColorConversionTransformation::internalConversionFlags()); 0166 } 0167 0168 void KoColor::setColor(const quint8 * data, const KoColorSpace * colorSpace) 0169 { 0170 Q_ASSERT(data); 0171 Q_ASSERT(colorSpace); 0172 if(d->colorSpace->pixelSize() != colorSpace->pixelSize()) 0173 { 0174 delete [] d->data; 0175 d->data = new quint8[colorSpace->pixelSize()]; 0176 } 0177 memcpy(d->data, data, colorSpace->pixelSize()); 0178 d->colorSpace = KoColorSpaceRegistry::instance()->permanentColorspace(colorSpace); 0179 } 0180 0181 // To save the user the trouble of doing color->colorSpace()->toQColor(color->data(), &c, &a, profile 0182 void KoColor::toQColor(QColor *c) const 0183 { 0184 Q_ASSERT(c); 0185 if (d->colorSpace && d->data) { 0186 d->colorSpace->toQColor(d->data, c); 0187 } 0188 } 0189 0190 QColor KoColor::toQColor() const 0191 { 0192 QColor c; 0193 toQColor(&c); 0194 return c; 0195 } 0196 0197 void KoColor::fromQColor(const QColor& c) const 0198 { 0199 if (d->colorSpace && d->data) { 0200 d->colorSpace->fromQColor(c, d->data); 0201 } 0202 } 0203 0204 #ifndef NDEBUG 0205 void KoColor::dump() const 0206 { 0207 dbgPigment <<"KoColor (" << this <<")," << d->colorSpace->id() <<""; 0208 QList<KoChannelInfo *> channels = d->colorSpace->channels(); 0209 0210 QList<KoChannelInfo *>::const_iterator begin = channels.constBegin(); 0211 QList<KoChannelInfo *>::const_iterator end = channels.constEnd(); 0212 0213 for (QList<KoChannelInfo *>::const_iterator it = begin; it != end; ++it) { 0214 KoChannelInfo * ch = (*it); 0215 // XXX: setNum always takes a byte. 0216 if (ch->size() == sizeof(quint8)) { 0217 // Byte 0218 dbgPigment <<"Channel (byte):" << ch->name() <<":" << QString().setNum(d->data[ch->pos()]) <<""; 0219 } else if (ch->size() == sizeof(quint16)) { 0220 // Short (may also by an nvidia half) 0221 dbgPigment <<"Channel (short):" << ch->name() <<":" << QString().setNum(*((const quint16 *)(d->data+ch->pos()))) <<""; 0222 } else if (ch->size() == sizeof(quint32)) { 0223 // Integer (may also be float... Find out how to distinguish these!) 0224 dbgPigment <<"Channel (int):" << ch->name() <<":" << QString().setNum(*((const quint32 *)(d->data+ch->pos()))) <<""; 0225 } 0226 } 0227 } 0228 #endif 0229 0230 void KoColor::fromKoColor(const KoColor& src) 0231 { 0232 src.colorSpace()->convertPixelsTo(src.d->data, d->data, colorSpace(), 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); 0233 } 0234 0235 const KoColorProfile * KoColor::profile() const 0236 { 0237 return d->colorSpace->profile(); 0238 } 0239 0240 quint8 * KoColor::data() 0241 { 0242 return d->data; 0243 } 0244 0245 const quint8 * KoColor::data() const 0246 { 0247 return d->data; 0248 } 0249 0250 const KoColorSpace * KoColor::colorSpace() const 0251 { 0252 return d->colorSpace; 0253 } 0254 0255 void KoColor::toXML(QDomDocument& doc, QDomElement& colorElt) const 0256 { 0257 d->colorSpace->colorToXML(d->data, doc, colorElt); 0258 } 0259 0260 void KoColor::setOpacity(quint8 alpha) 0261 { 0262 d->colorSpace->setOpacity(d->data, alpha, 1); 0263 } 0264 void KoColor::setOpacity(qreal alpha) 0265 { 0266 d->colorSpace->setOpacity(d->data, alpha, 1); 0267 } 0268 quint8 KoColor::opacityU8() const 0269 { 0270 return d->colorSpace->opacityU8(d->data); 0271 } 0272 qreal KoColor::opacityF() const 0273 { 0274 return d->colorSpace->opacityF(d->data); 0275 } 0276 0277 KoColor KoColor::fromXML(const QDomElement& elt, const QString & bitDepthId, const QHash<QString, QString> & aliases) 0278 { 0279 QString modelId; 0280 if (elt.tagName() == "CMYK") { 0281 modelId = CMYKAColorModelID.id(); 0282 } else if (elt.tagName() == "RGB") { 0283 modelId = RGBAColorModelID.id(); 0284 } else if (elt.tagName() == "sRGB") { 0285 modelId = RGBAColorModelID.id(); 0286 } else if (elt.tagName() == "Lab") { 0287 modelId = LABAColorModelID.id(); 0288 } else if (elt.tagName() == "XYZ") { 0289 modelId = XYZAColorModelID.id(); 0290 } else if (elt.tagName() == "Gray") { 0291 modelId = GrayAColorModelID.id(); 0292 } else if (elt.tagName() == "YCbCr") { 0293 modelId = YCbCrAColorModelID.id(); 0294 } 0295 QString profileName; 0296 if (elt.tagName() != "sRGB") { 0297 profileName = elt.attribute("space", ""); 0298 const QHash<QString, QString>::ConstIterator it = aliases.find(profileName); 0299 if (it != aliases.end()) { 0300 profileName = it.value(); 0301 } 0302 if (!KoColorSpaceRegistry::instance()->profileByName(profileName)) { 0303 profileName.clear(); 0304 } 0305 } 0306 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, bitDepthId, profileName); 0307 if (cs == 0) { 0308 QList<KoID> list = KoColorSpaceRegistry::instance()->colorDepthList(modelId, KoColorSpaceRegistry::AllColorSpaces); 0309 if (!list.empty()) { 0310 cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, list[0].id(), profileName); 0311 } 0312 } 0313 if (cs) { 0314 KoColor c(cs); 0315 cs->colorFromXML(c.data(), elt); 0316 return c; 0317 } else { 0318 return KoColor(); 0319 } 0320 } 0321 0322 QString KoColor::toQString(const KoColor &color) 0323 { 0324 QStringList ls; 0325 foreach(KoChannelInfo *channel, KoChannelInfo::displayOrderSorted(color.colorSpace()->channels())) { 0326 int realIndex = KoChannelInfo::displayPositionToChannelIndex(channel->displayPosition(), color.colorSpace()->channels()); 0327 ls << channel->name(); 0328 ls << color.colorSpace()->channelValueText(color.data(), realIndex); 0329 } 0330 return ls.join(" "); 0331 }