|
MagickCore
6.7.5
|
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-2012 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 "MagickCore/studio.h" 00044 #include "MagickCore/color-private.h" 00045 #include "MagickCore/draw.h" 00046 #include "MagickCore/gem.h" 00047 #include "MagickCore/gem-private.h" 00048 #include "MagickCore/image.h" 00049 #include "MagickCore/image-private.h" 00050 #include "MagickCore/log.h" 00051 #include "MagickCore/memory_.h" 00052 #include "MagickCore/pixel-accessor.h" 00053 #include "MagickCore/quantum.h" 00054 #include "MagickCore/quantum-private.h" 00055 #include "MagickCore/random_.h" 00056 #include "MagickCore/resize.h" 00057 #include "MagickCore/transform.h" 00058 #include "MagickCore/signature-private.h" 00059 00060 /* 00061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00062 % % 00063 % % 00064 % % 00065 % C o n v e r t H S B T o R G B % 00066 % % 00067 % % 00068 % % 00069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00070 % 00071 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red, 00072 % green, blue) triple. 00073 % 00074 % The format of the ConvertHSBToRGBImage method is: 00075 % 00076 % void ConvertHSBToRGB(const double hue,const double saturation, 00077 % const double brightness,double *red,double *green,double *blue) 00078 % 00079 % A description of each parameter follows: 00080 % 00081 % o hue, saturation, brightness: A double value representing a 00082 % component of the HSB color space. 00083 % 00084 % o red, green, blue: A pointer to a pixel component of type Quantum. 00085 % 00086 */ 00087 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation, 00088 const double brightness,double *red,double *green,double *blue) 00089 { 00090 MagickRealType 00091 f, 00092 h, 00093 p, 00094 q, 00095 t; 00096 00097 /* 00098 Convert HSB to RGB colorspace. 00099 */ 00100 assert(red != (double *) NULL); 00101 assert(green != (double *) NULL); 00102 assert(blue != (double *) NULL); 00103 if (saturation == 0.0) 00104 { 00105 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00106 *green=(*red); 00107 *blue=(*red); 00108 return; 00109 } 00110 h=6.0*(hue-floor(hue)); 00111 f=h-floor((double) h); 00112 p=brightness*(1.0-saturation); 00113 q=brightness*(1.0-saturation*f); 00114 t=brightness*(1.0-(saturation*(1.0-f))); 00115 switch ((int) h) 00116 { 00117 case 0: 00118 default: 00119 { 00120 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00121 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*t); 00122 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*p); 00123 break; 00124 } 00125 case 1: 00126 { 00127 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*q); 00128 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00129 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*p); 00130 break; 00131 } 00132 case 2: 00133 { 00134 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*p); 00135 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00136 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*t); 00137 break; 00138 } 00139 case 3: 00140 { 00141 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*p); 00142 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*q); 00143 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00144 break; 00145 } 00146 case 4: 00147 { 00148 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*t); 00149 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*p); 00150 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00151 break; 00152 } 00153 case 5: 00154 { 00155 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*brightness); 00156 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*p); 00157 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*q); 00158 break; 00159 } 00160 } 00161 } 00162 00163 /* 00164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00165 % % 00166 % % 00167 % % 00168 % C o n v e r t H S L T o R G B % 00169 % % 00170 % % 00171 % % 00172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00173 % 00174 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red, 00175 % green, blue) triple. 00176 % 00177 % The format of the ConvertHSLToRGBImage method is: 00178 % 00179 % void ConvertHSLToRGB(const double hue,const double saturation, 00180 % const double lightness,double *red,double *green,double *blue) 00181 % 00182 % A description of each parameter follows: 00183 % 00184 % o hue, saturation, lightness: A double value representing a 00185 % component of the HSL color space. 00186 % 00187 % o red, green, blue: A pointer to a pixel component of type Quantum. 00188 % 00189 */ 00190 00191 static inline MagickRealType ConvertHueToRGB(MagickRealType m1, 00192 MagickRealType m2,MagickRealType hue) 00193 { 00194 if (hue < 0.0) 00195 hue+=1.0; 00196 if (hue > 1.0) 00197 hue-=1.0; 00198 if ((6.0*hue) < 1.0) 00199 return(m1+6.0*(m2-m1)*hue); 00200 if ((2.0*hue) < 1.0) 00201 return(m2); 00202 if ((3.0*hue) < 2.0) 00203 return(m1+6.0*(m2-m1)*(2.0/3.0-hue)); 00204 return(m1); 00205 } 00206 00207 MagickExport void ConvertHSLToRGB(const double hue,const double saturation, 00208 const double lightness,double *red,double *green,double *blue) 00209 { 00210 MagickRealType 00211 b, 00212 g, 00213 r, 00214 m1, 00215 m2; 00216 00217 /* 00218 Convert HSL to RGB colorspace. 00219 */ 00220 assert(red != (double *) NULL); 00221 assert(green != (double *) NULL); 00222 assert(blue != (double *) NULL); 00223 if (saturation == 0) 00224 { 00225 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*lightness); 00226 *green=(*red); 00227 *blue=(*red); 00228 return; 00229 } 00230 if (lightness < 0.5) 00231 m2=lightness*(saturation+1.0); 00232 else 00233 m2=(lightness+saturation)-(lightness*saturation); 00234 m1=2.0*lightness-m2; 00235 r=ConvertHueToRGB(m1,m2,hue+1.0/3.0); 00236 g=ConvertHueToRGB(m1,m2,hue); 00237 b=ConvertHueToRGB(m1,m2,hue-1.0/3.0); 00238 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*r); 00239 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*g); 00240 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*b); 00241 } 00242 00243 /* 00244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00245 % % 00246 % % 00247 % % 00248 % C o n v e r t H W B T o R G B % 00249 % % 00250 % % 00251 % % 00252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00253 % 00254 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green, 00255 % blue) triple. 00256 % 00257 % The format of the ConvertHWBToRGBImage method is: 00258 % 00259 % void ConvertHWBToRGB(const double hue,const double whiteness, 00260 % const double blackness,double *red,double *green,double *blue) 00261 % 00262 % A description of each parameter follows: 00263 % 00264 % o hue, whiteness, blackness: A double value representing a 00265 % component of the HWB color space. 00266 % 00267 % o red, green, blue: A pointer to a pixel component of type Quantum. 00268 % 00269 */ 00270 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness, 00271 const double blackness,double *red,double *green,double *blue) 00272 { 00273 MagickRealType 00274 b, 00275 f, 00276 g, 00277 n, 00278 r, 00279 v; 00280 00281 register ssize_t 00282 i; 00283 00284 /* 00285 Convert HWB to RGB colorspace. 00286 */ 00287 assert(red != (double *) NULL); 00288 assert(green != (double *) NULL); 00289 assert(blue != (double *) NULL); 00290 v=1.0-blackness; 00291 if (hue == 0.0) 00292 { 00293 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*v); 00294 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*v); 00295 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*v); 00296 return; 00297 } 00298 i=(ssize_t) floor(6.0*hue); 00299 f=6.0*hue-i; 00300 if ((i & 0x01) != 0) 00301 f=1.0-f; 00302 n=whiteness+f*(v-whiteness); /* linear interpolation */ 00303 switch (i) 00304 { 00305 default: 00306 case 6: 00307 case 0: r=v; g=n; b=whiteness; break; 00308 case 1: r=n; g=v; b=whiteness; break; 00309 case 2: r=whiteness; g=v; b=n; break; 00310 case 3: r=whiteness; g=n; b=v; break; 00311 case 4: r=n; g=whiteness; b=v; break; 00312 case 5: r=v; g=whiteness; b=n; break; 00313 } 00314 *red=(double) ClampToQuantum((MagickRealType) QuantumRange*r); 00315 *green=(double) ClampToQuantum((MagickRealType) QuantumRange*g); 00316 *blue=(double) ClampToQuantum((MagickRealType) QuantumRange*b); 00317 } 00318 00319 /* 00320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00321 % % 00322 % % 00323 % % 00324 % C o n v e r t R G B T o H S B % 00325 % % 00326 % % 00327 % % 00328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00329 % 00330 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation, 00331 % brightness) triple. 00332 % 00333 % The format of the ConvertRGBToHSB method is: 00334 % 00335 % void ConvertRGBToHSB(const double red,const double green, 00336 % const double blue,double *hue,double *saturation,double *brightness) 00337 % 00338 % A description of each parameter follows: 00339 % 00340 % o red, green, blue: A Quantum value representing the red, green, and 00341 % blue component of a pixel.. 00342 % 00343 % o hue, saturation, brightness: A pointer to a double value representing a 00344 % component of the HSB color space. 00345 % 00346 */ 00347 MagickPrivate void ConvertRGBToHSB(const double red,const double green, 00348 const double blue,double *hue,double *saturation,double *brightness) 00349 { 00350 MagickRealType 00351 delta, 00352 max, 00353 min; 00354 00355 /* 00356 Convert RGB to HSB colorspace. 00357 */ 00358 assert(hue != (double *) NULL); 00359 assert(saturation != (double *) NULL); 00360 assert(brightness != (double *) NULL); 00361 *hue=0.0; 00362 *saturation=0.0; 00363 *brightness=0.0; 00364 min=(MagickRealType) (red < green ? red : green); 00365 if ((MagickRealType) blue < min) 00366 min=(MagickRealType) blue; 00367 max=(MagickRealType) (red > green ? red : green); 00368 if ((MagickRealType) blue > max) 00369 max=(MagickRealType) blue; 00370 if (max == 0.0) 00371 return; 00372 delta=max-min; 00373 *saturation=(double) (delta/max); 00374 *brightness=(double) (QuantumScale*max); 00375 if (delta == 0.0) 00376 return; 00377 if ((MagickRealType) red == max) 00378 *hue=(double) ((green-(MagickRealType) blue)/delta); 00379 else 00380 if ((MagickRealType) green == max) 00381 *hue=(double) (2.0+(blue-(MagickRealType) red)/delta); 00382 else 00383 *hue=(double) (4.0+(red-(MagickRealType) green)/delta); 00384 *hue/=6.0; 00385 if (*hue < 0.0) 00386 *hue+=1.0; 00387 } 00388 00389 /* 00390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00391 % % 00392 % % 00393 % % 00394 % C o n v e r t R G B T o H S L % 00395 % % 00396 % % 00397 % % 00398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00399 % 00400 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation, 00401 % lightness) triple. 00402 % 00403 % The format of the ConvertRGBToHSL method is: 00404 % 00405 % void ConvertRGBToHSL(const double red,const double green, 00406 % const double blue,double *hue,double *saturation,double *lightness) 00407 % 00408 % A description of each parameter follows: 00409 % 00410 % o red, green, blue: A Quantum value representing the red, green, and 00411 % blue component of a pixel.. 00412 % 00413 % o hue, saturation, lightness: A pointer to a double value representing a 00414 % component of the HSL color space. 00415 % 00416 */ 00417 00418 static inline double MagickMax(const double x,const double y) 00419 { 00420 if (x > y) 00421 return(x); 00422 return(y); 00423 } 00424 00425 static inline double MagickMin(const double x,const double y) 00426 { 00427 if (x < y) 00428 return(x); 00429 return(y); 00430 } 00431 00432 MagickExport void ConvertRGBToHSL(const double red,const double green, 00433 const double blue,double *hue,double *saturation,double *lightness) 00434 { 00435 MagickRealType 00436 b, 00437 delta, 00438 g, 00439 max, 00440 min, 00441 r; 00442 00443 /* 00444 Convert RGB to HSL colorspace. 00445 */ 00446 assert(hue != (double *) NULL); 00447 assert(saturation != (double *) NULL); 00448 assert(lightness != (double *) NULL); 00449 r=QuantumScale*red; 00450 g=QuantumScale*green; 00451 b=QuantumScale*blue; 00452 max=MagickMax(r,MagickMax(g,b)); 00453 min=MagickMin(r,MagickMin(g,b)); 00454 *lightness=(double) ((min+max)/2.0); 00455 delta=max-min; 00456 if (delta == 0.0) 00457 { 00458 *hue=0.0; 00459 *saturation=0.0; 00460 return; 00461 } 00462 if (*lightness < 0.5) 00463 *saturation=(double) (delta/(min+max)); 00464 else 00465 *saturation=(double) (delta/(2.0-max-min)); 00466 if (r == max) 00467 *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta; 00468 else 00469 if (g == max) 00470 *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/ 00471 delta; 00472 else 00473 if (b == max) 00474 *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+ 00475 (delta/2.0)))/delta; 00476 if (*hue < 0.0) 00477 *hue+=1.0; 00478 if (*hue > 1.0) 00479 *hue-=1.0; 00480 } 00481 00482 /* 00483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00484 % % 00485 % % 00486 % % 00487 % C o n v e r t R G B T o H W B % 00488 % % 00489 % % 00490 % % 00491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00492 % 00493 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness, 00494 % blackness) triple. 00495 % 00496 % The format of the ConvertRGBToHWB method is: 00497 % 00498 % void ConvertRGBToHWB(const double red,const double green, 00499 % const double blue,double *hue,double *whiteness,double *blackness) 00500 % 00501 % A description of each parameter follows: 00502 % 00503 % o red, green, blue: A Quantum value representing the red, green, and 00504 % blue component of a pixel. 00505 % 00506 % o hue, whiteness, blackness: A pointer to a double value representing a 00507 % component of the HWB color space. 00508 % 00509 */ 00510 MagickPrivate void ConvertRGBToHWB(const double red,const double green, 00511 const double blue,double *hue,double *whiteness,double *blackness) 00512 { 00513 long 00514 i; 00515 00516 MagickRealType 00517 f, 00518 v, 00519 w; 00520 00521 /* 00522 Convert RGB to HWB colorspace. 00523 */ 00524 assert(hue != (double *) NULL); 00525 assert(whiteness != (double *) NULL); 00526 assert(blackness != (double *) NULL); 00527 w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double) 00528 blue)); 00529 v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double) 00530 blue)); 00531 *blackness=1.0-QuantumScale*v; 00532 *whiteness=QuantumScale*w; 00533 if (v == w) 00534 { 00535 *hue=0.0; 00536 return; 00537 } 00538 f=((MagickRealType) red == w) ? green-(MagickRealType) blue : 00539 (((MagickRealType) green == w) ? blue-(MagickRealType) red : red- 00540 (MagickRealType) green); 00541 i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1); 00542 *hue=((double) i-f/(v-1.0*w))/6.0; 00543 } 00544 00545 /* 00546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00547 % % 00548 % % 00549 % % 00550 % E x p a n d A f f i n e % 00551 % % 00552 % % 00553 % % 00554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00555 % 00556 % ExpandAffine() computes the affine's expansion factor, i.e. the square root 00557 % of the factor by which the affine transform affects area. In an affine 00558 % transform composed of scaling, rotation, shearing, and translation, returns 00559 % the amount of scaling. 00560 % 00561 % The format of the ExpandAffine method is: 00562 % 00563 % double ExpandAffine(const AffineMatrix *affine) 00564 % 00565 % A description of each parameter follows: 00566 % 00567 % o expansion: Method ExpandAffine returns the affine's expansion factor. 00568 % 00569 % o affine: A pointer the affine transform of type AffineMatrix. 00570 % 00571 */ 00572 MagickExport double ExpandAffine(const AffineMatrix *affine) 00573 { 00574 assert(affine != (const AffineMatrix *) NULL); 00575 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry))); 00576 } 00577 00578 /* 00579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00580 % % 00581 % % 00582 % % 00583 % G e n e r a t e D i f f e r e n t i a l N o i s e % 00584 % % 00585 % % 00586 % % 00587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00588 % 00589 % GenerateDifferentialNoise() generates differentual noise. 00590 % 00591 % The format of the GenerateDifferentialNoise method is: 00592 % 00593 % double GenerateDifferentialNoise(RandomInfo *random_info, 00594 % const Quantum pixel,const NoiseType noise_type,const double attenuate) 00595 % 00596 % A description of each parameter follows: 00597 % 00598 % o random_info: the random info. 00599 % 00600 % o pixel: noise is relative to this pixel value. 00601 % 00602 % o noise_type: the type of noise. 00603 % 00604 % o attenuate: attenuate the noise. 00605 % 00606 */ 00607 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info, 00608 const Quantum pixel,const NoiseType noise_type,const double attenuate) 00609 { 00610 #define SigmaUniform (attenuate*0.015625) 00611 #define SigmaGaussian (attenuate*0.015625) 00612 #define SigmaImpulse (attenuate*0.1) 00613 #define SigmaLaplacian (attenuate*0.0390625) 00614 #define SigmaMultiplicativeGaussian (attenuate*0.5) 00615 #define SigmaPoisson (attenuate*12.5) 00616 #define TauGaussian (attenuate*0.078125) 00617 00618 double 00619 alpha, 00620 beta, 00621 noise, 00622 sigma; 00623 00624 alpha=GetPseudoRandomValue(random_info); 00625 switch (noise_type) 00626 { 00627 case UniformNoise: 00628 default: 00629 { 00630 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5)); 00631 break; 00632 } 00633 case GaussianNoise: 00634 { 00635 double 00636 gamma, 00637 tau; 00638 00639 if (alpha == 0.0) 00640 alpha=1.0; 00641 beta=GetPseudoRandomValue(random_info); 00642 gamma=sqrt(-2.0*log(alpha)); 00643 sigma=gamma*cos((double) (2.0*MagickPI*beta)); 00644 tau=gamma*sin((double) (2.0*MagickPI*beta)); 00645 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+ 00646 QuantumRange*TauGaussian*tau); 00647 break; 00648 } 00649 case ImpulseNoise: 00650 { 00651 if (alpha < (SigmaImpulse/2.0)) 00652 noise=0.0; 00653 else 00654 if (alpha >= (1.0-(SigmaImpulse/2.0))) 00655 noise=(double) QuantumRange; 00656 else 00657 noise=(double) pixel; 00658 break; 00659 } 00660 case LaplacianNoise: 00661 { 00662 if (alpha <= 0.5) 00663 { 00664 if (alpha <= MagickEpsilon) 00665 noise=(double) (pixel-QuantumRange); 00666 else 00667 noise=(double) (pixel+QuantumRange*SigmaLaplacian* 00668 log(2.0*alpha)+0.5); 00669 break; 00670 } 00671 beta=1.0-alpha; 00672 if (beta <= (0.5*MagickEpsilon)) 00673 noise=(double) (pixel+QuantumRange); 00674 else 00675 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5); 00676 break; 00677 } 00678 case MultiplicativeGaussianNoise: 00679 { 00680 sigma=1.0; 00681 if (alpha > MagickEpsilon) 00682 sigma=sqrt(-2.0*log(alpha)); 00683 beta=GetPseudoRandomValue(random_info); 00684 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma* 00685 cos((double) (2.0*MagickPI*beta))/2.0); 00686 break; 00687 } 00688 case PoissonNoise: 00689 { 00690 double 00691 poisson; 00692 00693 register ssize_t 00694 i; 00695 00696 poisson=exp(-SigmaPoisson*QuantumScale*pixel); 00697 for (i=0; alpha > poisson; i++) 00698 { 00699 beta=GetPseudoRandomValue(random_info); 00700 alpha*=beta; 00701 } 00702 noise=(double) (QuantumRange*i/SigmaPoisson); 00703 break; 00704 } 00705 case RandomNoise: 00706 { 00707 noise=(double) (QuantumRange*alpha); 00708 break; 00709 } 00710 } 00711 return(noise); 00712 } 00713 00714 /* 00715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00716 % % 00717 % % 00718 % % 00719 % G e t O p t i m a l K e r n e l W i d t h % 00720 % % 00721 % % 00722 % % 00723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00724 % 00725 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution 00726 % filter. Start with the minimum value of 3 pixels and walk out until we drop 00727 % below the threshold of one pixel numerical accuracy. 00728 % 00729 % The format of the GetOptimalKernelWidth method is: 00730 % 00731 % size_t GetOptimalKernelWidth(const double radius, 00732 % const double sigma) 00733 % 00734 % A description of each parameter follows: 00735 % 00736 % o width: Method GetOptimalKernelWidth returns the optimal width of 00737 % a convolution kernel. 00738 % 00739 % o radius: the radius of the Gaussian, in pixels, not counting the center 00740 % pixel. 00741 % 00742 % o sigma: the standard deviation of the Gaussian, in pixels. 00743 % 00744 */ 00745 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius, 00746 const double sigma) 00747 { 00748 double 00749 alpha, 00750 beta, 00751 gamma, 00752 normalize, 00753 value; 00754 00755 register ssize_t 00756 i; 00757 00758 size_t 00759 width; 00760 00761 ssize_t 00762 j; 00763 00764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00765 if (radius > MagickEpsilon) 00766 return((size_t) (2.0*ceil(radius)+1.0)); 00767 gamma=fabs(sigma); 00768 if (gamma <= MagickEpsilon) 00769 return(3UL); 00770 alpha=1.0/(2.0*gamma*gamma); 00771 beta=(double) (1.0/(MagickSQ2PI*gamma)); 00772 for (width=5; ; ) 00773 { 00774 normalize=0.0; 00775 j=(ssize_t) width/2; 00776 for (i=(-j); i <= j; i++) 00777 normalize+=exp(-((double) (i*i))*alpha)*beta; 00778 value=exp(-((double) (j*j))*alpha)*beta/normalize; 00779 if ((value < QuantumScale) || (value < MagickEpsilon)) 00780 break; 00781 width+=2; 00782 } 00783 return((size_t) (width-2)); 00784 } 00785 00786 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius, 00787 const double sigma) 00788 { 00789 double 00790 alpha, 00791 beta, 00792 gamma, 00793 normalize, 00794 value; 00795 00796 size_t 00797 width; 00798 00799 ssize_t 00800 j, 00801 u, 00802 v; 00803 00804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00805 if (radius > MagickEpsilon) 00806 return((size_t) (2.0*ceil(radius)+1.0)); 00807 gamma=fabs(sigma); 00808 if (gamma <= MagickEpsilon) 00809 return(3UL); 00810 alpha=1.0/(2.0*gamma*gamma); 00811 beta=(double) (1.0/(Magick2PI*gamma*gamma)); 00812 for (width=5; ; ) 00813 { 00814 normalize=0.0; 00815 j=(ssize_t) width/2; 00816 for (v=(-j); v <= j; v++) 00817 for (u=(-j); u <= j; u++) 00818 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta; 00819 value=exp(-((double) (j*j))*alpha)*beta/normalize; 00820 if ((value < QuantumScale) || (value < MagickEpsilon)) 00821 break; 00822 width+=2; 00823 } 00824 return((size_t) (width-2)); 00825 } 00826 00827 MagickPrivate size_t GetOptimalKernelWidth(const double radius, 00828 const double sigma) 00829 { 00830 return(GetOptimalKernelWidth1D(radius,sigma)); 00831 }