gem.c revision 7118edf0993ccec017e96e2172e6ac672d3e24cd
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% GGGG EEEEE M M % 73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% G E MM MM % 83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% G GG EEE M M M % 93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% G G E M M % 103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% GGGG EEEEE M M % 113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Graphic Gems - Graphic Support Methods % 143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Software Design % 163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% John Cristy % 173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% August 1996 % 183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 207e41fe84a841d7b9d7b36b245b65e9dcb3314943cristy% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % 213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% dedicated to making software imaging solutions freely available. % 223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% You may not use this file except in compliance with the License. You may % 243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% obtain a copy of the License at % 253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% http://www.imagemagick.org/script/license.php % 273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Unless required by applicable law or agreed to in writing, software % 293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% distributed under the License is distributed on an "AS IS" BASIS, % 303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% See the License for the specific language governing permissions and % 323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% limitations under the License. % 333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Include declarations. 423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h" 444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h" 454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h" 464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h" 47d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristy#include "MagickCore/gem-private.h" 484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h" 494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h" 504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h" 514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h" 524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h" 534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum.h" 544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h" 554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/random_.h" 564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resize.h" 574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/transform.h" 584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/signature-private.h" 593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% C o n v e r t H S B T o R G B % 663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red, 723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% green, blue) triple. 733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ConvertHSBToRGBImage method is: 753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% void ConvertHSBToRGB(const double hue,const double saturation, 773094b7f3243820cc5559d370412a9d406d074348cristy% const double brightness,double *red,double *green,double *blue) 783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o hue, saturation, brightness: A double value representing a 823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% component of the HSB color space. 833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o red, green, blue: A pointer to a pixel component of type Quantum. 853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 87d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristyMagickPrivate void ConvertHSBToRGB(const double hue,const double saturation, 883094b7f3243820cc5559d370412a9d406d074348cristy const double brightness,double *red,double *green,double *blue) 893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType 913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy f, 923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy h, 933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p, 943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy q, 953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy t; 963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Convert HSB to RGB colorspace. 993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 1003094b7f3243820cc5559d370412a9d406d074348cristy assert(red != (double *) NULL); 1013094b7f3243820cc5559d370412a9d406d074348cristy assert(green != (double *) NULL); 1023094b7f3243820cc5559d370412a9d406d074348cristy assert(blue != (double *) NULL); 10398a65d5565159ce59b24013f0e3d148428af50d6cristy if (saturation == 0.0) 1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 105bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*brightness); 1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *green=(*red); 1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *blue=(*red); 1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11098a65d5565159ce59b24013f0e3d148428af50d6cristy h=6.0*(hue-floor(hue)); 11198a65d5565159ce59b24013f0e3d148428af50d6cristy f=h-floor((double) h); 11298a65d5565159ce59b24013f0e3d148428af50d6cristy p=brightness*(1.0-saturation); 11398a65d5565159ce59b24013f0e3d148428af50d6cristy q=brightness*(1.0-saturation*f); 11498a65d5565159ce59b24013f0e3d148428af50d6cristy t=brightness*(1.0-(saturation*(1.0-f))); 1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch ((int) h) 1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 0: 1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 120bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*brightness); 121bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*t); 122bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*p); 1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 1: 1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 127bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*q); 128bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*brightness); 129bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*p); 1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 2: 1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 134bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*p); 135bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*brightness); 136bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*t); 1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 3: 1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 141bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*p); 142bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*q); 143bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness); 1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 4: 1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 148bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*t); 149bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*p); 150bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*brightness); 1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 5: 1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 155bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*brightness); 156bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*p); 157bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*q); 1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% C o n v e r t H S L T o R G B % 1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red, 1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% green, blue) triple. 1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ConvertHSLToRGBImage method is: 1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% void ConvertHSLToRGB(const double hue,const double saturation, 1803094b7f3243820cc5559d370412a9d406d074348cristy% const double lightness,double *red,double *green,double *blue) 1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o hue, saturation, lightness: A double value representing a 1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% component of the HSL color space. 1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o red, green, blue: A pointer to a pixel component of type Quantum. 1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline MagickRealType ConvertHueToRGB(MagickRealType m1, 1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType m2,MagickRealType hue) 1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (hue < 0.0) 1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy hue+=1.0; 1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (hue > 1.0) 1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy hue-=1.0; 1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if ((6.0*hue) < 1.0) 199a163b0c302844472b6f8e028b25ed090aa9bf84acristy return(m1+6.0*(m2-m1)*hue); 200a163b0c302844472b6f8e028b25ed090aa9bf84acristy if ((2.0*hue) < 1.0) 201a163b0c302844472b6f8e028b25ed090aa9bf84acristy return(m2); 202a163b0c302844472b6f8e028b25ed090aa9bf84acristy if ((3.0*hue) < 2.0) 203a163b0c302844472b6f8e028b25ed090aa9bf84acristy return(m1+6.0*(m2-m1)*(2.0/3.0-hue)); 204a163b0c302844472b6f8e028b25ed090aa9bf84acristy return(m1); 2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport void ConvertHSLToRGB(const double hue,const double saturation, 2083094b7f3243820cc5559d370412a9d406d074348cristy const double lightness,double *red,double *green,double *blue) 2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType 2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy b, 2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy g, 2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy r, 2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy m1, 2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy m2; 2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Convert HSL to RGB colorspace. 2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 2203094b7f3243820cc5559d370412a9d406d074348cristy assert(red != (double *) NULL); 2213094b7f3243820cc5559d370412a9d406d074348cristy assert(green != (double *) NULL); 2223094b7f3243820cc5559d370412a9d406d074348cristy assert(blue != (double *) NULL); 22398a65d5565159ce59b24013f0e3d148428af50d6cristy if (saturation == 0) 2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 225bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*lightness); 2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *green=(*red); 2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *blue=(*red); 2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 23027cabb8cf0354e5570dce70b226165433d8d5585cristy if (lightness < 0.5) 23198a65d5565159ce59b24013f0e3d148428af50d6cristy m2=lightness*(saturation+1.0); 23298a65d5565159ce59b24013f0e3d148428af50d6cristy else 23398a65d5565159ce59b24013f0e3d148428af50d6cristy m2=(lightness+saturation)-(lightness*saturation); 23498a65d5565159ce59b24013f0e3d148428af50d6cristy m1=2.0*lightness-m2; 2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy r=ConvertHueToRGB(m1,m2,hue+1.0/3.0); 2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy g=ConvertHueToRGB(m1,m2,hue); 2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy b=ConvertHueToRGB(m1,m2,hue-1.0/3.0); 238bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*r); 239bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*g); 240bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*b); 2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% C o n v e r t H W B T o R G B % 2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green, 2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% blue) triple. 2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ConvertHWBToRGBImage method is: 2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% void ConvertHWBToRGB(const double hue,const double whiteness, 2603094b7f3243820cc5559d370412a9d406d074348cristy% const double blackness,double *red,double *green,double *blue) 2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o hue, whiteness, blackness: A double value representing a 2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% component of the HWB color space. 2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o red, green, blue: A pointer to a pixel component of type Quantum. 2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 270d1dd6e4fefa0810b9893e6ac9418f79c97c1b39acristyMagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness, 2713094b7f3243820cc5559d370412a9d406d074348cristy const double blackness,double *red,double *green,double *blue) 2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType 2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy b, 2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy f, 2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy g, 2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy n, 2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy r, 2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v; 2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 281bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i; 2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Convert HWB to RGB colorspace. 2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 2873094b7f3243820cc5559d370412a9d406d074348cristy assert(red != (double *) NULL); 2883094b7f3243820cc5559d370412a9d406d074348cristy assert(green != (double *) NULL); 2893094b7f3243820cc5559d370412a9d406d074348cristy assert(blue != (double *) NULL); 2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v=1.0-blackness; 2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (hue == 0.0) 2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 293bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*v); 294bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*v); 295bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*v); 2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 298bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy i=(ssize_t) floor(6.0*hue); 2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy f=6.0*hue-i; 3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if ((i & 0x01) != 0) 3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy f=1.0-f; 3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy n=whiteness+f*(v-whiteness); /* linear interpolation */ 3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (i) 3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 6: 3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 0: r=v; g=n; b=whiteness; break; 3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 1: r=n; g=v; b=whiteness; break; 3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 2: r=whiteness; g=v; b=n; break; 3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 3: r=whiteness; g=n; b=v; break; 3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 4: r=n; g=whiteness; b=v; break; 3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case 5: r=v; g=whiteness; b=n; break; 3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 314bcfb0439a92607a9f340b846b4c4147753059e62cristy *red=ClampToQuantum((MagickRealType) QuantumRange*r); 315bcfb0439a92607a9f340b846b4c4147753059e62cristy *green=ClampToQuantum((MagickRealType) QuantumRange*g); 316bcfb0439a92607a9f340b846b4c4147753059e62cristy *blue=ClampToQuantum((MagickRealType) QuantumRange*b); 3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% C o n v e r t R G B T o H S B % 3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation, 3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% brightness) triple. 3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ConvertRGBToHSB method is: 3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3353094b7f3243820cc5559d370412a9d406d074348cristy% void ConvertRGBToHSB(const double red,const double green, 3363094b7f3243820cc5559d370412a9d406d074348cristy% const double blue,double *hue,double *saturation,double *brightness) 3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o red, green, blue: A Quantum value representing the red, green, and 3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% blue component of a pixel.. 3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o hue, saturation, brightness: A pointer to a double value representing a 3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% component of the HSB color space. 3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 3473094b7f3243820cc5559d370412a9d406d074348cristyMagickPrivate void ConvertRGBToHSB(const double red,const double green, 3483094b7f3243820cc5559d370412a9d406d074348cristy const double blue,double *hue,double *saturation,double *brightness) 3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType 3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy delta, 3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy max, 3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy min; 3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Convert RGB to HSB colorspace. 3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(hue != (double *) NULL); 3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(saturation != (double *) NULL); 3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(brightness != (double *) NULL); 3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=0.0; 3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *saturation=0.0; 3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *brightness=0.0; 3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy min=(MagickRealType) (red < green ? red : green); 3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if ((MagickRealType) blue < min) 3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy min=(MagickRealType) blue; 3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy max=(MagickRealType) (red > green ? red : green); 3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if ((MagickRealType) blue > max) 3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy max=(MagickRealType) blue; 3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (max == 0.0) 3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy delta=max-min; 3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *saturation=(double) (delta/max); 3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *brightness=(double) (QuantumScale*max); 3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (delta == 0.0) 3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 37718b17443128598500357da7bff2f01683cf32890cristy if ((MagickRealType) red == max) 37818b17443128598500357da7bff2f01683cf32890cristy *hue=(double) ((green-(MagickRealType) blue)/delta); 3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 38018b17443128598500357da7bff2f01683cf32890cristy if ((MagickRealType) green == max) 38118b17443128598500357da7bff2f01683cf32890cristy *hue=(double) (2.0+(blue-(MagickRealType) red)/delta); 3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 38318b17443128598500357da7bff2f01683cf32890cristy *hue=(double) (4.0+(red-(MagickRealType) green)/delta); 38418b17443128598500357da7bff2f01683cf32890cristy *hue/=6.0; 3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (*hue < 0.0) 3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue+=1.0; 3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% C o n v e r t R G B T o H S L % 3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation, 4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% lightness) triple. 4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ConvertRGBToHSL method is: 4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4053094b7f3243820cc5559d370412a9d406d074348cristy% void ConvertRGBToHSL(const double red,const double green, 4063094b7f3243820cc5559d370412a9d406d074348cristy% const double blue,double *hue,double *saturation,double *lightness) 4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o red, green, blue: A Quantum value representing the red, green, and 4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% blue component of a pixel.. 4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o hue, saturation, lightness: A pointer to a double value representing a 4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% component of the HSL color space. 4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline double MagickMax(const double x,const double y) 4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (x > y) 4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(x); 4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(y); 4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline double MagickMin(const double x,const double y) 4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (x < y) 4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(x); 4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(y); 4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4323094b7f3243820cc5559d370412a9d406d074348cristyMagickExport void ConvertRGBToHSL(const double red,const double green, 4333094b7f3243820cc5559d370412a9d406d074348cristy const double blue,double *hue,double *saturation,double *lightness) 4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType 4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy b, 4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy delta, 4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy g, 4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy max, 4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy min, 4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy r; 4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Convert RGB to HSL colorspace. 4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(hue != (double *) NULL); 4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(saturation != (double *) NULL); 4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(lightness != (double *) NULL); 4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy r=QuantumScale*red; 4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy g=QuantumScale*green; 4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy b=QuantumScale*blue; 4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy max=MagickMax(r,MagickMax(g,b)); 4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy min=MagickMin(r,MagickMin(g,b)); 4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *lightness=(double) ((min+max)/2.0); 4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy delta=max-min; 4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (delta == 0.0) 4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=0.0; 4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *saturation=0.0; 4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (*lightness < 0.5) 4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *saturation=(double) (delta/(min+max)); 4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *saturation=(double) (delta/(2.0-max-min)); 4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (r == max) 4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=((((max-b)/6.0)+(delta/2.0))-(((max-g)/6.0)+(delta/2.0)))/delta; 4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (g == max) 4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=(1.0/3.0)+((((max-r)/6.0)+(delta/2.0))-(((max-b)/6.0)+(delta/2.0)))/ 4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy delta; 4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (b == max) 4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=(2.0/3.0)+((((max-g)/6.0)+(delta/2.0))-(((max-r)/6.0)+ 4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (delta/2.0)))/delta; 4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (*hue < 0.0) 4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue+=1.0; 4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (*hue > 1.0) 4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue-=1.0; 4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% C o n v e r t R G B T o H W B % 4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness, 4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% blackness) triple. 4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ConvertRGBToHWB method is: 4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4983094b7f3243820cc5559d370412a9d406d074348cristy% void ConvertRGBToHWB(const double red,const double green, 4993094b7f3243820cc5559d370412a9d406d074348cristy% const double blue,double *hue,double *whiteness,double *blackness) 5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o red, green, blue: A Quantum value representing the red, green, and 5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% blue component of a pixel. 5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o hue, whiteness, blackness: A pointer to a double value representing a 5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% component of the HWB color space. 5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 5103094b7f3243820cc5559d370412a9d406d074348cristyMagickPrivate void ConvertRGBToHWB(const double red,const double green, 5113094b7f3243820cc5559d370412a9d406d074348cristy const double blue,double *hue,double *whiteness,double *blackness) 5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 513bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy long 514bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy i; 515bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickRealType 5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy f, 5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v, 5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy w; 5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Convert RGB to HWB colorspace. 5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(hue != (double *) NULL); 5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(whiteness != (double *) NULL); 5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(blackness != (double *) NULL); 5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy w=(MagickRealType) MagickMin((double) red,MagickMin((double) green,(double) 5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy blue)); 5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v=(MagickRealType) MagickMax((double) red,MagickMax((double) green,(double) 5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy blue)); 5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *blackness=1.0-QuantumScale*v; 5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *whiteness=QuantumScale*w; 5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (v == w) 5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=0.0; 5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return; 5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy f=((MagickRealType) red == w) ? green-(MagickRealType) blue : 5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (((MagickRealType) green == w) ? blue-(MagickRealType) red : red- 5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (MagickRealType) green); 5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=((MagickRealType) red == w) ? 3 : (((MagickRealType) green == w) ? 5 : 1); 5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *hue=((double) i-f/(v-1.0*w))/6.0; 5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% E x p a n d A f f i n e % 5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ExpandAffine() computes the affine's expansion factor, i.e. the square root 5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% of the factor by which the affine transform affects area. In an affine 5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% transform composed of scaling, rotation, shearing, and translation, returns 5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% the amount of scaling. 5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ExpandAffine method is: 5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% double ExpandAffine(const AffineMatrix *affine) 5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o expansion: Method ExpandAffine returns the affine's expansion factor. 5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o affine: A pointer the affine transform of type AffineMatrix. 5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport double ExpandAffine(const AffineMatrix *affine) 5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(affine != (const AffineMatrix *) NULL); 5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry))); 5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 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 % 5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 58982b1583d4ca9179180de2754e6c25eef115cc181cristy% GenerateDifferentialNoise() generates differentual noise. 5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the GenerateDifferentialNoise method is: 5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% double GenerateDifferentialNoise(RandomInfo *random_info, 5949ed1f810381187775960350780d4d619c111dc4bcristy% const Quantum pixel,const NoiseType noise_type,const double attenuate) 5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o random_info: the random info. 5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o pixel: noise is relative to this pixel value. 6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o noise_type: the type of noise. 6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o attenuate: attenuate the noise. 6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 6078ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info, 6089ed1f810381187775960350780d4d619c111dc4bcristy const Quantum pixel,const NoiseType noise_type,const double attenuate) 6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 6107118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaUniform (attenuate*0.015625) 6117118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaGaussian (attenuate*0.015625) 6127118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaImpulse (attenuate*0.1) 6137118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaLaplacian (attenuate*0.0390625) 6147118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaMultiplicativeGaussian (attenuate*0.5) 6157118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define SigmaPoisson (attenuate*0.05/0.0001953125) 6167118edf0993ccec017e96e2172e6ac672d3e24cdcristy#define TauGaussian (attenuate*0.078125) 6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 618adb41caab5f958d39a3466968df0be65ef2b1045cristy double 6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy alpha, 6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy beta, 6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy noise, 6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy sigma; 6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy alpha=GetPseudoRandomValue(random_info); 6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (noise_type) 6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case UniformNoise: 6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6307118edf0993ccec017e96e2172e6ac672d3e24cdcristy noise=(double) pixel+QuantumRange*SigmaUniform*(alpha-0.5); 6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case GaussianNoise: 6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 635adb41caab5f958d39a3466968df0be65ef2b1045cristy double 63662faa60a11bc656bbeb1b418a95de40815a4490ccristy gamma, 6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy tau; 6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 639adb41caab5f958d39a3466968df0be65ef2b1045cristy if (alpha == 0.0) 640adb41caab5f958d39a3466968df0be65ef2b1045cristy alpha=1.0; 6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy beta=GetPseudoRandomValue(random_info); 64262faa60a11bc656bbeb1b418a95de40815a4490ccristy gamma=sqrt(-2.0*log(alpha)); 64355a91cddcdea3aa002893186a773e1704884a9dfcristy sigma=gamma*cos((double) (2.0*MagickPI*beta)); 64455a91cddcdea3aa002893186a773e1704884a9dfcristy tau=gamma*sin((double) (2.0*MagickPI*beta)); 6457118edf0993ccec017e96e2172e6ac672d3e24cdcristy noise=(double) pixel+sqrt((double) pixel)*SigmaGaussian*sigma+ 6467118edf0993ccec017e96e2172e6ac672d3e24cdcristy QuantumRange*TauGaussian*tau; 6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case ImpulseNoise: 6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (alpha < (SigmaImpulse/2.0)) 6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy noise=0.0; 65337c2407b40ceacf637731f133d9dbff27a39f669cristy else 65437c2407b40ceacf637731f133d9dbff27a39f669cristy if (alpha >= (1.0-(SigmaImpulse/2.0))) 65537c2407b40ceacf637731f133d9dbff27a39f669cristy noise=(double) QuantumRange; 65637c2407b40ceacf637731f133d9dbff27a39f669cristy else 65737c2407b40ceacf637731f133d9dbff27a39f669cristy noise=(double) pixel; 6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case LaplacianNoise: 6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (alpha <= 0.5) 6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6647118edf0993ccec017e96e2172e6ac672d3e24cdcristy if (alpha <= MagickEpsilon) 665adb41caab5f958d39a3466968df0be65ef2b1045cristy noise=(double) pixel-(double) QuantumRange; 6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 66737c2407b40ceacf637731f133d9dbff27a39f669cristy noise=(double) pixel+QuantumRange*SigmaLaplacian* 6687118edf0993ccec017e96e2172e6ac672d3e24cdcristy log(2.0*alpha)+0.5; 6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy beta=1.0-alpha; 6727118edf0993ccec017e96e2172e6ac672d3e24cdcristy if (beta <= (0.5*MagickEpsilon)) 673adb41caab5f958d39a3466968df0be65ef2b1045cristy noise=(double) (pixel+QuantumRange); 6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 6757118edf0993ccec017e96e2172e6ac672d3e24cdcristy noise=(double) pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5; 6767118edf0993ccec017e96e2172e6ac672d3e24cdcristy break; 6777118edf0993ccec017e96e2172e6ac672d3e24cdcristy } 6787118edf0993ccec017e96e2172e6ac672d3e24cdcristy case MultiplicativeGaussianNoise: 6797118edf0993ccec017e96e2172e6ac672d3e24cdcristy { 6807118edf0993ccec017e96e2172e6ac672d3e24cdcristy sigma=1.0; 6817118edf0993ccec017e96e2172e6ac672d3e24cdcristy if (alpha > MagickEpsilon) 6827118edf0993ccec017e96e2172e6ac672d3e24cdcristy sigma=sqrt(-2.0*log(alpha)); 6837118edf0993ccec017e96e2172e6ac672d3e24cdcristy beta=GetPseudoRandomValue(random_info); 6847118edf0993ccec017e96e2172e6ac672d3e24cdcristy noise=(double) pixel+pixel*SigmaMultiplicativeGaussian*sigma* 6857118edf0993ccec017e96e2172e6ac672d3e24cdcristy cos((double) (2.0*MagickPI*beta))/2.0; 6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case PoissonNoise: 6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 690adb41caab5f958d39a3466968df0be65ef2b1045cristy double 6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy poisson; 6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 693bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i; 6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6967118edf0993ccec017e96e2172e6ac672d3e24cdcristy poisson=exp(-SigmaPoisson*QuantumScale*pixel); 6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for (i=0; alpha > poisson; i++) 6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy beta=GetPseudoRandomValue(random_info); 7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy alpha*=beta; 7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7027118edf0993ccec017e96e2172e6ac672d3e24cdcristy noise=(double) QuantumRange*i/SigmaPoisson; 7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy case RandomNoise: 7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7072a42b1b23d5468cc276418f2cb7c786be39d7339cristy noise=(double) QuantumRange*alpha; 7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(noise); 7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% G e t O p t i m a l K e r n e l W i d t h % 7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% GetOptimalKernelWidth() computes the optimal kernel radius for a convolution 7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% filter. Start with the minimum value of 3 pixels and walk out until we drop 7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% below the threshold of one pixel numerical accuracy. 7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the GetOptimalKernelWidth method is: 7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 731bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy% size_t GetOptimalKernelWidth(const double radius, 7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% const double sigma) 7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o width: Method GetOptimalKernelWidth returns the optimal width of 7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% a convolution kernel. 7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o radius: the radius of the Gaussian, in pixels, not counting the center 7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% pixel. 7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o sigma: the standard deviation of the Gaussian, in pixels. 7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 7458ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth1D(const double radius, 746e96405a0f45f803fb9c26f75e7bdee252437febbcristy const double sigma) 7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 748e96405a0f45f803fb9c26f75e7bdee252437febbcristy double 749e96405a0f45f803fb9c26f75e7bdee252437febbcristy alpha, 750e96405a0f45f803fb9c26f75e7bdee252437febbcristy beta, 751e96405a0f45f803fb9c26f75e7bdee252437febbcristy gamma, 7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy normalize, 753e96405a0f45f803fb9c26f75e7bdee252437febbcristy value; 7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 755bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 75647e00508ba238041491b7e0daf628ae3f21ab91ecristy i; 75747e00508ba238041491b7e0daf628ae3f21ab91ecristy 758bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 75947e00508ba238041491b7e0daf628ae3f21ab91ecristy width; 7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7619d314ff2c17a77996c05413c2013880387e50f0ecristy ssize_t 7629d314ff2c17a77996c05413c2013880387e50f0ecristy j; 7639d314ff2c17a77996c05413c2013880387e50f0ecristy 7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 76547e00508ba238041491b7e0daf628ae3f21ab91ecristy if (radius > MagickEpsilon) 766bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return((size_t) (2.0*ceil(radius)+1.0)); 767e96405a0f45f803fb9c26f75e7bdee252437febbcristy gamma=fabs(sigma); 768e96405a0f45f803fb9c26f75e7bdee252437febbcristy if (gamma <= MagickEpsilon) 769c106172cd6da00b6c8fd6a4c06efdd4aa32c7f06anthony return(3UL); 770e96405a0f45f803fb9c26f75e7bdee252437febbcristy alpha=1.0/(2.0*gamma*gamma); 77155a91cddcdea3aa002893186a773e1704884a9dfcristy beta=(double) (1.0/(MagickSQ2PI*gamma)); 7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for (width=5; ; ) 7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy normalize=0.0; 775bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy j=(ssize_t) width/2; 77647e00508ba238041491b7e0daf628ae3f21ab91ecristy for (i=(-j); i <= j; i++) 777e96405a0f45f803fb9c26f75e7bdee252437febbcristy normalize+=exp(-((double) (i*i))*alpha)*beta; 778e96405a0f45f803fb9c26f75e7bdee252437febbcristy value=exp(-((double) (j*j))*alpha)*beta/normalize; 77920908dac8b2f15a9c0289728e57698bde5b74094cristy if ((value < QuantumScale) || (value < MagickEpsilon)) 7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width+=2; 7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 783bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return((size_t) (width-2)); 7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7868ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth2D(const double radius, 787e96405a0f45f803fb9c26f75e7bdee252437febbcristy const double sigma) 7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 78947e00508ba238041491b7e0daf628ae3f21ab91ecristy double 790e96405a0f45f803fb9c26f75e7bdee252437febbcristy alpha, 791e96405a0f45f803fb9c26f75e7bdee252437febbcristy beta, 792e96405a0f45f803fb9c26f75e7bdee252437febbcristy gamma, 7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy normalize, 794e96405a0f45f803fb9c26f75e7bdee252437febbcristy value; 7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7969d314ff2c17a77996c05413c2013880387e50f0ecristy size_t 7979d314ff2c17a77996c05413c2013880387e50f0ecristy width; 7989d314ff2c17a77996c05413c2013880387e50f0ecristy 799bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 80047e00508ba238041491b7e0daf628ae3f21ab91ecristy j, 8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy u, 8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v; 8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 80547e00508ba238041491b7e0daf628ae3f21ab91ecristy if (radius > MagickEpsilon) 806bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return((size_t) (2.0*ceil(radius)+1.0)); 807e96405a0f45f803fb9c26f75e7bdee252437febbcristy gamma=fabs(sigma); 808e96405a0f45f803fb9c26f75e7bdee252437febbcristy if (gamma <= MagickEpsilon) 809c106172cd6da00b6c8fd6a4c06efdd4aa32c7f06anthony return(3UL); 810e96405a0f45f803fb9c26f75e7bdee252437febbcristy alpha=1.0/(2.0*gamma*gamma); 81155a91cddcdea3aa002893186a773e1704884a9dfcristy beta=(double) (1.0/(Magick2PI*gamma*gamma)); 8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for (width=5; ; ) 8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy normalize=0.0; 815bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy j=(ssize_t) width/2; 81647e00508ba238041491b7e0daf628ae3f21ab91ecristy for (v=(-j); v <= j; v++) 81747e00508ba238041491b7e0daf628ae3f21ab91ecristy for (u=(-j); u <= j; u++) 818e96405a0f45f803fb9c26f75e7bdee252437febbcristy normalize+=exp(-((double) (u*u+v*v))*alpha)*beta; 819e96405a0f45f803fb9c26f75e7bdee252437febbcristy value=exp(-((double) (j*j))*alpha)*beta/normalize; 82020908dac8b2f15a9c0289728e57698bde5b74094cristy if ((value < QuantumScale) || (value < MagickEpsilon)) 8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width+=2; 8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 824bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return((size_t) (width-2)); 8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8278ea81224e9ff022e56eb2cddb12860a8b2e90411cristyMagickPrivate size_t GetOptimalKernelWidth(const double radius, 8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy const double sigma) 8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(GetOptimalKernelWidth1D(radius,sigma)); 8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 832