1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/PTdecode/CImg-1.3.0/plugins/draw_gradient.h Mon Aug 03 14:09:20 2009 +0100 1.3 @@ -0,0 +1,248 @@ 1.4 +/* 1.5 + # 1.6 + # File : draw_gradient.h 1.7 + # ( C++ header file - CImg plug-in ) 1.8 + # 1.9 + # Description : Plugin that can be used to draw color gradient on images. 1.10 + # This file is a part of the CImg Library project. 1.11 + # ( http://cimg.sourceforge.net ) 1.12 + # 1.13 + # Copyright : Jerome Boulanger 1.14 + # ( http://www.ricam.oeaw.ac.at/people/page.cgi?firstn=Jerome;lastn=Boulanger ) 1.15 + # 1.16 + # License : CeCILL v2.0 1.17 + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) 1.18 + # 1.19 + # This software is governed by the CeCILL license under French law and 1.20 + # abiding by the rules of distribution of free software. You can use, 1.21 + # modify and/ or redistribute the software under the terms of the CeCILL 1.22 + # license as circulated by CEA, CNRS and INRIA at the following URL 1.23 + # "http://www.cecill.info". 1.24 + # 1.25 + # As a counterpart to the access to the source code and rights to copy, 1.26 + # modify and redistribute granted by the license, users are provided only 1.27 + # with a limited warranty and the software's author, the holder of the 1.28 + # economic rights, and the successive licensors have only limited 1.29 + # liability. 1.30 + # 1.31 + # In this respect, the user's attention is drawn to the risks associated 1.32 + # with loading, using, modifying and/or developing or reproducing the 1.33 + # software by the user in light of its specific status of free software, 1.34 + # that may mean that it is complicated to manipulate, and that also 1.35 + # therefore means that it is reserved for developers and experienced 1.36 + # professionals having in-depth computer knowledge. Users are therefore 1.37 + # encouraged to load and test the software's suitability as regards their 1.38 + # requirements in conditions enabling the security of their systems and/or 1.39 + # data to be ensured and, more generally, to use and operate it in the 1.40 + # same conditions as regards security. 1.41 + # 1.42 + # The fact that you are presently reading this means that you have had 1.43 + # knowledge of the CeCILL license and that you accept its terms. 1.44 + # 1.45 +*/ 1.46 + 1.47 +#ifndef cimg_plugin_draw_gradient 1.48 +#define cimg_plugin_draw_gradient 1.49 + 1.50 +// Convert the couple (shape,profile) into a description string 1.51 +static inline const char *get_gradient_str(const int shape, const int profile) { 1.52 + static char buf[128]; 1.53 + switch(shape) { 1.54 + case 0: std::sprintf(buf,"linear shape and");break; 1.55 + case 1: std::sprintf(buf,"spheric shape and");break; 1.56 + case 2: std::sprintf(buf,"conic shape and");break; 1.57 + case 3: std::sprintf(buf,"square shape and");break; 1.58 + case 4: std::sprintf(buf,"rectangle (L1) shape and");break; 1.59 + case 5: std::sprintf(buf,"rectangle (Linf) shape and");break; 1.60 + case 6: std::sprintf(buf,"Gaussian shape and");break; 1.61 + default: std::sprintf(buf,"undefined shape and");break; 1.62 + } 1.63 + switch(profile) { 1.64 + case 0: std::strcat(buf," linear profile");break; 1.65 + case 1: std::strcat(buf," wave profile");break; 1.66 + case 2: std::strcat(buf," ring/bar profile");break; 1.67 + case 3: std::strcat(buf," exponential");break; 1.68 + case 4: std::strcat(buf," vanishing wave profile");break; 1.69 + case 5: std::strcat(buf," vanishing ring/bar profile");break; 1.70 + case 6: std::strcat(buf," circ diffraction (Airy) profile");break; 1.71 + case 7: std::strcat(buf," rect diffraction (sinc2) profile");break; 1.72 + default: std::strcat(buf," undefined profile");break; 1.73 + } 1.74 + return buf; 1.75 +} 1.76 + 1.77 +template<typename tc> 1.78 +void _draw_gradient_profile(T *const ptr, const float opacity, const float r, 1.79 + const tc *const color0, const tc *const color1, 1.80 + const int profile) { 1.81 + const unsigned int id = (color0?1:0) + (color1?2:0); 1.82 + const tc col0 = color0?*color0:0, col1 = color1?*color1:0; 1.83 + switch(profile) { 1.84 + case 0: { // linear 1.85 + switch(id) { // map the 3 cases 1.86 + case 3: *ptr = (T)((1-opacity)**ptr + opacity*(col0*(1.f-r)+col1*r)); break; 1.87 + case 1: if (r<1) *ptr = (T)((1-opacity*(1-r))**ptr + col0*opacity*(1-r)); break; 1.88 + case 2: if (r>0) *ptr = (T)((1-opacity*r)**ptr + col1*opacity*r); break; 1.89 + default: break; 1.90 + } break; 1.91 + } 1.92 + case 1: { // waves 1.93 + const float f = (1 - (float)std::cos(4.5f*r*2.f*cimg::valuePI))/2; 1.94 + switch(id) { // map the 3 cases 1.95 + case 3: *ptr = (T)((1-opacity)**ptr + opacity*(col0*(1.f-f)+col1*f)); break; 1.96 + case 1: if (f<1) *ptr = (T)((1-opacity*(1-f))**ptr + col0*opacity*(1-f)); break; 1.97 + case 2: if (f>0) *ptr = (T)((1-opacity*f)**ptr + col1*opacity*f); break; 1.98 + default: break; 1.99 + } break; 1.100 + } 1.101 + case 2:{ // ring/bar 1.102 + const float f = (1 + (float)std::cos(r*2.f*cimg::valuePI))/2; 1.103 + switch(id) { // map the 3 cases 1.104 + case 3: *ptr = (T)((1-opacity)**ptr + opacity*(col0*(1.f-f)+col1*f)); break; 1.105 + case 1: if (f<1) *ptr = (T)((1-opacity*(1-f))**ptr + col0*opacity*(1-f)); break; 1.106 + case 2: if (f>0) *ptr = (T)((1-opacity*f)**ptr + col1*opacity*f); break; 1.107 + default: break; 1.108 + } break; 1.109 + } 1.110 + case 3: { // exponential 1.111 + const float f = 1 - (float)std::exp(-r); 1.112 + switch(id) { // map the 3 cases 1.113 + case 3: *ptr = (T)((1-opacity)**ptr + opacity*(col0*(1.f-f)+col1*f)); break; 1.114 + case 1: if (f<1) *ptr = (T)((1-opacity*(1-f))**ptr + col0*opacity*(1-f)); break; 1.115 + case 2: if (f>0) *ptr = (T)((1-opacity*f)**ptr + col1*opacity*f); break; 1.116 + default: break; 1.117 + } break; 1.118 + } 1.119 + case 4: { // vanishing wave 1.120 + const float f = (1 - (float)std::cos(4.5f*r*2.f*cimg::valuePI))/2, o = r<.9f?(float)std::exp(-.5*r*r*12.f):0; 1.121 + switch(id) { // map the 3 cases 1.122 + case 3: if (o>0) *ptr = (T)((1-o)**ptr + o*(col0*(1.f-f)+col1*f)); break; 1.123 + case 1: if (f<1) *ptr = (T)((1-o*(1-f))**ptr + col0*o*(1-f)); break; 1.124 + case 2: if (f>0) *ptr = (T)((1-o*f)**ptr + col1*o*f); break; 1.125 + default: break; 1.126 + } break; 1.127 + } 1.128 + case 5: { // vanishing ring/bar 1.129 + const float f = (1 + (float)std::cos(r*2.f*cimg::valuePI))/2, o = r<.9?(float)std::exp(-.5*r*r*12.f):0; 1.130 + switch(id) { // map the 3 cases 1.131 + case 3: if (o>0) *ptr = (T)((1-o)**ptr + o*(col0*(1.f-f)+col1*f)); break; 1.132 + case 1: if (f<1) *ptr = (T)((1-o*(1-f))**ptr + col0*o*(1-f)); break; 1.133 + case 2: if (f>0) *ptr = (T)((1-o*f)**ptr + col1*o*f); break; 1.134 + default: break; 1.135 + } break; 1.136 + } 1.137 + case 6: { // diffraction pattern of a circular aperture (Airy function) 1.138 +#define myj1(x) (std::sin((x)<3?(x)*2.2/3:(x)-0.8)*std::exp(-std::pow((x)/5.0,1/3.0))) 1.139 + const float a = 10*(float)cimg::valuePI*r, tmp = a<0.2?.5f:((float)myj1(a)/a), f = 1-4*tmp*tmp; 1.140 +#undef myj1 1.141 + switch(id) { // map the 3 cases 1.142 + case 3: *ptr = (T)((1-opacity)**ptr + opacity*(col0*(1.f-f)+col1*f)); break; 1.143 + case 1: if (f<1) *ptr = (T)((1-opacity*(1-f))**ptr + col0*opacity*(1-f)); break; 1.144 + case 2: if (f>0) *ptr = (T)((1-opacity*f)**ptr + col1*opacity*f); break; 1.145 + default: break; 1.146 + } 1.147 + break; 1.148 + } 1.149 + case 7: { // diffraction pattern of a rectangular function (sinc function) 1.150 + const float a = 10*(float)cimg::valuePI*r, tmp = a==0?1:(float)std::sin(a)/a, f = 1-tmp*tmp; 1.151 + switch(id) { // map the 3 cases 1.152 + case 3: *ptr = (T)((1-opacity)**ptr + opacity*(col0*(1.f-f)+col1*f)); break; 1.153 + case 1: if (f<1) *ptr = (T)((1-opacity*(1-f))**ptr + col0*opacity*(1-f)); break; 1.154 + case 2: if (f>0) *ptr = (T)((1-opacity*f)**ptr + col1*opacity*f); break; 1.155 + default: break; 1.156 + } break; 1.157 + } 1.158 + default: 1.159 + CImgArgumentException("CImg<%s>::draw_gradient : unknown profile parameter",pixel_type()); break; 1.160 + } 1.161 +} 1.162 + 1.163 +//! Draw a gradient with various shape and profile 1.164 +/** 1.165 + \param x0 X-coordinate of the 1st control point 1.166 + \param y0 Y-coordinate of the 1st control point 1.167 + \param x1 X-coordinate of the 2nd control point 1.168 + \param y1 Y-coordinate of the 2nd control point 1.169 + \param color0 Array of dimv() values of type \c T, defining the 1st color. 1.170 + \param color1 Array of dimv() values of type \c T, defining the 2nd color. 1.171 + \param shape shape of the gradient (0,3) 1.172 + \param profile select a profile function (0,7) 1.173 + \param opacity Drawing opacity. 1.174 + \note 1.175 + - if one color is NULL then the gradient is done to transparency 1.176 +**/ 1.177 +template<typename tc> 1.178 +CImg<T>& draw_gradient(const int x0, const int y0, const int x1, const int y1, 1.179 + const tc *const color0, const tc *const color1, 1.180 + const int shape=0, const int profile=0, const float opacity=1.0f){ 1.181 + if (is_empty()) return *this; 1.182 + if (!color0 && !color1) 1.183 + throw CImgArgumentException("CImg<%s>::draw_gradient : The two specified colors are (null).", 1.184 + pixel_type()); 1.185 + if (profile<0 || profile>7) { // catch this case before entering in the for loop 1.186 + CImgArgumentException("CImg<%s>::draw_gradient : unknown profile parameter",pixel_type()); 1.187 + return *this; 1.188 + } 1.189 + const float abx = (float)x1-x0, aby = (float)y1-y0, ab2 = abx*abx + aby*aby; // pt A=(x0,y0), B=(x1,y1) 1.190 + const tc *pcol0 = color0, *pcol1 = color1; 1.191 + T *ptr = data; 1.192 + 1.193 + switch(shape) { 1.194 + case 0: { // linear 1.195 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { // point M=(x,z) 1.196 + const float amx = (float)x-x0, amy = (float)y-y0, r = cimg::max(0.f,cimg::min(1.f,(amx*abx+amy*aby)/ab2)); 1.197 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.198 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.199 + case 1:{ // radial 1.200 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { 1.201 + const float amx = (float)x-x0, amy = (float)y-y0, r = cimg::max(0.f,cimg::min(1.f,(amx*amx+amy*amy)/ab2)); 1.202 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.203 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.204 + case 2:{ // radial cone 1.205 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { 1.206 + const float amx = (float)x-x0, amy = (float)y-y0, r = cimg::max(0.f,cimg::min(1.f,(float)std::sqrt((amx*amx+amy*amy)/ab2))); 1.207 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.208 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.209 + case 3:{ // square 1.210 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { 1.211 + const float amx = (float)x-x0, amy = (float)y-y0, r=cimg::max(0.f,cimg::min(1.f,(cimg::abs(amx*abx+amy*aby)+cimg::abs(amx*aby-amy*abx))/ab2)); 1.212 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.213 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.214 + case 4:{ // rectangle (L1) 1.215 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { 1.216 + const float amx = (float)x-x0, amy = (float)y-y0, 1.217 + r = cimg::max(0.f,cimg::min(1.f,(cimg::abs(amx/abx)+cimg::abs(amy/aby)))); 1.218 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.219 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.220 + case 5:{ // rectangle (Linf) 1.221 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { 1.222 + const float amx = (float)x-x0, amy = (float)y-y0, 1.223 + r=cimg::max(0.f,cimg::min(1.f,cimg::max(cimg::abs(amx/abx),cimg::abs(amy/aby)))); 1.224 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.225 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.226 + case 6:{ // gaussian 1.227 + cimg_forV(*this,v) { cimg_forXYZ(*this,x,y,z) { 1.228 + const float amx = (float)x-x0, amy = (float)y-y0, r = cimg::max(0.f,cimg::min(1.f,1-(float)std::exp(-(amx*amx+amy*amy)/ab2))); 1.229 + _draw_gradient_profile(ptr++,opacity,r,pcol0,pcol1,profile); 1.230 + } if (pcol0) ++pcol0; if (pcol1) ++pcol1; }} break; 1.231 + default: 1.232 + CImgArgumentException("CImg<%s>::draw_gradient : unknown shape parameter",pixel_type()); break; 1.233 + } 1.234 + return *this; 1.235 +} 1.236 + 1.237 +template<typename tc> 1.238 +CImg<T>& draw_gradient(const int x0, const int y0, const int x1, const int y1, 1.239 + const tc *const color0, const int color1, 1.240 + const int shape=0, const int profile=0, const float opacity=1.0f) { 1.241 + return (*this).draw_gradient(x0,y0,x1,y1,color0,(tc*)color1,shape,profile,opacity); 1.242 +} 1.243 + 1.244 +template<typename tc> 1.245 +CImg<T>& draw_gradient(const int x0, const int y0, const int x1, const int y1, 1.246 + const int color0, const tc *const color1, 1.247 + const int shape=0, const int profile=0, const float opacity=1.0f) { 1.248 + return (*this).draw_gradient(x0,y0,x1,y1,(tc*)color0,color1,shape,profile,opacity); 1.249 +} 1.250 + 1.251 +#endif