1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_basegfx.hxx" 26 27 #include <basegfx/numeric/ftools.hxx> 28 #include <basegfx/color/bcolor.hxx> 29 #include <basegfx/color/bcolortools.hxx> 30 31 ////////////////////////////////////////////////////////////////////////////// 32 33 namespace basegfx { namespace tools 34 { rgb2hsl(const BColor & rRGBColor)35 BColor rgb2hsl(const BColor& rRGBColor) 36 { 37 const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue(); 38 const double minVal = ::std::min( ::std::min( r, g ), b ); 39 const double maxVal = ::std::max( ::std::max( r, g ), b ); 40 const double d = maxVal - minVal; 41 42 double h=0, s=0, l=0; 43 44 l = (maxVal + minVal) / 2.0; 45 46 if( ::basegfx::fTools::equalZero(d) ) 47 { 48 s = h = 0; // hue undefined (achromatic case) 49 } 50 else 51 { 52 s = l > 0.5 ? d/(2.0-maxVal-minVal) : 53 d/(maxVal + minVal); 54 55 if( r == maxVal ) 56 h = (g - b)/d; 57 else if( g == maxVal ) 58 h = 2.0 + (b - r)/d; 59 else 60 h = 4.0 + (r - g)/d; 61 62 h *= 60.0; 63 64 if( h < 0.0 ) 65 h += 360.0; 66 } 67 68 return BColor(h,s,l); 69 } 70 hsl2rgbHelper(double nValue1,double nValue2,double nHue)71 static inline double hsl2rgbHelper( double nValue1, double nValue2, double nHue ) 72 { 73 // clamp hue to [0,360] 74 nHue = fmod( nHue, 360.0 ); 75 76 // cope with wrap-arounds 77 if( nHue < 0.0 ) 78 nHue += 360.0; 79 80 if( nHue < 60.0 ) 81 return nValue1 + (nValue2 - nValue1)*nHue/60.0; 82 else if( nHue < 180.0 ) 83 return nValue2; 84 else if( nHue < 240.0 ) 85 return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0; 86 else 87 return nValue1; 88 } 89 hsl2rgb(const BColor & rHSLColor)90 BColor hsl2rgb(const BColor& rHSLColor) 91 { 92 const double h=rHSLColor.getRed(), s=rHSLColor.getGreen(), l=rHSLColor.getBlue(); 93 94 if( fTools::equalZero(s) ) 95 return BColor(l, l, l ); // achromatic case 96 97 const double nVal1( l <= 0.5 ? l*(1.0 + s) : l + s - l*s ); 98 const double nVal2( 2.0*l - nVal1 ); 99 100 return BColor( 101 hsl2rgbHelper(nVal2, 102 nVal1, 103 h + 120.0), 104 hsl2rgbHelper(nVal2, 105 nVal1, 106 h), 107 hsl2rgbHelper(nVal2, 108 nVal1, 109 h - 120.0) ); 110 } 111 rgb2hsv(const BColor & rRGBColor)112 BColor rgb2hsv(const BColor& rRGBColor) 113 { 114 const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue(); 115 const double maxVal = std::max(std::max(r,g),b); 116 const double minVal = std::min(std::min(r,g),b); 117 const double delta = maxVal-minVal; 118 119 double h=0, s=0, v=0; 120 121 v = maxVal; 122 if( fTools::equalZero(v) ) 123 s = 0; 124 else 125 s = delta / v; 126 127 if( !fTools::equalZero(s) ) 128 { 129 if( maxVal == r ) 130 { 131 h = (g - b) / delta; 132 } 133 else if( maxVal == g ) 134 { 135 h = 2.0 + (b - r) / delta; 136 } 137 else 138 { 139 h = 4.0 + (r - g) / delta; 140 } 141 142 h *= 60.0; 143 144 if( h < 0 ) 145 h += 360; 146 } 147 148 return BColor(h,s,v); 149 } 150 hsv2rgb(const BColor & rHSVColor)151 BColor hsv2rgb(const BColor& rHSVColor) 152 { 153 double h=rHSVColor.getRed(); 154 const double s=rHSVColor.getGreen(), v=rHSVColor.getBlue(); 155 156 if( fTools::equalZero(s) ) 157 { 158 // achromatic case: no hue. 159 return BColor(v,v,v); 160 } 161 else 162 { 163 if( fTools::equal(h,360) ) 164 h = 0; // 360 degrees is equivalent to 0 degrees 165 166 h /= 60.0; 167 const sal_Int32 intval = static_cast< sal_Int32 >( h ); 168 const double f = h - intval; 169 const double p = v*(1.0-s); 170 const double q = v*(1.0-(s*f)); 171 const double t = v*(1.0-(s*(1.0-f))); 172 173 /* which hue area? */ 174 switch( intval ) 175 { 176 case 0: 177 return BColor(v,t,p); 178 179 case 1: 180 return BColor(q,v,p); 181 182 case 2: 183 return BColor(p,v,t); 184 185 case 3: 186 return BColor(p,q,v); 187 188 case 4: 189 return BColor(t,p,v); 190 191 case 5: 192 return BColor(v,p,q); 193 194 default: 195 // hue overflow 196 return BColor(); 197 } 198 } 199 } 200 rgb2yiq(const BColor & rRGBColor)201 BColor rgb2yiq(const BColor& rRGBColor) 202 { 203 // from Foley, van Dam, Computer Graphics 204 const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue(); 205 return BColor( 206 0.299*r + 0.587*g + 0.114*b, 207 0.596*r - 0.274*g - 0.322*b, 208 0.211*r - 0.522*g + 0.311*b); 209 } 210 yiq2rgb(const BColor & rYIQColor)211 BColor yiq2rgb(const BColor& rYIQColor) 212 { 213 // from Foley, van Dam, Computer Graphics 214 const double y=rYIQColor.getRed(), i=rYIQColor.getGreen(), q=rYIQColor.getBlue(); 215 return BColor( 216 y + 0.956*i + 0.623*q, 217 y - 0.272*i - 0.648*q, 218 y - 1.105*i + 1.705*q ); 219 } 220 ciexyz2rgb(const BColor & rXYZColor)221 BColor ciexyz2rgb( const BColor& rXYZColor ) 222 { 223 // from Poynton color faq, and SMPTE RP 177-1993, Derivation 224 // of Basic Television Color Equations 225 const double x=rXYZColor.getRed(), y=rXYZColor.getGreen(), z=rXYZColor.getBlue(); 226 return BColor( 227 3.240479*x - 1.53715*y - 0.498535*z, 228 -0.969256*x + 1.875991*y + 0.041556*z, 229 0.055648*x - 0.204043*y + 1.057311*z ); 230 } 231 rgb2ciexyz(const BColor & rRGBColor)232 BColor rgb2ciexyz( const BColor& rRGBColor ) 233 { 234 // from Poynton color faq, and SMPTE RP 177-1993, Derivation 235 // of Basic Television Color Equations 236 const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue(); 237 return BColor( 238 0.412453*r + 0.35758*g + 0.180423*b, 239 0.212671*r + 0.71516*g + 0.072169*b, 240 0.019334*r + 0.119193*g + 0.950227*b); 241 } 242 rgb2ypbpr(const BColor & rRGBColor)243 BColor rgb2ypbpr(const BColor& rRGBColor) 244 { 245 const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue(); 246 return BColor( 247 0.299*r + 0.587*g + 0.114*b, 248 -0.168736*r - 0.331264*g + 0.5*b, 249 0.5*r - 0.418688*g - 0.081312*b); 250 } 251 ypbpr2rgb(const BColor & rYPbPrColor)252 BColor ypbpr2rgb(const BColor& rYPbPrColor) 253 { 254 const double y=rYPbPrColor.getRed(), pb=rYPbPrColor.getGreen(), pr=rYPbPrColor.getBlue(); 255 return BColor( 256 1.*y + 0.*pb + 1.402*pr, 257 1.*y - 0.344136*pb - 0.714136*pr, 258 1.*y + 1.772*pb + 0.*pr); 259 } 260 261 } } // end of namespace basegfx 262 263 ////////////////////////////////////////////////////////////////////////////// 264 // eof 265