File indexing completed on 2024-05-05 04:21:07
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #define DEBUG_KP_COLOR 0 0030 0031 0032 #include "kpColor.h" 0033 0034 #include <QDataStream> 0035 0036 #include "kpLogCategories.h" 0037 0038 //--------------------------------------------------------------------- 0039 0040 kpColor::kpColor() 0041 : m_rgbaIsValid(false), 0042 m_rgba(0), 0043 m_colorCacheIsValid(false) 0044 { 0045 } 0046 0047 //--------------------------------------------------------------------- 0048 0049 kpColor::kpColor (int red, int green, int blue, bool isTransparent) 0050 : m_rgba(0), m_colorCacheIsValid(false) 0051 { 0052 #if DEBUG_KP_COLOR 0053 qCDebug(kpLogImagelib) << "kpColor::<ctor>(r=" << red << ",g=" << green << ",b=" << blue 0054 << ",isTrans=" << isTransparent << ")"; 0055 #endif 0056 if (red < 0 || red > 255 || 0057 green < 0 || green > 255 || 0058 blue < 0 || blue > 255) 0059 { 0060 qCCritical(kpLogImagelib) << "kpColor::<ctor>(r=" << red 0061 << ",g=" << green 0062 << ",b=" << blue 0063 << ",t=" << isTransparent 0064 << ") passed out of range values"; 0065 m_rgbaIsValid = false; 0066 return; 0067 } 0068 0069 m_rgba = qRgba (red, green, blue, isTransparent ? 0 : 255/*opaque*/); 0070 m_rgbaIsValid = true; 0071 } 0072 0073 //--------------------------------------------------------------------- 0074 0075 kpColor::kpColor (const QRgb &rgba) 0076 : m_colorCacheIsValid (false) 0077 { 0078 #if DEBUG_KP_COLOR 0079 qCDebug(kpLogImagelib) << "kpColor::<ctor>(rgba=" << (int *) rgba << ")"; 0080 #endif 0081 m_rgba = rgba; 0082 m_rgbaIsValid = true; 0083 } 0084 0085 //--------------------------------------------------------------------- 0086 0087 kpColor::kpColor (const kpColor &rhs) 0088 : m_rgbaIsValid (rhs.m_rgbaIsValid), 0089 m_rgba (rhs.m_rgba), 0090 m_colorCacheIsValid (rhs.m_colorCacheIsValid), 0091 m_colorCache (rhs.m_colorCache) 0092 { 0093 #if DEBUG_KP_COLOR 0094 qCDebug(kpLogImagelib) << "kpColor::<copy_ctor>()"; 0095 #endif 0096 } 0097 0098 //--------------------------------------------------------------------- 0099 0100 // friend 0101 QDataStream &operator<< (QDataStream &stream, const kpColor &color) 0102 { 0103 stream << int (color.m_rgbaIsValid) << int (color.m_rgba); 0104 0105 return stream; 0106 } 0107 0108 //--------------------------------------------------------------------- 0109 0110 // friend 0111 QDataStream &operator>> (QDataStream &stream, kpColor &color) 0112 { 0113 int a, b; 0114 stream >> a >> b; 0115 color.m_rgbaIsValid = a; 0116 color.m_rgba = static_cast<unsigned int> (b); 0117 0118 color.m_colorCacheIsValid = false; 0119 0120 return stream; 0121 } 0122 0123 //--------------------------------------------------------------------- 0124 0125 kpColor &kpColor::operator= (const kpColor &rhs) 0126 { 0127 // (as soon as you add a ptr, you won't be complaining to me that this 0128 // method was unnecessary :)) 0129 0130 if (this == &rhs) { 0131 return *this; 0132 } 0133 0134 m_rgbaIsValid = rhs.m_rgbaIsValid; 0135 m_rgba = rhs.m_rgba; 0136 m_colorCacheIsValid = rhs.m_colorCacheIsValid; 0137 m_colorCache = rhs.m_colorCache; 0138 0139 return *this; 0140 } 0141 0142 bool kpColor::operator== (const kpColor &rhs) const 0143 { 0144 return isSimilarTo (rhs, kpColor::Exact); 0145 } 0146 0147 bool kpColor::operator!= (const kpColor &rhs) const 0148 { 0149 return !(*this == rhs); 0150 } 0151 0152 //--------------------------------------------------------------------- 0153 0154 0155 template <class dtype> 0156 inline dtype square (dtype val) 0157 { 0158 return val * val; 0159 } 0160 0161 //--------------------------------------------------------------------- 0162 0163 // public static 0164 int kpColor::processSimilarity (double colorSimilarity) 0165 { 0166 // sqrt (dr ^ 2 + dg ^ 2 + db ^ 2) <= colorSimilarity * sqrt (255 ^ 2 * 3) 0167 // dr ^ 2 + dg ^ 2 + db ^ 2 <= (colorSimilarity ^ 2) * (255 ^ 2 * 3) 0168 0169 return int (square (colorSimilarity) * (square (255) * 3)); 0170 } 0171 0172 //--------------------------------------------------------------------- 0173 0174 bool kpColor::isSimilarTo (const kpColor &rhs, int processedSimilarity) const 0175 { 0176 // Are we the same? 0177 if (this == &rhs) { 0178 return true; 0179 } 0180 0181 0182 // Do we dither in terms of validity? 0183 if (isValid () != rhs.isValid ()) { 0184 return false; 0185 } 0186 0187 // Are both of us invalid? 0188 if (!isValid ()) { 0189 return true; 0190 } 0191 0192 // --- both are now valid --- 0193 0194 if (m_rgba == rhs.m_rgba) { 0195 return true; 0196 } 0197 0198 if (processedSimilarity == kpColor::Exact) { 0199 return false; 0200 } 0201 0202 0203 return (square (qRed (m_rgba) - qRed (rhs.m_rgba)) + 0204 square (qGreen (m_rgba) - qGreen (rhs.m_rgba)) + 0205 square (qBlue (m_rgba) - qBlue (rhs.m_rgba)) 0206 <= processedSimilarity); 0207 0208 } 0209 0210 //--------------------------------------------------------------------- 0211 0212 // public 0213 bool kpColor::isValid () const 0214 { 0215 return m_rgbaIsValid; 0216 } 0217 0218 //--------------------------------------------------------------------- 0219 0220 // public 0221 int kpColor::red () const 0222 { 0223 if (!m_rgbaIsValid) 0224 { 0225 qCCritical(kpLogImagelib) << "kpColor::red() called with invalid kpColor"; 0226 return 0; 0227 } 0228 0229 return qRed (m_rgba); 0230 } 0231 0232 //--------------------------------------------------------------------- 0233 0234 // public 0235 int kpColor::green () const 0236 { 0237 if (!m_rgbaIsValid) 0238 { 0239 qCCritical(kpLogImagelib) << "kpColor::green() called with invalid kpColor"; 0240 return 0; 0241 } 0242 0243 return qGreen (m_rgba); 0244 } 0245 0246 //--------------------------------------------------------------------- 0247 0248 // public 0249 int kpColor::blue () const 0250 { 0251 if (!m_rgbaIsValid) 0252 { 0253 qCCritical(kpLogImagelib) << "kpColor::blue() called with invalid kpColor"; 0254 return 0; 0255 } 0256 0257 return qBlue (m_rgba); 0258 } 0259 0260 //--------------------------------------------------------------------- 0261 0262 // public 0263 int kpColor::alpha () const 0264 { 0265 if (!m_rgbaIsValid) 0266 { 0267 qCCritical(kpLogImagelib) << "kpColor::alpha() called with invalid kpColor"; 0268 return 0; 0269 } 0270 0271 return qAlpha (m_rgba); 0272 } 0273 0274 //--------------------------------------------------------------------- 0275 0276 // public 0277 bool kpColor::isTransparent () const 0278 { 0279 return (alpha () == 0); 0280 } 0281 0282 //--------------------------------------------------------------------- 0283 0284 // public 0285 QRgb kpColor::toQRgb () const 0286 { 0287 if (!m_rgbaIsValid) 0288 { 0289 qCCritical(kpLogImagelib) << "kpColor::toQRgb() called with invalid kpColor"; 0290 return 0; 0291 } 0292 0293 return m_rgba; 0294 } 0295 0296 //--------------------------------------------------------------------- 0297 0298 // public 0299 QColor kpColor::toQColor () const 0300 { 0301 if (!m_rgbaIsValid) 0302 { 0303 qCCritical(kpLogImagelib) << "kpColor::toQColor() called with invalid kpColor"; 0304 return Qt::black; 0305 } 0306 0307 if (m_colorCacheIsValid) { 0308 return m_colorCache; 0309 } 0310 0311 m_colorCache = QColor(qRed(m_rgba), qGreen(m_rgba), qBlue(m_rgba), qAlpha(m_rgba)); 0312 m_colorCacheIsValid = true; 0313 0314 return m_colorCache; 0315 } 0316 0317 //---------------------------------------------------------------------