00001 #ifndef IMG_CS_BASE_H_
00002 #define IMG_CS_BASE_H_
00003
00004
00005
00006 #include "img/img.h"
00007
00008 namespace img {
00009
00010
00011 template<int Channels, typename ScalarType1, bool Safe1,typename ScalarType2, bool Safe2>
00012 inline void convert_gamma_precompensated_rgb_to_linear_rgb(const img::Image<Channels,ScalarType1,Safe1> &gamma_precompensated_rgb_image, img::Image<Channels,ScalarType2,Safe2> &linear_rgb_image)
00013 {
00014 assert(gamma_precompensated_rgb_image.isValid());
00015 assert(!gamma_precompensated_rgb_image.attributes.hasColorspace(SRGB));
00016 assert(gamma_precompensated_rgb_image.attributes.hasRange(0.0,1.0));
00017 ScalarType2 old_gamma;
00018 gamma_precompensated_rgb_image.attributes.getGamma(old_gamma);
00019 assert((old_gamma>0.0)&&(old_gamma<1.0));
00020 if(Safe1 || Safe2){
00021 if(!gamma_precompensated_rgb_image.isValid()) throw ImageException("Invalid rgb image");
00022 if(gamma_precompensated_rgb_image.attributes.hasColorspace(SRGB)) throw ImageException("Invalid colorspace attribute");
00023 if(!gamma_precompensated_rgb_image.attributes.hasRange(0,1)) throw ImageException("Invalid range attribute");
00024 if(!((old_gamma>0.0)&&(old_gamma<1.0))) throw ImageException("Invalid gamma attribute");
00025 }
00026 linear_rgb_image.setZero(gamma_precompensated_rgb_image.width(),gamma_precompensated_rgb_image.height());
00027 linear_rgb_image.attributes=gamma_precompensated_rgb_image.attributes;
00028
00029 for(int channel=0; channel<Channels; ++channel)
00030 for(int x_coord=0; x_coord<gamma_precompensated_rgb_image.width(); ++x_coord)
00031 for(int y_coord=0; y_coord<gamma_precompensated_rgb_image.height(); ++y_coord){
00032 linear_rgb_image.setValue(x_coord,y_coord,channel, pow(ScalarType2(gamma_precompensated_rgb_image.getValue(x_coord,y_coord,channel)),ScalarType2(1.0)/old_gamma));
00033 }
00034 linear_rgb_image.attributes.setGamma(ScalarType2(1.0));
00035 }
00036
00037
00038
00039 template<int Channels, typename ScalarType1, bool Safe1,typename ScalarType2, bool Safe2>
00040 inline void convert_linear_rgb_to_gamma_precompensated_rgb(const img::Image<Channels,ScalarType1,Safe1> &linear_rgb_image, img::Image<Channels,ScalarType2,Safe2> &gamma_precompensated_rgb_image, ScalarType2 gamma=ScalarType2(1.0/2.2))
00041 {
00042 assert(linear_rgb_image.isValid());
00043 assert(!linear_rgb_image.attributes.hasColorspace(SRGB));
00044 assert(linear_rgb_image.attributes.hasRange(0.0,1.0));
00045 assert(linear_rgb_image.attributes.hasGamma(1.0));
00046 assert((gamma>0.0)&&(gamma<1.0));
00047 if(Safe1 || Safe2){
00048 if(!linear_rgb_image.isValid()) throw img::ImageException("Invalid rgb image");
00049 if(linear_rgb_image.attributes.hasColorspace(SRGB)) throw ImageException("Invalid colorspace attribute");
00050 if(!linear_rgb_image.attributes.hasRange(0.0,1.0)) throw ImageException("Invalid range attribute");
00051 if(!linear_rgb_image.attributes.hasGamma(1.0)) throw ImageException("Invalid gamma attribute");
00052 if(!((gamma>0.0)&&(gamma<1.0))) throw ImageException("Invalid gamma parameter");
00053 }
00054 gamma_precompensated_rgb_image.setZero(linear_rgb_image.width(),linear_rgb_image.height());
00055 gamma_precompensated_rgb_image.attributes=linear_rgb_image.attributes;
00056
00057 for(int channel=0; channel<Channels; ++channel)
00058 for(int x_coord=0; x_coord<linear_rgb_image.width(); ++x_coord)
00059 for(int y_coord=0; y_coord<linear_rgb_image.height(); ++y_coord){
00060 gamma_precompensated_rgb_image.setValue(x_coord,y_coord,channel, pow(ScalarType2(linear_rgb_image.getValue(x_coord,y_coord,channel)),gamma));
00061 }
00062 gamma_precompensated_rgb_image.attributes.setGamma(gamma);
00063 }
00064
00065
00066 template<int Channels, typename ScalarType1, bool Safe1,typename ScalarType2, bool Safe2>
00067 inline void convert_gamma_precompensated_srgb_to_linear_srgb(const img::Image<Channels,ScalarType1,Safe1> &gamma_precompensated_srgb_image, img::Image<Channels,ScalarType2,Safe2> &linear_srgb_image)
00068 {
00069 assert(gamma_precompensated_srgb_image.isValid());
00070 assert(gamma_precompensated_srgb_image.attributes.hasColorspace(SRGB));
00071 assert(gamma_precompensated_srgb_image.attributes.hasRange(0.0,1.0));
00072 assert(!gamma_precompensated_srgb_image.attributes.hasGamma(1.0));
00073 if(Safe1 || Safe2){
00074 if(!gamma_precompensated_srgb_image.isValid()) throw ImageException("Invalid rgb image");
00075 if(!gamma_precompensated_srgb_image.attributes.hasColorspace(SRGB)) throw ImageException("Invalid colorspace attribute");
00076 if(!gamma_precompensated_srgb_image.attributes.hasRange(0,1)) throw ImageException("Invalid range attribute");
00077 if(gamma_precompensated_srgb_image.attributes.hasGamma(1.0)) throw ImageException("Invalid gamma attribute");
00078 }
00079 linear_srgb_image.setZero(gamma_precompensated_srgb_image.width(),gamma_precompensated_srgb_image.height());
00080 linear_srgb_image.attributes=gamma_precompensated_srgb_image.attributes;
00081
00082 for(int channel=0; channel<Channels; ++channel)
00083 for(int x_coord=0; x_coord<gamma_precompensated_srgb_image.width(); ++x_coord)
00084 for(int y_coord=0; y_coord<gamma_precompensated_srgb_image.height(); ++y_coord){
00085 ScalarType2 value = ScalarType2(gamma_precompensated_srgb_image.getValue(x_coord,y_coord,channel));
00086 if(value<=ScalarType2(0.04045))
00087 value = value / ScalarType2(12.92);
00088 else
00089 value = pow( (value+ScalarType2(0.055)) / ScalarType2(1.055), ScalarType2(2.4) );
00090 linear_srgb_image.setValue(x_coord, y_coord, channel, value);
00091 }
00092 linear_srgb_image.attributes.setGamma(ScalarType2(1.0));
00093 }
00094
00095
00096 template<int Channels, typename ScalarType1, bool Safe1,typename ScalarType2, bool Safe2>
00097 inline void convert_linear_srgb_to_gamma_precompensated_srgb(const img::Image<Channels,ScalarType1,Safe1> &linear_srgb_image, img::Image<Channels,ScalarType2,Safe2> &gamma_precompensated_srgb_image)
00098 {
00099 assert(linear_srgb_image.isValid());
00100 assert(linear_srgb_image.attributes.hasColorspace(SRGB));
00101 assert(linear_srgb_image.attributes.hasRange(0.0,1.0));
00102 assert(linear_srgb_image.attributes.hasGamma(1.0));
00103 if(Safe1 || Safe2){
00104 if(!linear_srgb_image.isValid()) throw img::ImageException("Invalid rgb image");
00105 if(!linear_srgb_image.attributes.hasColorspace(SRGB)) throw ImageException("Invalid colorspace attribute");
00106 if(!linear_srgb_image.attributes.hasRange(0.0,1.0)) throw ImageException("Invalid range attribute");
00107 if(!linear_srgb_image.attributes.hasGamma(1.0)) throw ImageException("Invalid gamma attribute");
00108 }
00109 gamma_precompensated_srgb_image.setZero(linear_srgb_image.width(),linear_srgb_image.height());
00110 gamma_precompensated_srgb_image.attributes=linear_srgb_image.attributes;
00111
00112 for(int channel=0; channel<Channels; ++channel)
00113 for(int x_coord=0; x_coord<linear_srgb_image.width(); ++x_coord)
00114 for(int y_coord=0; y_coord<linear_srgb_image.height(); ++y_coord){
00115 ScalarType2 value = ScalarType2(linear_srgb_image.getValue(x_coord,y_coord,channel));
00116 if(value<=ScalarType2(0.0031308))
00117 value = value * ScalarType2(12.92);
00118 else
00119 value = (ScalarType2(1.055) * pow(value, ScalarType2(1.0/2.4))) - ScalarType2(0.055);
00120 gamma_precompensated_srgb_image.setValue(x_coord, y_coord, channel, value);
00121 }
00122 gamma_precompensated_srgb_image.attributes.setGamma(ScalarType2(2.2));
00123 }
00124
00125
00126 template<typename ScalarType1, bool Safe1,typename ScalarType2, bool Safe2>
00127 inline void convert_srgb_to_xyz(const img::Image<3,ScalarType1,Safe1> &rgb_image, img::Image<3,ScalarType2,Safe2> &xyz_image)
00128 {
00129 assert( rgb_image.isValid());
00130 assert( rgb_image.attributes.hasRange(0.0,1.0));
00131 assert( rgb_image.attributes.hasGamma(1.0));
00132 assert( rgb_image.attributes.hasColorspace(img::RGB) );
00133 if(Safe1 || Safe2){
00134 if(!rgb_image.isValid()) throw img::ImageException("Invalid rgb image");
00135 if(!rgb_image.attributes.hasRange(0.0,1.0)) throw img::ImageException("Invalid range attribute");
00136 if(!rgb_image.attributes.hasGamma(1.0)) throw img::ImageException("Invalid gamma attribute");
00137 if(!rgb_image.attributes.hasColorspace(img::RGB)) throw img::ImageException("Invalid colorspace attribute");
00138 }
00139 xyz_image.setZero(rgb_image.width(),rgb_image.height());
00140 xyz_image.attributes=rgb_image.attributes;
00141
00142 for(int x_coord=0; x_coord<rgb_image.width(); ++x_coord)
00143 for(int y_coord=0; y_coord<rgb_image.height(); ++y_coord){
00144 const ScalarType2 R = static_cast<ScalarType2>(rgb_image.getValue(x_coord,y_coord,0));
00145 const ScalarType2 G = static_cast<ScalarType2>(rgb_image.getValue(x_coord,y_coord,1));
00146 const ScalarType2 B = static_cast<ScalarType2>(rgb_image.getValue(x_coord,y_coord,2));
00147
00148 xyz_image.setValue(x_coord,y_coord,0, ( 0.412453f*R + 0.357580f*G + 0.180423f*B ) );
00149 xyz_image.setValue(x_coord,y_coord,1, ( 0.212671f*R + 0.715160f*G + 0.072169f*B ) );
00150 xyz_image.setValue(x_coord,y_coord,2, ( 0.019334f*R + 0.119193f*G + 0.950227f*B ) );
00151 }
00152 xyz_image.setColorspace(img::CIE_XYZ);
00153 }
00154
00155
00156 template<typename ScalarType1, bool Safe1,typename ScalarType2, bool Safe2>
00157 inline void convert_xyz_to_rgb(const img::Image<3,ScalarType1,Safe1> &xyz_image, img::Image<3,ScalarType2,Safe2> &rgb_image)
00158 {
00159 assert( xyz_image.isValid());
00160 assert( xyz_image.attributes.hasRange(0.0,1.0));
00161 assert( xyz_image.attributes.hasGamma(1.0));
00162 assert( xyz_image.attributes.hasColorspace(img::CIE_XYZ) );
00163
00164 if(Safe1 || Safe2){
00165 if(!xyz_image.isValid()) throw img::ImageException("Invalid xyz image");
00166 if(!xyz_image.attributes.hasRange(0.0,1.0)) throw img::ImageException("Invalid range attribute");
00167 if(!xyz_image.attributes.hasGamma(1.0)) throw img::ImageException("Invalid gamma attribute");
00168 if(!rgb_image.attributes.hasColorspace(img::CIE_XYZ)) throw img::ImageException("Invalid colorspace attribute");
00169 }
00170 rgb_image.setZero(xyz_image.width(),xyz_image.height());
00171 rgb_image.attributes=xyz_image.attributes;
00172
00173 for(int x=0; x<xyz_image.width(); ++x)
00174 for(int y=0; y<xyz_image.height(); ++y){
00175 const ScalarType2 X = static_cast<ScalarType2>(xyz_image.getValue(x,y,0));
00176 const ScalarType2 Y = static_cast<ScalarType2>(xyz_image.getValue(x,y,1));
00177 const ScalarType2 Z = static_cast<ScalarType2>(xyz_image.getValue(x,y,2));
00178
00179 const ScalarType2 R = 3.240479f*X + -1.537150f*Y + -0.498535f*Z;
00180 const ScalarType2 G = -0.969256f*X + 1.875992f*Y + 0.041556f*Z;
00181 const ScalarType2 B = 0.055648f*X + -0.204043f*Y + 1.057311f*Z;
00182
00183 rgb_image.setValue(x,y,0, ( R<0.0f?0.0f:(R>1.0f?1.0f:R) ) );
00184 rgb_image.setValue(x,y,1, ( G<0.0f?0.0f:(G>1.0f?1.0f:G) ) );
00185 rgb_image.setValue(x,y,2, ( B<0.0f?0.0f:(B>1.0f?1.0f:B) ) );
00186 }
00187 rgb_image.setColorspace(img::RGB);
00188 }
00189
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 }
00247
00248 #endif