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