00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009 #include "vil_colour_space.h"
00010 #include <vcl_cstdlib.h>
00011 #include <vcl_algorithm.h>
00012 #include <vcl_cmath.h>
00013
00014 template <class T>
00015 void vil_colour_space_RGB_to_YIQ(T const in[3], T out[3])
00016 {
00017 out[0] = T(0.299) * in[0] + T(0.587) * in[1] + T(0.114) * in[2];
00018 out[1] = T(0.595716) * in[0] - T(0.274453) * in[1] - T(0.321263) * in[2];
00019 out[2] = T(0.211456) * in[0] - T(0.522591) * in[1] + T(0.311135) * in[2];
00020 }
00021
00022 template <class T>
00023 void vil_colour_space_YIQ_to_RGB(T const in[3], T out[3])
00024 {
00025 out[0] = in[0] + T(0.956296) * in[1] + T(0.621024) * in[2];
00026 out[1] = in[0] - T(0.272122) * in[1] - T(0.647381) * in[2];
00027 out[2] = in[0] - T(1.106989) * in[1] + T(1.704615) * in[2];
00028 }
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 template <class T>
00041 void vil_colour_space_RGB_to_HSV(T r, T g, T b, T *h, T *s, T *v)
00042 {
00043 T max = vcl_max(r, vcl_max(g, b));
00044 T min = vcl_min(r, vcl_min(g, b));
00045
00046
00047 *v = max;
00048
00049
00050 if (max > 0)
00051 *s = (max - min)/max;
00052 else
00053 *s = 0;
00054
00055
00056 if (*s == 0)
00057 *h = T();
00058 else {
00059 T delta = max - min;
00060 if (r == max)
00061 *h = (g - b)/delta;
00062 else if (g == max)
00063 *h = 2 + (b - r)/delta;
00064 else if (b == max)
00065 *h = 4 + (r - g)/delta;
00066 else
00067 vcl_abort();
00068
00069 *h *= 60;
00070 if (*h < 0)
00071 *h += 360;
00072 }
00073 }
00074
00075 template <class T>
00076 void vil_colour_space_HSV_to_RGB(T h, T s, T v, T *r, T *g, T *b)
00077 {
00078 T p1, p2, p3, f, nr=0, ng=0, nb=0;
00079 T xh;
00080 int i;
00081
00082 v = v/255;
00083
00084 #if 0
00085 extern float hue, s, v;
00086
00087 extern long r2, g2, b2;
00088 #endif
00089
00090 h -= int(h/360)*360;
00091 if (h < 0) h += 360;
00092
00093 xh = h / 60;
00094 i = (int)vcl_floor((double)xh);
00095 f = xh - i;
00096 p1 = v * (1 - s);
00097 p2 = v * (1 - (s * f));
00098 p3 = v * (1 - (s * (1 - f)));
00099
00100 switch (i)
00101 {
00102 case 0:
00103 nr = v;
00104 ng = p3;
00105 nb = p1;
00106 break;
00107 case 1:
00108 nr = p2;
00109 ng = v;
00110 nb = p1;
00111 break;
00112 case 2:
00113 nr = p1;
00114 ng = v;
00115 nb = p3;
00116 break;
00117 case 3:
00118 nr = p1;
00119 ng = p2;
00120 nb = v;
00121 break;
00122 case 4:
00123 nr = p3;
00124 ng = p1;
00125 nb = v;
00126 break;
00127 case 5:
00128 nr = v;
00129 ng = p1;
00130 nb = p2;
00131 break;
00132 default:
00133 break;
00134 }
00135
00136 *r = nr * 255;
00137 *g = ng * 255;
00138 *b = nb * 255;
00139 return;
00140 }
00141
00142
00143 template <class T>
00144 void vil_colour_space_RGB_to_YUV(T const in[3], T out[3])
00145 {
00146 out[0] = T(0.299) * in[0] + T(0.587) * in[1] + T(0.114) * in[2];
00147 out[1] = T(0.492) * (in[2] - out[0]);
00148 out[2] = T(0.877) * (in[0] - out[0]);
00149 }
00150
00151
00152 template <class T>
00153 void vil_colour_space_YUV_to_RGB(T const in[3], T out[3])
00154 {
00155
00156
00157
00158 out[0] = in[0] + T(1.1402508551881) * in[2];
00159 out[1] = in[0] - T(0.39473137491174) * in[1] - T(0.5808092090311) * in[2];
00160 out[2] = in[0] + T(2.0325203252033) * in[1];
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 template <class T>
00174 void vil_colour_space_RGB_to_YPbPr_601(T const RGB[3], T YPbPr[3])
00175 {
00176 YPbPr[0] = T(0.299) * RGB[0] + T(0.587) * RGB[1] + T(0.114) * RGB[2];
00177 YPbPr[1] = T(-0.168736)* RGB[0] - T(0.331264) * RGB[1] + T(0.5) * RGB[2];
00178 YPbPr[2] = T(0.5) * RGB[0] - T(0.418688) * RGB[1] - T(0.081312) * RGB[2];
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 template <class T>
00192 void vil_colour_space_YPbPr_601_to_RGB(T const YPbPr[3], T RGB[3])
00193 {
00194 RGB[0] = vcl_max(T(0.0), vcl_min(T(1.0), (YPbPr[0] + T(1.402) * YPbPr[2])));
00195 RGB[1] = vcl_max(T(0.0), vcl_min(T(1.0), (YPbPr[0] - T(0.344136) * YPbPr[1] - T(0.714136) * YPbPr[2])));
00196 RGB[2] = vcl_max(T(0.0), vcl_min(T(1.0), (YPbPr[0] + T(1.772) * YPbPr[1] )));
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 void vil_colour_space_RGB_to_YCbCr_601(const unsigned char RGB[3], unsigned char YCbCr[3])
00212 {
00213
00214 YCbCr[0] = static_cast<unsigned char>(
00215 16.0 + ( 65.738 * RGB[0] + 129.057 * RGB[1] + 25.064 * RGB[2])/256.0 + 0.55555555);
00216 YCbCr[1] = static_cast<unsigned char>(
00217 128.0 + ( -37.945 * RGB[0] - 74.494 * RGB[1] + 112.439 * RGB[2])/256.0 + 0.55555555);
00218 YCbCr[2] = static_cast<unsigned char>(
00219 128.0 + ( 112.439 * RGB[0] - 94.154 * RGB[1] - 18.285 * RGB[2])/256.0 + 0.55555555);
00220 }
00221
00222
00223
00224
00225
00226
00227 void vil_colour_space_YCbCr_601_to_RGB(const unsigned char YCbCr[3], unsigned char RGB[3])
00228 {
00229 RGB[0] = static_cast<unsigned char>(
00230 (298.082 * YCbCr[0] + 408.583 * YCbCr[2]) / 256.0 - 222.921);
00231 RGB[1] = static_cast<unsigned char>(
00232 (298.082 * YCbCr[0] - 100.291 * YCbCr[1] - 208.120 * YCbCr[2]) / 256.0 + 135.576);
00233 RGB[2] = static_cast<unsigned char>(
00234 (298.082 * YCbCr[0] + 516.412 * YCbCr[1] ) / 256.0 - 276.836);
00235 }
00236
00237
00238
00239
00240 #define inst(T) \
00241 template void vil_colour_space_RGB_to_YIQ(T const [3], T [3]); \
00242 template void vil_colour_space_YIQ_to_RGB(T const [3], T [3]); \
00243 template void vil_colour_space_RGB_to_HSV(T, T, T, T *, T *, T *); \
00244 template void vil_colour_space_HSV_to_RGB(T, T, T, T *, T *, T *); \
00245 template void vil_colour_space_RGB_to_YUV(T const [3], T [3]); \
00246 template void vil_colour_space_YUV_to_RGB(T const [3], T [3]); \
00247 template void vil_colour_space_RGB_to_YPbPr_601(T const RGB[3], T YPbPr[3]); \
00248 template void vil_colour_space_YPbPr_601_to_RGB(T const YPbPr[3], T RGB[3])
00249
00250 inst(double);
00251 inst(float);