gem.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                              GGGG  EEEEE  M   M                             %
00007 %                             G      E      MM MM                             %
00008 %                             G GG   EEE    M M M                             %
00009 %                             G   G  E      M   M                             %
00010 %                              GGGG  EEEEE  M   M                             %
00011 %                                                                             %
00012 %                                                                             %
00013 %                    Graphic Gems - Graphic Support Methods                   %
00014 %                                                                             %
00015 %                               Software Design                               %
00016 %                                 John Cristy                                 %
00017 %                                 August 1996                                 %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "magick/studio.h"
00044 #include "magick/color-private.h"
00045 #include "magick/draw.h"
00046 #include "magick/gem.h"
00047 #include "magick/image.h"
00048 #include "magick/image-private.h"
00049 #include "magick/log.h"
00050 #include "magick/memory_.h"
00051 #include "magick/pixel-private.h"
00052 #include "magick/quantum.h"
00053 #include "magick/random_.h"
00054 #include "magick/resize.h"
00055 #include "magick/transform.h"
00056 #include "magick/signature-private.h"
00057 
00058 /*
00059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00060 %                                                                             %
00061 %                                                                             %
00062 %                                                                             %
00063 %   C o n v e r t H S B T o R G B                                             %
00064 %                                                                             %
00065 %                                                                             %
00066 %                                                                             %
00067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00068 %
00069 %  ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
00070 %  green, blue) triple.
00071 %
00072 %  The format of the ConvertHSBToRGBImage method is:
00073 %
00074 %      void ConvertHSBToRGB(const double hue,const double saturation,
00075 %        const double brightness,Quantum *red,Quantum *green,Quantum *blue)
00076 %
00077 %  A description of each parameter follows:
00078 %
00079 %    o hue, saturation, brightness: A double value representing a
00080 %      component of the HSB color space.
00081 %
00082 %    o red, green, blue: A pointer to a pixel component of type Quantum.
00083 %
00084 */
00085 MagickExport void ConvertHSBToRGB(const double hue,const double saturation,
00086   const double brightness,Quantum *red,Quantum *green,Quantum *blue)
00087 {
00088   MagickRealType
00089     f,
00090     h,
00091     p,
00092     q,
00093     t;
00094 
00095   /*
00096     Convert HSB to RGB colorspace.
00097   */
00098   assert(red != (Quantum *) NULL);
00099   assert(green != (Quantum *) NULL);
00100   assert(blue != (Quantum *) NULL);
00101   if (saturation == 0.0)
00102     {
00103       *red=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00104       *green=(*red);
00105       *blue=(*red);
00106       return;
00107     }
00108   h=6.0*(hue-floor(hue));
00109   f=h-floor((double) h);
00110   p=brightness*(1.0-saturation);
00111   q=brightness*(1.0-saturation*f);
00112   t=brightness*(1.0-(saturation*(1.0-f)));
00113   switch ((int) h)
00114   {
00115     case 0:
00116     default:
00117     {
00118       *red=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00119       *green=RoundToQuantum((MagickRealType) QuantumRange*t);
00120       *blue=RoundToQuantum((MagickRealType) QuantumRange*p);
00121       break;
00122     }
00123     case 1:
00124     {
00125       *red=RoundToQuantum((MagickRealType) QuantumRange*q);
00126       *green=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00127       *blue=RoundToQuantum((MagickRealType) QuantumRange*p);
00128       break;
00129     }
00130     case 2:
00131     {
00132       *red=RoundToQuantum((MagickRealType) QuantumRange*p);
00133       *green=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00134       *blue=RoundToQuantum((MagickRealType) QuantumRange*t);
00135       break;
00136     }
00137     case 3:
00138     {
00139       *red=RoundToQuantum((MagickRealType) QuantumRange*p);
00140       *green=RoundToQuantum((MagickRealType) QuantumRange*q);
00141       *blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00142       break;
00143     }
00144     case 4:
00145     {
00146       *red=RoundToQuantum((MagickRealType) QuantumRange*t);
00147       *green=RoundToQuantum((MagickRealType) QuantumRange*p);
00148       *blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00149       break;
00150     }
00151     case 5:
00152     {
00153       *red=RoundToQuantum((MagickRealType) QuantumRange*brightness);
00154       *green=RoundToQuantum((MagickRealType) QuantumRange*p);
00155       *blue=RoundToQuantum((MagickRealType) QuantumRange*q);
00156       break;
00157     }
00158   }
00159 }
00160 
00161 /*
00162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00163 %                                                                             %
00164 %                                                                             %
00165 %                                                                             %
00166 %   C o n v e r t H S L T o R G B                                             %
00167 %                                                                             %
00168 %                                                                             %
00169 %                                                                             %
00170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00171 %
00172 %  ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
00173 %  green, blue) triple.
00174 %
00175 %  The format of the ConvertHSLToRGBImage method is:
00176 %
00177 %      void ConvertHSLToRGB(const double hue,const double saturation,
00178 %        const double lightness,Quantum *red,Quantum *green,Quantum *blue)
00179 %
00180 %  A description of each parameter follows:
00181 %
00182 %    o hue, saturation, lightness: A double value representing a
00183 %      component of the HSL color space.
00184 %
00185 %    o red, green, blue: A pointer to a pixel component of type Quantum.
00186 %
00187 */
00188 
00189 static inline MagickRealType ConvertHueToRGB(MagickRealType m1,
00190   MagickRealType m2,MagickRealType hue)
00191 {
00192   if (hue < 0.0)
00193     hue+=1.0;
00194   if (hue > 1.0)
00195     hue-=1.0;
00196   if ((6.0*hue) < 1.0)
00197     return(m1+6.0*(m2-m1)*hue);
00198   if ((2.0*hue) < 1.0)
00199     return(m2);
00200   if ((3.0*hue) < 2.0)
00201     return(m1+6.0*(m2-m1)*(2.0/3.0-hue));
00202   return(m1);
00203 }
00204 
00205 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
00206   const double lightness,Quantum *red,Quantum *green,Quantum *blue)
00207 {
00208   MagickRealType
00209     b,
00210     g,
00211     r,
00212     m1,
00213     m2;
00214 
00215   /*
00216     Convert HSL to RGB colorspace.
00217   */
00218   assert(red != (Quantum *) NULL);
00219   assert(green != (Quantum *) NULL);
00220   assert(blue != (Quantum *) NULL);
00221   if (saturation == 0)
00222     {
00223       *red=RoundToQuantum((MagickRealType) QuantumRange*lightness);
00224       *green=(*red);
00225       *blue=(*red);
00226       return;
00227     }
00228   if (lightness <= 0.5)
00229     m2=lightness*(saturation+1.0);
00230   else
00231     m2=(lightness+saturation)-(lightness*saturation);
00232   m1=2.0*lightness-m2;
00233   r=ConvertHueToRGB(m1,m2,hue+1.0/3.0);
00234   g=ConvertHueToRGB(m1,m2,hue);
00235   b=ConvertHueToRGB(m1,m2,hue-1.0/3.0);
00236   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
00237   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
00238   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
00239 }
00240 
00241 /*
00242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00243 %                                                                             %
00244 %                                                                             %
00245 %                                                                             %
00246 %   C o n v e r t H W B T o R G B                                             %
00247 %                                                                             %
00248 %                                                                             %
00249 %                                                                             %
00250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00251 %
00252 %  ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
00253 %  blue) triple.
00254 %
00255 %  The format of the ConvertHWBToRGBImage method is:
00256 %
00257 %      void ConvertHWBToRGB(const double hue,const double whiteness,
00258 %        const double blackness,Quantum *red,Quantum *green,Quantum *blue)
00259 %
00260 %  A description of each parameter follows:
00261 %
00262 %    o hue, whiteness, blackness: A double value representing a
00263 %      component of the HWB color space.
00264 %
00265 %    o red, green, blue: A pointer to a pixel component of type Quantum.
00266 %
00267 */
00268 MagickExport void ConvertHWBToRGB(const double hue,const double whiteness,
00269   const double blackness,Quantum *red,Quantum *green,Quantum *blue)
00270 {
00271   MagickRealType
00272     b,
00273     f,
00274     g,
00275     n,
00276     r,
00277     v;
00278 
00279   register long
00280     i;
00281 
00282   /*
00283     Convert HWB to RGB colorspace.
00284   */
00285   assert(red != (Quantum *) NULL);
00286   assert(green != (Quantum *) NULL);
00287   assert(blue != (Quantum *) NULL);
00288   v=1.0-blackness;
00289   if (hue == 0.0)
00290     {
00291       *red=RoundToQuantum((MagickRealType) QuantumRange*v);
00292       *green=RoundToQuantum((MagickRealType) QuantumRange*v);
00293       *blue=RoundToQuantum((MagickRealType) QuantumRange*v);
00294       return;
00295     }
00296   i=(long) floor(6.0*hue);
00297   f=6.0*hue-i;
00298   if ((i & 0x01) != 0)
00299     f=1.0-f;
00300   n=whiteness+f*(v-whiteness);  /* linear interpolation */
00301   switch (i)
00302   {
00303     default:
00304     case 6:
00305     case 0: r=v; g=n; b=whiteness; break;
00306     case 1: r=n; g=v; b=whiteness; break;
00307     case 2: r=whiteness; g=v; b=n; break;
00308     case 3: r=whiteness; g=n; b=v; break;
00309     case 4: r=n; g=whiteness; b=v; break;
00310     case 5: r=v; g=whiteness; b=n; break;
00311   }
00312   *red=RoundToQuantum((MagickRealType) QuantumRange*r);
00313   *green=RoundToQuantum((MagickRealType) QuantumRange*g);
00314   *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
00315 }
00316 
00317 /*
00318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00319 %                                                                             %
00320 %                                                                             %
00321 %                                                                             %
00322 %   C o n v e r t R G B T o H S B                                             %
00323 %                                                                             %
00324 %                                                                             %
00325 %                                                                             %
00326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00327 %
00328 %  ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
00329 %  brightness) triple.
00330 %
00331 %  The format of the ConvertRGBToHSB method is:
00332 %
00333 %      void ConvertRGBToHSB(const Quantum red,const Quantum green,
00334 %        const Quantum blue,double *hue,double *saturation,double *brightness)
00335 %
00336 %  A description of each parameter follows:
00337 %
00338 %    o red, green, blue: A Quantum value representing the red, green, and
00339 %      blue component of a pixel..
00340 %
00341 %    o hue, saturation, brightness: A pointer to a double value representing a
00342 %      component of the HSB color space.
00343 %
00344 */
00345 MagickExport void ConvertRGBToHSB(const Quantum red,const Quantum green,
00346   const Quantum blue,double *hue,double *saturation,double *brightness)
00347 {
00348   MagickRealType
00349     delta,
00350     max,
00351     min;
00352 
00353   /*
00354     Convert RGB to HSB colorspace.
00355   */
00356   assert(hue != (double *) NULL);
00357   assert(saturation != (double *) NULL);
00358   assert(brightness != (double *) NULL);
00359   *hue=0.0;
00360   *saturation=0.0;
00361   *brightness=0.0;
00362   min=(MagickRealType) (red < green ? red : green);
00363   if ((MagickRealType) blue < min)
00364     min=(MagickRealType) blue;
00365   max=(MagickRealType) (red > green ? red : green);
00366   if ((MagickRealType) blue > max)
00367     max=(MagickRealType) blue;
00368   if (max == 0.0)
00369     return;
00370   delta=max-min;
00371   *saturation=(double) (delta/max);
00372   *brightness=(double) (QuantumScale*max);
00373   if (delta == 0.0)
00374     return;
00375   if ((MagickRealType) red == max)
00376     *hue=(double) ((green-(MagickRealType) blue)/delta);
00377   else
00378     if ((MagickRealType) green == max)
00379       *hue=(double) (2.0+(blue-(MagickRealType) red)/delta);
00380     else
00381       *hue=(double) (4.0+(red-(MagickRealType) green)/delta);
00382   *hue/=6.0;
00383   if (*hue < 0.0)
00384     *hue+=1.0;
00385 }
00386 
00387 /*
00388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00389 %                                                                             %
00390 %                                                                             %
00391 %                                                                             %
00392 %   C o n v e r t R G B T o H S L                                             %
00393 %                                                                             %
00394 %                                                                             %
00395 %                                                                             %
00396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00397 %
00398 %  ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
00399 %  lightness) triple.
00400 %
00401 %  The format of the ConvertRGBToHSL method is:
00402 %
00403 %      void ConvertRGBToHSL(const Quantum red,const Quantum green,
00404 %        const Quantum blue,double *hue,double *saturation,double *lightness)
00405 %
00406 %  A description of each parameter follows:
00407 %
00408 %    o red, green, blue: A Quantum value representing the red, green, and
00409 %      blue component of a pixel..
00410 %
00411 %    o hue, saturation, lightness: A pointer to a double value representing a
00412 %      component of the HSL color space.
00413 %
00414 */
00415 
00416 static inline double MagickMax(const double x,const double y)
00417 {
00418   if (x > y)
00419     return(x);
00420   return(y);
00421 }
00422 
00423 static inline double MagickMin(const double x,const double y)
00424 {
00425   if (x < y)
00426     return(x);
00427   return(y);
00428 }
00429 
00430 MagickExport void ConvertRGBToHSL(const Quantum red,const Quantum green,
00431   const Quantum blue,double *hue,double *saturation,double *lightness)
00432 {
00433   MagickRealType
00434     b,
00435     delta,
00436     g,
00437     max,
00438     min,
00439     r;
00440 
00441   /*
00442     Convert RGB to HSL colorspace.
00443   */
00444   assert(hue != (double *) NULL);
00445   assert(saturation != (double *) NULL);
00446   assert(lightness != (double *) NULL);
00447   r=QuantumScale*red;
00448   g=QuantumScale*green;
00449   b=QuantumScale*blue;
00450   max=MagickMax(r,MagickMax(g,b));
00451   min=MagickMin(r,MagickMin(g,b));
00452   *lightness=(double) ((min+max)/2.0);
00453   delta=max-min;
00454   if (delta == 0.0)
00455     {
00456       *hue=0.0;
00457       *saturation=0.0;
00458       return;
00459     }
00460   if (*lightness < 0.5)
00461     *saturation=(double) (delta/(min+max));
00462   else
00463     *saturation=(double) (delta/(2.0-max-min));
00464   if (r == max)
00465     *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta;
00466   else
00467     if (g == max)
00468       *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/
00469         delta;
00470     else
00471       if (b == max)
00472         *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+
00473           (delta/2.0)))/delta;
00474   if (*hue < 0.0)
00475     *hue+=1.0;
00476   if (*hue > 1.0)
00477     *hue-=1.0;
00478 }
00479 
00480 /*
00481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00482 %                                                                             %
00483 %                                                                             %
00484 %                                                                             %
00485 %   C o n v e r t R G B T o H W B                                             %
00486 %                                                                             %
00487 %                                                                             %
00488 %                                                                             %
00489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00490 %
00491 %  ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
00492 %  blackness) triple.
00493 %
00494 %  The format of the ConvertRGBToHWB method is:
00495 %
00496 %      void ConvertRGBToHWB(const Quantum red,const Quantum green,
00497 %        const Quantum blue,double *hue,double *whiteness,double *blackness)
00498 %
00499 %  A description of each parameter follows:
00500 %
00501 %    o red, green, blue: A Quantum value representing the red, green, and
00502 %      blue component of a pixel.
00503 %
00504 %    o hue, whiteness, blackness: A pointer to a double value representing a
00505 %      component of the HWB color space.
00506 %
00507 */
00508 MagickExport void ConvertRGBToHWB(const Quantum red,const Quantum green,
00509   const Quantum blue,double *hue,double *whiteness,double *blackness)
00510 {
00511   MagickRealType
00512     f,
00513     v,
00514     w;
00515 
00516   register long
00517     i;
00518 
00519   /*
00520     Convert RGB to HWB colorspace.
00521   */
00522   assert(hue != (double *) NULL);
00523   assert(whiteness != (double *) NULL);
00524   assert(blackness != (double *) NULL);
00525   w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double)
00526     blue));
00527   v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double)
00528     blue));
00529   *blackness=1.0-QuantumScale*v;
00530   *whiteness=QuantumScale*w;
00531   if (v == w)
00532     {
00533       *hue=0.0;
00534       return;
00535     }
00536   f=((MagickRealType) red == w) ? green-(MagickRealType) blue :
00537     (((MagickRealType) green == w) ? blue-(MagickRealType) red : red-
00538     (MagickRealType) green);
00539   i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1);
00540   *hue=((double) i-f/(v-1.0*w))/6.0;
00541 }
00542 
00543 /*
00544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00545 %                                                                             %
00546 %                                                                             %
00547 %                                                                             %
00548 %   E x p a n d A f f i n e                                                   %
00549 %                                                                             %
00550 %                                                                             %
00551 %                                                                             %
00552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00553 %
00554 %  ExpandAffine() computes the affine's expansion factor, i.e. the square root
00555 %  of the factor by which the affine transform affects area. In an affine
00556 %  transform composed of scaling, rotation, shearing, and translation, returns
00557 %  the amount of scaling.
00558 %
00559 %  The format of the ExpandAffine method is:
00560 %
00561 %      double ExpandAffine(const AffineMatrix *affine)
00562 %
00563 %  A description of each parameter follows:
00564 %
00565 %    o expansion: Method ExpandAffine returns the affine's expansion factor.
00566 %
00567 %    o affine: A pointer the affine transform of type AffineMatrix.
00568 %
00569 */
00570 MagickExport double ExpandAffine(const AffineMatrix *affine)
00571 {
00572   assert(affine != (const AffineMatrix *) NULL);
00573   return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
00574 }
00575 
00576 /*
00577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00578 %                                                                             %
00579 %                                                                             %
00580 %                                                                             %
00581 %   G e t O p t i m a l K e r n e l W i d t h                                 %
00582 %                                                                             %
00583 %                                                                             %
00584 %                                                                             %
00585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00586 %
00587 %  GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
00588 %  filter.  Start with the minimum value of 3 pixels and walk out until we drop
00589 %  below the threshold of one pixel numerical accuracy.
00590 %
00591 %  The format of the GetOptimalKernelWidth method is:
00592 %
00593 %      unsigned long GetOptimalKernelWidth(const double radius,
00594 %        const double sigma)
00595 %
00596 %  A description of each parameter follows:
00597 %
00598 %    o width: Method GetOptimalKernelWidth returns the optimal width of
00599 %      a convolution kernel.
00600 %
00601 %    o radius: the radius of the Gaussian, in pixels, not counting the center
00602 %      pixel.
00603 %
00604 %    o sigma: the standard deviation of the Gaussian, in pixels.
00605 %
00606 */
00607 MagickExport unsigned long GetOptimalKernelWidth1D(const double radius,
00608   const double sigma)
00609 {
00610   long
00611     width;
00612 
00613   MagickRealType
00614     normalize,
00615     value;
00616 
00617   register long
00618     u;
00619 
00620   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00621   if (radius > 0.0)
00622     return((unsigned long) (2.0*ceil(radius)+1.0));
00623   if (fabs(sigma) <= MagickEpsilon)
00624     return(1);
00625   for (width=5; ; )
00626   {
00627     normalize=0.0;
00628     for (u=(-width/2); u <= (width/2); u++)
00629       normalize+=exp(-((double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma);
00630     u=width/2;
00631     value=exp(-((double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma)/normalize;
00632     if ((long) (QuantumRange*value) <= 0L)
00633       break;
00634     width+=2;
00635   }
00636   return((unsigned long) (width-2));
00637 }
00638 
00639 MagickExport unsigned long GetOptimalKernelWidth2D(const double radius,
00640   const double sigma)
00641 {
00642 
00643   long
00644     width;
00645 
00646   MagickRealType
00647     alpha,
00648     normalize,
00649     value;
00650 
00651   register long
00652     u,
00653     v;
00654 
00655   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00656   if (radius > 0.0)
00657     return((unsigned long) (2.0*ceil(radius)+1.0));
00658   if (fabs(sigma) <= MagickEpsilon)
00659     return(1);
00660   for (width=5; ; )
00661   {
00662     normalize=0.0;
00663     for (v=(-width/2); v <= (width/2); v++)
00664     {
00665       for (u=(-width/2); u <= (width/2); u++)
00666       {
00667         alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
00668         normalize+=alpha/(2.0*MagickPI*sigma*sigma);
00669       }
00670     }
00671     v=width/2;
00672     value=exp(-((double) v*v)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma)/normalize;
00673     if ((long) (QuantumRange*value) <= 0L)
00674       break;
00675     width+=2;
00676   }
00677   return((unsigned long) (width-2));
00678 }
00679 
00680 MagickExport unsigned long  GetOptimalKernelWidth(const double radius,
00681   const double sigma)
00682 {
00683   return(GetOptimalKernelWidth1D(radius,sigma));
00684 }

Generated on Thu Nov 20 21:54:46 2008 for MagickCore by  doxygen 1.5.7.1