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