00001 /* 00002 File: Colour.cc 00003 00004 Function: Implements Colour.h 00005 00006 Author(s): Andrew Willmott 00007 00008 Copyright: (c) 1995-2000, Andrew Willmott 00009 00010 Notes: Useful info on colour (Gamma & Colour FAQs): 00011 http://www.inforamp.net/~poynton/notes/colour_and_gamma 00012 Useful info on colour transforms: 00013 http://www.sgi.com/grafica/matrix/index.html 00014 http://www.sgi.com/grafica/interp/index.html 00015 */ 00016 00017 #include "gcl/Colour.h" 00018 #include "gcl/Geometry.h" 00019 00032 Colour &ClipColour(Colour &c) 00033 { 00034 if (c[0] > 1.0) c[0] = 1.0; 00035 if (c[0] < 0.0) c[0] = 0.0; 00036 if (c[1] > 1.0) c[1] = 1.0; 00037 if (c[1] < 0.0) c[1] = 0.0; 00038 if (c[2] > 1.0) c[2] = 1.0; 00039 if (c[2] < 0.0) c[2] = 0.0; 00040 00041 return(c); 00042 } 00043 00044 Colour &ClipColourZero(Colour &c) 00045 { 00046 if (c[0] < 0.0) c[0] = 0.0; 00047 if (c[1] < 0.0) c[1] = 0.0; 00048 if (c[2] < 0.0) c[2] = 0.0; 00049 00050 return(c); 00051 } 00052 00053 Colour HSVCol(ClrReal hue, ClrReal saturation, ClrReal value) 00054 // Convert HSV to RGB... 00055 { 00056 hue = hue - 360 * floor(hue / 360); 00057 Int face = (Int) floor(hue / 120); 00058 ClrReal d = (hue - 120 * face) / 60; 00059 Colour result; 00060 00061 if (face == 3) 00062 face--; 00063 00064 result[face] = value; 00065 00066 if (d > 1) 00067 { 00068 result[(face + 1) % 3] = value * (1 - saturation * (2 - d)); 00069 result[(face + 2) % 3] = value * (1 - saturation); 00070 } 00071 else 00072 { 00073 result[(face + 1) % 3] = value * (1 - saturation); 00074 result[(face + 2) % 3] = value * (1 - saturation * d); 00075 } 00076 00077 return(result); 00078 } 00079 00080 // --- Colour transformations ---------------- 00081 00082 ClrTrans RGBScale(ClrReal rscale, ClrReal gscale, ClrReal bscale) 00083 { 00084 return(HScale4f(Colour(rscale, gscale, bscale))); 00085 } 00086 00087 ClrTrans RGBToLum() 00088 { 00089 ClrTrans result; 00090 00091 result[0] = Vec4f(cRGBToLum, 0.0); 00092 result[1] = Vec4f(cRGBToLum, 0.0); 00093 result[2] = Vec4f(cRGBToLum, 0.0); 00094 result[3] = vl_w; 00095 00096 return(result); 00097 } 00098 00099 ClrTrans RGBSaturate(ClrReal sat) 00100 { 00101 // saturate by interpolating with greyscale pixel 00102 return(Mix(RGBToLum(), ClrTrans(vl_I), sat)); 00103 } 00104 00105 ClrTrans RGBReplace(const Colour &c) 00106 // replace with colour c 00107 { 00108 ClrTrans result = vl_0; 00109 00110 result[0][3] = c[0]; 00111 result[1][3] = c[1]; 00112 result[2][3] = c[2]; 00113 result[3][3] = 1.0; 00114 00115 return(result); 00116 } 00117 00118 ClrTrans RGBPixelMix(ClrReal mix, const Colour &c) 00119 // If you use c = cBlack, mix < 1.0 will darken the image, 00120 // and mix > 1.0 will lighten it. 00121 // If you use the average colour of an image, c = img.AverageColour(), 00122 // mix < 1.0 will lower contrast, mix > 1.0 raise it. 00123 { 00124 return(Mix(RGBReplace(c), ClrTrans(vl_I), mix)); 00125 } 00126 00127 ClrTrans RGBOffset(const Colour &c) 00128 { 00129 return(HTrans4f(c)); 00130 } 00131 00132 ClrTrans RGBHueRotate(ClrReal degrees) 00133 { 00134 ClrTrans trans, shear; 00135 Colour newLum; 00136 00137 // align grey vector with z axis (vl_z) 00138 trans = HRot4f(norm(Colour(1, -1, 0)), DegsToRads(45)); 00139 00140 // what is the luminance vector in the new space? 00141 newLum = xform(trans, cRGBToLum); 00142 // shear so plane parallel to this vector is now horizontal (x-y) 00143 // if dot(x, newLum) = c, (shear * x)[2] * newLum[2] = c, 00144 // i.e. is constant 00145 shear = vl_I; 00146 shear[2][0] = newLum[0] / newLum[2]; 00147 shear[2][1] = newLum[1] / newLum[2]; 00148 trans = xform(trans, shear); 00149 00150 // rotate the hue! 00151 trans = xform(trans, HRot4f(vl_z, DegsToRads(degrees))); 00152 00153 // unshear 00154 shear[2][0] = -shear[2][0]; 00155 shear[2][1] = -shear[2][1]; 00156 trans = xform(trans, shear); 00157 // unrotate 00158 trans = xform(trans, HRot4f(norm(Colour(1, -1, 0)), DegsToRads(-45))); 00159 00160 return(trans); 00161 } 00162 00163 Colour YUVToRGB(const Colour &yuv) 00164 { 00165 Colour rgb; 00166 00167 rgb[0] = yuv[0] + 1.4075 * (yuv[2] - 0.5); 00168 rgb[1] = yuv[0] - 0.3455 * (yuv[1] - 0.5) - 0.7169 * (yuv[2] - 0.5); 00169 rgb[2] = yuv[0] + 1.7790 * (yuv[1] - 0.5); 00170 00171 return(rgb); 00172 } 00173 00174 Colour RGBToYUV(const Colour &rgb) 00175 { 00176 Colour yuv; 00177 00178 yuv[0] = rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114; 00179 yuv[1] = rgb[0] * -0.1687 + rgb[1] * -0.3313 + rgb[2] * 0.500 + 0.5; 00180 yuv[2] = rgb[0] * 0.500 + rgb[1] * -0.4187 + rgb[2] * -0.0813 + 0.5; 00181 00182 return(yuv); 00183 } 00184 00185 #ifdef CL_TMPL_INST 00186 template class Array<Colour>; 00187 #endif