1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% GGGG EEEEE M M % 7% G E MM MM % 8% G GG EEE M M M % 9% G G E M M % 10% GGGG EEEEE M M % 11% % 12% % 13% Graphic Gems - Graphic Support Methods % 14% % 15% Software Design % 16% Cristy % 17% August 1996 % 18% % 19% % 20% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21% dedicated to making software imaging solutions freely available. % 22% % 23% You may not use this file except in compliance with the License. You may % 24% obtain a copy of the License at % 25% % 26% http://www.imagemagick.org/script/license.php % 27% % 28% Unless required by applicable law or agreed to in writing, software % 29% distributed under the License is distributed on an "AS IS" BASIS, % 30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31% See the License for the specific language governing permissions and % 32% limitations under the License. % 33% % 34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35% 36% 37% 38*/ 39 40/* 41 Include declarations. 42*/ 43#include "MagickCore/studio.h" 44#include "MagickCore/color-private.h" 45#include "MagickCore/draw.h" 46#include "MagickCore/gem.h" 47#include "MagickCore/gem-private.h" 48#include "MagickCore/image.h" 49#include "MagickCore/image-private.h" 50#include "MagickCore/log.h" 51#include "MagickCore/memory_.h" 52#include "MagickCore/pixel-accessor.h" 53#include "MagickCore/pixel-private.h" 54#include "MagickCore/quantum.h" 55#include "MagickCore/quantum-private.h" 56#include "MagickCore/random_.h" 57#include "MagickCore/resize.h" 58#include "MagickCore/transform.h" 59#include "MagickCore/signature-private.h" 60 61/* 62%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 63% % 64% % 65% % 66% C o n v e r t H C L T o R G B % 67% % 68% % 69% % 70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 71% 72% ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green, 73% blue) triple. 74% 75% The format of the ConvertHCLToRGBImage method is: 76% 77% void ConvertHCLToRGB(const double hue,const double chroma, 78% const double luma,double *red,double *green,double *blue) 79% 80% A description of each parameter follows: 81% 82% o hue, chroma, luma: A double value representing a component of the 83% HCL color space. 84% 85% o red, green, blue: A pointer to a pixel component of type Quantum. 86% 87*/ 88MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma, 89 const double luma,double *red,double *green,double *blue) 90{ 91 double 92 b, 93 c, 94 g, 95 h, 96 m, 97 r, 98 x; 99 100 /* 101 Convert HCL to RGB colorspace. 102 */ 103 assert(red != (double *) NULL); 104 assert(green != (double *) NULL); 105 assert(blue != (double *) NULL); 106 h=6.0*hue; 107 c=chroma; 108 x=c*(1.0-fabs(fmod(h,2.0)-1.0)); 109 r=0.0; 110 g=0.0; 111 b=0.0; 112 if ((0.0 <= h) && (h < 1.0)) 113 { 114 r=c; 115 g=x; 116 } 117 else 118 if ((1.0 <= h) && (h < 2.0)) 119 { 120 r=x; 121 g=c; 122 } 123 else 124 if ((2.0 <= h) && (h < 3.0)) 125 { 126 g=c; 127 b=x; 128 } 129 else 130 if ((3.0 <= h) && (h < 4.0)) 131 { 132 g=x; 133 b=c; 134 } 135 else 136 if ((4.0 <= h) && (h < 5.0)) 137 { 138 r=x; 139 b=c; 140 } 141 else 142 if ((5.0 <= h) && (h < 6.0)) 143 { 144 r=c; 145 b=x; 146 } 147 m=luma-(0.298839*r+0.586811*g+0.114350*b); 148 *red=QuantumRange*(r+m); 149 *green=QuantumRange*(g+m); 150 *blue=QuantumRange*(b+m); 151} 152 153/* 154%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 155% % 156% % 157% % 158% C o n v e r t H C L p T o R G B % 159% % 160% % 161% % 162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 163% 164% ConvertHCLpToRGB() transforms a (hue, chroma, luma) to a (red, green, 165% blue) triple. Since HCL colorspace is wider than RGB, we instead choose a 166% saturation strategy to project it on the RGB cube. 167% 168% The format of the ConvertHCLpToRGBImage method is: 169% 170% void ConvertHCLpToRGB(const double hue,const double chroma, 171% const double luma,double *red,double *green,double *blue) 172% 173% A description of each parameter follows: 174% 175% o hue, chroma, luma: A double value representing a componenet of the 176% HCLp color space. 177% 178% o red, green, blue: A pointer to a pixel component of type Quantum. 179% 180*/ 181MagickPrivate void ConvertHCLpToRGB(const double hue,const double chroma, 182 const double luma,double *red,double *green,double *blue) 183{ 184 double 185 b, 186 c, 187 g, 188 h, 189 m, 190 r, 191 x, 192 z; 193 194 /* 195 Convert HCLp to RGB colorspace. 196 */ 197 assert(red != (double *) NULL); 198 assert(green != (double *) NULL); 199 assert(blue != (double *) NULL); 200 h=6.0*hue; 201 c=chroma; 202 x=c*(1.0-fabs(fmod(h,2.0)-1.0)); 203 r=0.0; 204 g=0.0; 205 b=0.0; 206 if ((0.0 <= h) && (h < 1.0)) 207 { 208 r=c; 209 g=x; 210 } 211 else 212 if ((1.0 <= h) && (h < 2.0)) 213 { 214 r=x; 215 g=c; 216 } 217 else 218 if ((2.0 <= h) && (h < 3.0)) 219 { 220 g=c; 221 b=x; 222 } 223 else 224 if ((3.0 <= h) && (h < 4.0)) 225 { 226 g=x; 227 b=c; 228 } 229 else 230 if ((4.0 <= h) && (h < 5.0)) 231 { 232 r=x; 233 b=c; 234 } 235 else 236 if ((5.0 <= h) && (h < 6.0)) 237 { 238 r=c; 239 b=x; 240 } 241 m=luma-(0.298839*r+0.586811*g+0.114350*b); 242 z=1.0; 243 if (m < 0.0) 244 { 245 z=luma/(luma-m); 246 m=0.0; 247 } 248 else 249 if (m+c > 1.0) 250 { 251 z=(1.0-luma)/(m+c-luma); 252 m=1.0-z*c; 253 } 254 *red=QuantumRange*(z*r+m); 255 *green=QuantumRange*(z*g+m); 256 *blue=QuantumRange*(z*b+m); 257} 258 259/* 260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 261% % 262% % 263% % 264% C o n v e r t H S B T o R G B % 265% % 266% % 267% % 268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 269% 270% ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red, 271% green, blue) triple. 272% 273% The format of the ConvertHSBToRGBImage method is: 274% 275% void ConvertHSBToRGB(const double hue,const double saturation, 276% const double brightness,double *red,double *green,double *blue) 277% 278% A description of each parameter follows: 279% 280% o hue, saturation, brightness: A double value representing a 281% component of the HSB color space. 282% 283% o red, green, blue: A pointer to a pixel component of type Quantum. 284% 285*/ 286MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation, 287 const double brightness,double *red,double *green,double *blue) 288{ 289 double 290 f, 291 h, 292 p, 293 q, 294 t; 295 296 /* 297 Convert HSB to RGB colorspace. 298 */ 299 assert(red != (double *) NULL); 300 assert(green != (double *) NULL); 301 assert(blue != (double *) NULL); 302 if (fabs(saturation) < MagickEpsilon) 303 { 304 *red=QuantumRange*brightness; 305 *green=(*red); 306 *blue=(*red); 307 return; 308 } 309 h=6.0*(hue-floor(hue)); 310 f=h-floor((double) h); 311 p=brightness*(1.0-saturation); 312 q=brightness*(1.0-saturation*f); 313 t=brightness*(1.0-(saturation*(1.0-f))); 314 switch ((int) h) 315 { 316 case 0: 317 default: 318 { 319 *red=QuantumRange*brightness; 320 *green=QuantumRange*t; 321 *blue=QuantumRange*p; 322 break; 323 } 324 case 1: 325 { 326 *red=QuantumRange*q; 327 *green=QuantumRange*brightness; 328 *blue=QuantumRange*p; 329 break; 330 } 331 case 2: 332 { 333 *red=QuantumRange*p; 334 *green=QuantumRange*brightness; 335 *blue=QuantumRange*t; 336 break; 337 } 338 case 3: 339 { 340 *red=QuantumRange*p; 341 *green=QuantumRange*q; 342 *blue=QuantumRange*brightness; 343 break; 344 } 345 case 4: 346 { 347 *red=QuantumRange*t; 348 *green=QuantumRange*p; 349 *blue=QuantumRange*brightness; 350 break; 351 } 352 case 5: 353 { 354 *red=QuantumRange*brightness; 355 *green=QuantumRange*p; 356 *blue=QuantumRange*q; 357 break; 358 } 359 } 360} 361 362/* 363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 364% % 365% % 366% % 367% C o n v e r t H S I T o R G B % 368% % 369% % 370% % 371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 372% 373% ConvertHSIToRGB() transforms a (hue, saturation, intensity) to a (red, 374% green, blue) triple. 375% 376% The format of the ConvertHSIToRGBImage method is: 377% 378% void ConvertHSIToRGB(const double hue,const double saturation, 379% const double intensity,double *red,double *green,double *blue) 380% 381% A description of each parameter follows: 382% 383% o hue, saturation, intensity: A double value representing a 384% component of the HSI color space. 385% 386% o red, green, blue: A pointer to a pixel component of type Quantum. 387% 388*/ 389MagickPrivate void ConvertHSIToRGB(const double hue,const double saturation, 390 const double intensity,double *red,double *green,double *blue) 391{ 392 double 393 b, 394 g, 395 h, 396 r; 397 398 /* 399 Convert HSI to RGB colorspace. 400 */ 401 assert(red != (double *) NULL); 402 assert(green != (double *) NULL); 403 assert(blue != (double *) NULL); 404 h=360.0*hue; 405 h-=360.0*floor(h/360.0); 406 if (h < 120.0) 407 { 408 b=intensity*(1.0-saturation); 409 r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)* 410 (MagickPI/180.0))); 411 g=3.0*intensity-r-b; 412 } 413 else 414 if (h < 240.0) 415 { 416 h-=120.0; 417 r=intensity*(1.0-saturation); 418 g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)* 419 (MagickPI/180.0))); 420 b=3.0*intensity-r-g; 421 } 422 else 423 { 424 h-=240.0; 425 g=intensity*(1.0-saturation); 426 b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)* 427 (MagickPI/180.0))); 428 r=3.0*intensity-g-b; 429 } 430 *red=QuantumRange*r; 431 *green=QuantumRange*g; 432 *blue=QuantumRange*b; 433} 434 435/* 436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 437% % 438% % 439% % 440% C o n v e r t H S L T o R G B % 441% % 442% % 443% % 444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 445% 446% ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red, 447% green, blue) triple. 448% 449% The format of the ConvertHSLToRGBImage method is: 450% 451% void ConvertHSLToRGB(const double hue,const double saturation, 452% const double lightness,double *red,double *green,double *blue) 453% 454% A description of each parameter follows: 455% 456% o hue, saturation, lightness: A double value representing a 457% component of the HSL color space. 458% 459% o red, green, blue: A pointer to a pixel component of type Quantum. 460% 461*/ 462MagickExport void ConvertHSLToRGB(const double hue,const double saturation, 463 const double lightness,double *red,double *green,double *blue) 464{ 465 double 466 c, 467 h, 468 min, 469 x; 470 471 /* 472 Convert HSL to RGB colorspace. 473 */ 474 assert(red != (double *) NULL); 475 assert(green != (double *) NULL); 476 assert(blue != (double *) NULL); 477 h=hue*360.0; 478 if (lightness <= 0.5) 479 c=2.0*lightness*saturation; 480 else 481 c=(2.0-2.0*lightness)*saturation; 482 min=lightness-0.5*c; 483 h-=360.0*floor(h/360.0); 484 h/=60.0; 485 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0)); 486 switch ((int) floor(h)) 487 { 488 case 0: 489 { 490 *red=QuantumRange*(min+c); 491 *green=QuantumRange*(min+x); 492 *blue=QuantumRange*min; 493 break; 494 } 495 case 1: 496 { 497 *red=QuantumRange*(min+x); 498 *green=QuantumRange*(min+c); 499 *blue=QuantumRange*min; 500 break; 501 } 502 case 2: 503 { 504 *red=QuantumRange*min; 505 *green=QuantumRange*(min+c); 506 *blue=QuantumRange*(min+x); 507 break; 508 } 509 case 3: 510 { 511 *red=QuantumRange*min; 512 *green=QuantumRange*(min+x); 513 *blue=QuantumRange*(min+c); 514 break; 515 } 516 case 4: 517 { 518 *red=QuantumRange*(min+x); 519 *green=QuantumRange*min; 520 *blue=QuantumRange*(min+c); 521 break; 522 } 523 case 5: 524 { 525 *red=QuantumRange*(min+c); 526 *green=QuantumRange*min; 527 *blue=QuantumRange*(min+x); 528 break; 529 } 530 default: 531 { 532 *red=0.0; 533 *green=0.0; 534 *blue=0.0; 535 } 536 } 537} 538 539/* 540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 541% % 542% % 543% % 544% C o n v e r t H S V T o R G B % 545% % 546% % 547% % 548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 549% 550% ConvertHSVToRGB() transforms a (hue, saturation, value) to a (red, 551% green, blue) triple. 552% 553% The format of the ConvertHSVToRGBImage method is: 554% 555% void ConvertHSVToRGB(const double hue,const double saturation, 556% const double value,double *red,double *green,double *blue) 557% 558% A description of each parameter follows: 559% 560% o hue, saturation, value: A double value representing a 561% component of the HSV color space. 562% 563% o red, green, blue: A pointer to a pixel component of type Quantum. 564% 565*/ 566MagickPrivate void ConvertHSVToRGB(const double hue,const double saturation, 567 const double value,double *red,double *green,double *blue) 568{ 569 double 570 c, 571 h, 572 min, 573 x; 574 575 /* 576 Convert HSV to RGB colorspace. 577 */ 578 assert(red != (double *) NULL); 579 assert(green != (double *) NULL); 580 assert(blue != (double *) NULL); 581 h=hue*360.0; 582 c=value*saturation; 583 min=value-c; 584 h-=360.0*floor(h/360.0); 585 h/=60.0; 586 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0)); 587 switch ((int) floor(h)) 588 { 589 case 0: 590 { 591 *red=QuantumRange*(min+c); 592 *green=QuantumRange*(min+x); 593 *blue=QuantumRange*min; 594 break; 595 } 596 case 1: 597 { 598 *red=QuantumRange*(min+x); 599 *green=QuantumRange*(min+c); 600 *blue=QuantumRange*min; 601 break; 602 } 603 case 2: 604 { 605 *red=QuantumRange*min; 606 *green=QuantumRange*(min+c); 607 *blue=QuantumRange*(min+x); 608 break; 609 } 610 case 3: 611 { 612 *red=QuantumRange*min; 613 *green=QuantumRange*(min+x); 614 *blue=QuantumRange*(min+c); 615 break; 616 } 617 case 4: 618 { 619 *red=QuantumRange*(min+x); 620 *green=QuantumRange*min; 621 *blue=QuantumRange*(min+c); 622 break; 623 } 624 case 5: 625 { 626 *red=QuantumRange*(min+c); 627 *green=QuantumRange*min; 628 *blue=QuantumRange*(min+x); 629 break; 630 } 631 default: 632 { 633 *red=0.0; 634 *green=0.0; 635 *blue=0.0; 636 } 637 } 638} 639 640/* 641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 642% % 643% % 644% % 645% C o n v e r t H W B T o R G B % 646% % 647% % 648% % 649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 650% 651% ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green, 652% blue) triple. 653% 654% The format of the ConvertHWBToRGBImage method is: 655% 656% void ConvertHWBToRGB(const double hue,const double whiteness, 657% const double blackness,double *red,double *green,double *blue) 658% 659% A description of each parameter follows: 660% 661% o hue, whiteness, blackness: A double value representing a 662% component of the HWB color space. 663% 664% o red, green, blue: A pointer to a pixel component of type Quantum. 665% 666*/ 667MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness, 668 const double blackness,double *red,double *green,double *blue) 669{ 670 double 671 b, 672 f, 673 g, 674 n, 675 r, 676 v; 677 678 register ssize_t 679 i; 680 681 /* 682 Convert HWB to RGB colorspace. 683 */ 684 assert(red != (double *) NULL); 685 assert(green != (double *) NULL); 686 assert(blue != (double *) NULL); 687 v=1.0-blackness; 688 if (fabs(hue-(-1.0)) < MagickEpsilon) 689 { 690 *red=QuantumRange*v; 691 *green=QuantumRange*v; 692 *blue=QuantumRange*v; 693 return; 694 } 695 i=(ssize_t) floor(6.0*hue); 696 f=6.0*hue-i; 697 if ((i & 0x01) != 0) 698 f=1.0-f; 699 n=whiteness+f*(v-whiteness); /* linear interpolation */ 700 switch (i) 701 { 702 default: 703 case 6: 704 case 0: r=v; g=n; b=whiteness; break; 705 case 1: r=n; g=v; b=whiteness; break; 706 case 2: r=whiteness; g=v; b=n; break; 707 case 3: r=whiteness; g=n; b=v; break; 708 case 4: r=n; g=whiteness; b=v; break; 709 case 5: r=v; g=whiteness; b=n; break; 710 } 711 *red=QuantumRange*r; 712 *green=QuantumRange*g; 713 *blue=QuantumRange*b; 714} 715 716/* 717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 718% % 719% % 720% % 721% C o n v e r t L C H a b T o R G B % 722% % 723% % 724% % 725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 726% 727% ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green, 728% blue) triple. 729% 730% The format of the ConvertLCHabToRGBImage method is: 731% 732% void ConvertLCHabToRGB(const double luma,const double chroma, 733% const double hue,double *red,double *green,double *blue) 734% 735% A description of each parameter follows: 736% 737% o luma, chroma, hue: A double value representing a component of the 738% LCHab color space. 739% 740% o red, green, blue: A pointer to a pixel component of type Quantum. 741% 742*/ 743 744static inline void ConvertLCHabToXYZ(const double luma,const double chroma, 745 const double hue,double *X,double *Y,double *Z) 746{ 747 ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma* 748 sin(hue*MagickPI/180.0),X,Y,Z); 749} 750 751MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma, 752 const double hue,double *red,double *green,double *blue) 753{ 754 double 755 X, 756 Y, 757 Z; 758 759 /* 760 Convert LCHab to RGB colorspace. 761 */ 762 assert(red != (double *) NULL); 763 assert(green != (double *) NULL); 764 assert(blue != (double *) NULL); 765 ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z); 766 ConvertXYZToRGB(X,Y,Z,red,green,blue); 767} 768 769/* 770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 771% % 772% % 773% % 774% C o n v e r t L C H u v T o R G B % 775% % 776% % 777% % 778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 779% 780% ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green, 781% blue) triple. 782% 783% The format of the ConvertLCHuvToRGBImage method is: 784% 785% void ConvertLCHuvToRGB(const double luma,const double chroma, 786% const double hue,double *red,double *green,double *blue) 787% 788% A description of each parameter follows: 789% 790% o luma, chroma, hue: A double value representing a component of the 791% LCHuv color space. 792% 793% o red, green, blue: A pointer to a pixel component of type Quantum. 794% 795*/ 796 797static inline void ConvertLCHuvToXYZ(const double luma,const double chroma, 798 const double hue,double *X,double *Y,double *Z) 799{ 800 ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma* 801 sin(hue*MagickPI/180.0),X,Y,Z); 802} 803 804MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma, 805 const double hue,double *red,double *green,double *blue) 806{ 807 double 808 X, 809 Y, 810 Z; 811 812 /* 813 Convert LCHuv to RGB colorspace. 814 */ 815 assert(red != (double *) NULL); 816 assert(green != (double *) NULL); 817 assert(blue != (double *) NULL); 818 ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z); 819 ConvertXYZToRGB(X,Y,Z,red,green,blue); 820} 821 822/* 823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 824% % 825% % 826% % 827% C o n v e r t R G B T o H C L % 828% % 829% % 830% % 831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 832% 833% ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma, 834% luma) triple. 835% 836% The format of the ConvertRGBToHCL method is: 837% 838% void ConvertRGBToHCL(const double red,const double green, 839% const double blue,double *hue,double *chroma,double *luma) 840% 841% A description of each parameter follows: 842% 843% o red, green, blue: A Quantum value representing the red, green, and 844% blue component of a pixel. 845% 846% o hue, chroma, luma: A pointer to a double value representing a 847% component of the HCL color space. 848% 849*/ 850MagickPrivate void ConvertRGBToHCL(const double red,const double green, 851 const double blue,double *hue,double *chroma,double *luma) 852{ 853 double 854 c, 855 h, 856 max; 857 858 /* 859 Convert RGB to HCL colorspace. 860 */ 861 assert(hue != (double *) NULL); 862 assert(chroma != (double *) NULL); 863 assert(luma != (double *) NULL); 864 max=MagickMax(red,MagickMax(green,blue)); 865 c=max-(double) MagickMin(red,MagickMin(green,blue)); 866 h=0.0; 867 if (fabs(c) < MagickEpsilon) 868 h=0.0; 869 else 870 if (fabs(red-max) < MagickEpsilon) 871 h=fmod((green-blue)/c+6.0,6.0); 872 else 873 if (fabs(green-max) < MagickEpsilon) 874 h=((blue-red)/c)+2.0; 875 else 876 if (fabs(blue-max) < MagickEpsilon) 877 h=((red-green)/c)+4.0; 878 *hue=(h/6.0); 879 *chroma=QuantumScale*c; 880 *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue); 881} 882 883/* 884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 885% % 886% % 887% % 888% C o n v e r t R G B T o H C L p % 889% % 890% % 891% % 892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 893% 894% ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma, 895% luma) triple. 896% 897% The format of the ConvertRGBToHCLp method is: 898% 899% void ConvertRGBToHCLp(const double red,const double green, 900% const double blue,double *hue,double *chroma,double *luma) 901% 902% A description of each parameter follows: 903% 904% o red, green, blue: A Quantum value representing the red, green, and 905% blue component of a pixel. 906% 907% o hue, chroma, luma: A pointer to a double value representing a 908% component of the HCL color space. 909% 910*/ 911MagickPrivate void ConvertRGBToHCLp(const double red,const double green, 912 const double blue,double *hue,double *chroma,double *luma) 913{ 914 double 915 c, 916 h, 917 max; 918 919 /* 920 Convert RGB to HCL colorspace. 921 */ 922 assert(hue != (double *) NULL); 923 assert(chroma != (double *) NULL); 924 assert(luma != (double *) NULL); 925 max=MagickMax(red,MagickMax(green,blue)); 926 c=max-MagickMin(red,MagickMin(green,blue)); 927 h=0.0; 928 if (fabs(c) < MagickEpsilon) 929 h=0.0; 930 else 931 if (fabs(red-max) < MagickEpsilon) 932 h=fmod((green-blue)/c+6.0,6.0); 933 else 934 if (fabs(green-max) < MagickEpsilon) 935 h=((blue-red)/c)+2.0; 936 else 937 if (fabs(blue-max) < MagickEpsilon) 938 h=((red-green)/c)+4.0; 939 *hue=(h/6.0); 940 *chroma=QuantumScale*c; 941 *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue); 942} 943 944/* 945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 946% % 947% % 948% % 949% C o n v e r t R G B T o H S B % 950% % 951% % 952% % 953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 954% 955% ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation, 956% brightness) triple. 957% 958% The format of the ConvertRGBToHSB method is: 959% 960% void ConvertRGBToHSB(const double red,const double green, 961% const double blue,double *hue,double *saturation,double *brightness) 962% 963% A description of each parameter follows: 964% 965% o red, green, blue: A Quantum value representing the red, green, and 966% blue component of a pixel.. 967% 968% o hue, saturation, brightness: A pointer to a double value representing a 969% component of the HSB color space. 970% 971*/ 972MagickPrivate void ConvertRGBToHSB(const double red,const double green, 973 const double blue,double *hue,double *saturation,double *brightness) 974{ 975 double 976 delta, 977 max, 978 min; 979 980 /* 981 Convert RGB to HSB colorspace. 982 */ 983 assert(hue != (double *) NULL); 984 assert(saturation != (double *) NULL); 985 assert(brightness != (double *) NULL); 986 *hue=0.0; 987 *saturation=0.0; 988 *brightness=0.0; 989 min=red < green ? red : green; 990 if (blue < min) 991 min=blue; 992 max=red > green ? red : green; 993 if (blue > max) 994 max=blue; 995 if (fabs(max) < MagickEpsilon) 996 return; 997 delta=max-min; 998 *saturation=delta/max; 999 *brightness=QuantumScale*max; 1000 if (fabs(delta) < MagickEpsilon) 1001 return; 1002 if (fabs(red-max) < MagickEpsilon) 1003 *hue=(green-blue)/delta; 1004 else 1005 if (fabs(green-max) < MagickEpsilon) 1006 *hue=2.0+(blue-red)/delta; 1007 else 1008 *hue=4.0+(red-green)/delta; 1009 *hue/=6.0; 1010 if (*hue < 0.0) 1011 *hue+=1.0; 1012} 1013 1014/* 1015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1016% % 1017% % 1018% % 1019% C o n v e r t R G B T o H S I % 1020% % 1021% % 1022% % 1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1024% 1025% ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation, 1026% intensity) triple. 1027% 1028% The format of the ConvertRGBToHSI method is: 1029% 1030% void ConvertRGBToHSI(const double red,const double green, 1031% const double blue,double *hue,double *saturation,double *intensity) 1032% 1033% A description of each parameter follows: 1034% 1035% o red, green, blue: A Quantum value representing the red, green, and 1036% blue component of a pixel.. 1037% 1038% o hue, saturation, intensity: A pointer to a double value representing a 1039% component of the HSI color space. 1040% 1041*/ 1042MagickPrivate void ConvertRGBToHSI(const double red,const double green, 1043 const double blue,double *hue,double *saturation,double *intensity) 1044{ 1045 double 1046 alpha, 1047 beta; 1048 1049 /* 1050 Convert RGB to HSI colorspace. 1051 */ 1052 assert(hue != (double *) NULL); 1053 assert(saturation != (double *) NULL); 1054 assert(intensity != (double *) NULL); 1055 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0; 1056 if (*intensity <= 0.0) 1057 { 1058 *hue=0.0; 1059 *saturation=0.0; 1060 return; 1061 } 1062 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green, 1063 QuantumScale*blue))/(*intensity); 1064 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue); 1065 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue); 1066 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0; 1067 if (*hue < 0.0) 1068 *hue+=1.0; 1069} 1070 1071/* 1072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1073% % 1074% % 1075% % 1076% C o n v e r t R G B T o H S L % 1077% % 1078% % 1079% % 1080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1081% 1082% ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation, 1083% lightness) triple. 1084% 1085% The format of the ConvertRGBToHSL method is: 1086% 1087% void ConvertRGBToHSL(const double red,const double green, 1088% const double blue,double *hue,double *saturation,double *lightness) 1089% 1090% A description of each parameter follows: 1091% 1092% o red, green, blue: A Quantum value representing the red, green, and 1093% blue component of a pixel.. 1094% 1095% o hue, saturation, lightness: A pointer to a double value representing a 1096% component of the HSL color space. 1097% 1098*/ 1099MagickExport void ConvertRGBToHSL(const double red,const double green, 1100 const double blue,double *hue,double *saturation,double *lightness) 1101{ 1102 double 1103 c, 1104 max, 1105 min; 1106 1107 /* 1108 Convert RGB to HSL colorspace. 1109 */ 1110 assert(hue != (double *) NULL); 1111 assert(saturation != (double *) NULL); 1112 assert(lightness != (double *) NULL); 1113 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green, 1114 QuantumScale*blue)); 1115 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green, 1116 QuantumScale*blue)); 1117 c=max-min; 1118 *lightness=(max+min)/2.0; 1119 if (c <= 0.0) 1120 { 1121 *hue=0.0; 1122 *saturation=0.0; 1123 return; 1124 } 1125 if (fabs(max-QuantumScale*red) < MagickEpsilon) 1126 { 1127 *hue=(QuantumScale*green-QuantumScale*blue)/c; 1128 if ((QuantumScale*green) < (QuantumScale*blue)) 1129 *hue+=6.0; 1130 } 1131 else 1132 if (fabs(max-QuantumScale*green) < MagickEpsilon) 1133 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c; 1134 else 1135 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c; 1136 *hue*=60.0/360.0; 1137 if (*lightness <= 0.5) 1138 *saturation=c/(2.0*(*lightness)); 1139 else 1140 *saturation=c/(2.0-2.0*(*lightness)); 1141} 1142 1143/* 1144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1145% % 1146% % 1147% % 1148% C o n v e r t R G B T o H S V % 1149% % 1150% % 1151% % 1152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1153% 1154% ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation, 1155% value) triple. 1156% 1157% The format of the ConvertRGBToHSV method is: 1158% 1159% void ConvertRGBToHSV(const double red,const double green, 1160% const double blue,double *hue,double *saturation,double *value) 1161% 1162% A description of each parameter follows: 1163% 1164% o red, green, blue: A Quantum value representing the red, green, and 1165% blue component of a pixel.. 1166% 1167% o hue, saturation, value: A pointer to a double value representing a 1168% component of the HSV color space. 1169% 1170*/ 1171MagickPrivate void ConvertRGBToHSV(const double red,const double green, 1172 const double blue,double *hue,double *saturation,double *value) 1173{ 1174 double 1175 c, 1176 max, 1177 min; 1178 1179 /* 1180 Convert RGB to HSV colorspace. 1181 */ 1182 assert(hue != (double *) NULL); 1183 assert(saturation != (double *) NULL); 1184 assert(value != (double *) NULL); 1185 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green, 1186 QuantumScale*blue)); 1187 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green, 1188 QuantumScale*blue)); 1189 c=max-min; 1190 *value=max; 1191 if (c <= 0.0) 1192 { 1193 *hue=0.0; 1194 *saturation=0.0; 1195 return; 1196 } 1197 if (fabs(max-QuantumScale*red) < MagickEpsilon) 1198 { 1199 *hue=(QuantumScale*green-QuantumScale*blue)/c; 1200 if ((QuantumScale*green) < (QuantumScale*blue)) 1201 *hue+=6.0; 1202 } 1203 else 1204 if (fabs(max-QuantumScale*green) < MagickEpsilon) 1205 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c; 1206 else 1207 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c; 1208 *hue*=60.0/360.0; 1209 *saturation=c/max; 1210} 1211 1212/* 1213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1214% % 1215% % 1216% % 1217% C o n v e r t R G B T o H W B % 1218% % 1219% % 1220% % 1221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1222% 1223% ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness, 1224% blackness) triple. 1225% 1226% The format of the ConvertRGBToHWB method is: 1227% 1228% void ConvertRGBToHWB(const double red,const double green, 1229% const double blue,double *hue,double *whiteness,double *blackness) 1230% 1231% A description of each parameter follows: 1232% 1233% o red, green, blue: A Quantum value representing the red, green, and 1234% blue component of a pixel. 1235% 1236% o hue, whiteness, blackness: A pointer to a double value representing a 1237% component of the HWB color space. 1238% 1239*/ 1240MagickPrivate void ConvertRGBToHWB(const double red,const double green, 1241 const double blue,double *hue,double *whiteness,double *blackness) 1242{ 1243 double 1244 f, 1245 p, 1246 v, 1247 w; 1248 1249 /* 1250 Convert RGB to HWB colorspace. 1251 */ 1252 assert(hue != (double *) NULL); 1253 assert(whiteness != (double *) NULL); 1254 assert(blackness != (double *) NULL); 1255 w=MagickMin(red,MagickMin(green,blue)); 1256 v=MagickMax(red,MagickMax(green,blue)); 1257 *blackness=1.0-QuantumScale*v; 1258 *whiteness=QuantumScale*w; 1259 if (fabs(v-w) < MagickEpsilon) 1260 { 1261 *hue=(-1.0); 1262 return; 1263 } 1264 f=(fabs(red-w) < MagickEpsilon) ? green-blue : 1265 ((fabs(green-w) < MagickEpsilon) ? blue-red : red-green); 1266 p=(fabs(red-w) < MagickEpsilon) ? 3.0 : 1267 ((fabs(green-w) < MagickEpsilon) ? 5.0 : 1.0); 1268 *hue=(p-f/(v-1.0*w))/6.0; 1269} 1270 1271/* 1272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1273% % 1274% % 1275% % 1276% C o n v e r t R G B T o L C H a b % 1277% % 1278% % 1279% % 1280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1281% 1282% ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma, 1283% hue) triple. 1284% 1285% The format of the ConvertRGBToLCHab method is: 1286% 1287% void ConvertRGBToLCHab(const double red,const double green, 1288% const double blue,double *luma,double *chroma,double *hue) 1289% 1290% A description of each parameter follows: 1291% 1292% o red, green, blue: A Quantum value representing the red, green, and 1293% blue component of a pixel. 1294% 1295% o luma, chroma, hue: A pointer to a double value representing a 1296% component of the LCH color space. 1297% 1298*/ 1299 1300static inline void ConvertXYZToLCHab(const double X,const double Y, 1301 const double Z,double *luma,double *chroma,double *hue) 1302{ 1303 double 1304 a, 1305 b; 1306 1307 ConvertXYZToLab(X,Y,Z,luma,&a,&b); 1308 *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5; 1309 *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0; 1310 if (*hue < 0.0) 1311 *hue+=1.0; 1312} 1313 1314MagickPrivate void ConvertRGBToLCHab(const double red,const double green, 1315 const double blue,double *luma,double *chroma,double *hue) 1316{ 1317 double 1318 X, 1319 Y, 1320 Z; 1321 1322 /* 1323 Convert RGB to LCHab colorspace. 1324 */ 1325 assert(luma != (double *) NULL); 1326 assert(chroma != (double *) NULL); 1327 assert(hue != (double *) NULL); 1328 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z); 1329 ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue); 1330} 1331 1332/* 1333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1334% % 1335% % 1336% % 1337% C o n v e r t R G B T o L C H u v % 1338% % 1339% % 1340% % 1341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1342% 1343% ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma, 1344% hue) triple. 1345% 1346% The format of the ConvertRGBToLCHuv method is: 1347% 1348% void ConvertRGBToLCHuv(const double red,const double green, 1349% const double blue,double *luma,double *chroma,double *hue) 1350% 1351% A description of each parameter follows: 1352% 1353% o red, green, blue: A Quantum value representing the red, green, and 1354% blue component of a pixel. 1355% 1356% o luma, chroma, hue: A pointer to a double value representing a 1357% component of the LCHuv color space. 1358% 1359*/ 1360 1361static inline void ConvertXYZToLCHuv(const double X,const double Y, 1362 const double Z,double *luma,double *chroma,double *hue) 1363{ 1364 double 1365 u, 1366 v; 1367 1368 ConvertXYZToLuv(X,Y,Z,luma,&u,&v); 1369 *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5; 1370 *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0; 1371 if (*hue < 0.0) 1372 *hue+=1.0; 1373} 1374 1375MagickPrivate void ConvertRGBToLCHuv(const double red,const double green, 1376 const double blue,double *luma,double *chroma,double *hue) 1377{ 1378 double 1379 X, 1380 Y, 1381 Z; 1382 1383 /* 1384 Convert RGB to LCHuv colorspace. 1385 */ 1386 assert(luma != (double *) NULL); 1387 assert(chroma != (double *) NULL); 1388 assert(hue != (double *) NULL); 1389 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z); 1390 ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue); 1391} 1392 1393/* 1394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1395% % 1396% % 1397% % 1398% E x p a n d A f f i n e % 1399% % 1400% % 1401% % 1402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1403% 1404% ExpandAffine() computes the affine's expansion factor, i.e. the square root 1405% of the factor by which the affine transform affects area. In an affine 1406% transform composed of scaling, rotation, shearing, and translation, returns 1407% the amount of scaling. 1408% 1409% The format of the ExpandAffine method is: 1410% 1411% double ExpandAffine(const AffineMatrix *affine) 1412% 1413% A description of each parameter follows: 1414% 1415% o expansion: ExpandAffine returns the affine's expansion factor. 1416% 1417% o affine: A pointer the affine transform of type AffineMatrix. 1418% 1419*/ 1420MagickExport double ExpandAffine(const AffineMatrix *affine) 1421{ 1422 assert(affine != (const AffineMatrix *) NULL); 1423 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry))); 1424} 1425 1426/* 1427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1428% % 1429% % 1430% % 1431% 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 % 1432% % 1433% % 1434% % 1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1436% 1437% GenerateDifferentialNoise() generates differentual noise. 1438% 1439% The format of the GenerateDifferentialNoise method is: 1440% 1441% double GenerateDifferentialNoise(RandomInfo *random_info, 1442% const Quantum pixel,const NoiseType noise_type,const double attenuate) 1443% 1444% A description of each parameter follows: 1445% 1446% o random_info: the random info. 1447% 1448% o pixel: noise is relative to this pixel value. 1449% 1450% o noise_type: the type of noise. 1451% 1452% o attenuate: attenuate the noise. 1453% 1454*/ 1455MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info, 1456 const Quantum pixel,const NoiseType noise_type,const double attenuate) 1457{ 1458#define SigmaUniform (attenuate*0.015625) 1459#define SigmaGaussian (attenuate*0.015625) 1460#define SigmaImpulse (attenuate*0.1) 1461#define SigmaLaplacian (attenuate*0.0390625) 1462#define SigmaMultiplicativeGaussian (attenuate*0.5) 1463#define SigmaPoisson (attenuate*12.5) 1464#define SigmaRandom (attenuate) 1465#define TauGaussian (attenuate*0.078125) 1466 1467 double 1468 alpha, 1469 beta, 1470 noise, 1471 sigma; 1472 1473 alpha=GetPseudoRandomValue(random_info); 1474 switch (noise_type) 1475 { 1476 case UniformNoise: 1477 default: 1478 { 1479 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5)); 1480 break; 1481 } 1482 case GaussianNoise: 1483 { 1484 double 1485 gamma, 1486 tau; 1487 1488 if (fabs(alpha) < MagickEpsilon) 1489 alpha=1.0; 1490 beta=GetPseudoRandomValue(random_info); 1491 gamma=sqrt(-2.0*log(alpha)); 1492 sigma=gamma*cos((double) (2.0*MagickPI*beta)); 1493 tau=gamma*sin((double) (2.0*MagickPI*beta)); 1494 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+ 1495 QuantumRange*TauGaussian*tau); 1496 break; 1497 } 1498 case ImpulseNoise: 1499 { 1500 if (alpha < (SigmaImpulse/2.0)) 1501 noise=0.0; 1502 else 1503 if (alpha >= (1.0-(SigmaImpulse/2.0))) 1504 noise=(double) QuantumRange; 1505 else 1506 noise=(double) pixel; 1507 break; 1508 } 1509 case LaplacianNoise: 1510 { 1511 if (alpha <= 0.5) 1512 { 1513 if (alpha <= MagickEpsilon) 1514 noise=(double) (pixel-QuantumRange); 1515 else 1516 noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+ 1517 0.5); 1518 break; 1519 } 1520 beta=1.0-alpha; 1521 if (beta <= (0.5*MagickEpsilon)) 1522 noise=(double) (pixel+QuantumRange); 1523 else 1524 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5); 1525 break; 1526 } 1527 case MultiplicativeGaussianNoise: 1528 { 1529 sigma=1.0; 1530 if (alpha > MagickEpsilon) 1531 sigma=sqrt(-2.0*log(alpha)); 1532 beta=GetPseudoRandomValue(random_info); 1533 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma* 1534 cos((double) (2.0*MagickPI*beta))/2.0); 1535 break; 1536 } 1537 case PoissonNoise: 1538 { 1539 double 1540 poisson; 1541 1542 register ssize_t 1543 i; 1544 1545 poisson=exp(-SigmaPoisson*QuantumScale*pixel); 1546 for (i=0; alpha > poisson; i++) 1547 { 1548 beta=GetPseudoRandomValue(random_info); 1549 alpha*=beta; 1550 } 1551 noise=(double) (QuantumRange*i/SigmaPoisson); 1552 break; 1553 } 1554 case RandomNoise: 1555 { 1556 noise=(double) (QuantumRange*SigmaRandom*alpha); 1557 break; 1558 } 1559 } 1560 return(noise); 1561} 1562 1563/* 1564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1565% % 1566% % 1567% % 1568% G e t O p t i m a l K e r n e l W i d t h % 1569% % 1570% % 1571% % 1572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1573% 1574% GetOptimalKernelWidth() computes the optimal kernel radius for a convolution 1575% filter. Start with the minimum value of 3 pixels and walk out until we drop 1576% below the threshold of one pixel numerical accuracy. 1577% 1578% The format of the GetOptimalKernelWidth method is: 1579% 1580% size_t GetOptimalKernelWidth(const double radius, 1581% const double sigma) 1582% 1583% A description of each parameter follows: 1584% 1585% o width: GetOptimalKernelWidth returns the optimal width of a 1586% convolution kernel. 1587% 1588% o radius: the radius of the Gaussian, in pixels, not counting the center 1589% pixel. 1590% 1591% o sigma: the standard deviation of the Gaussian, in pixels. 1592% 1593*/ 1594MagickPrivate size_t GetOptimalKernelWidth1D(const double radius, 1595 const double sigma) 1596{ 1597 double 1598 alpha, 1599 beta, 1600 gamma, 1601 normalize, 1602 value; 1603 1604 register ssize_t 1605 i; 1606 1607 size_t 1608 width; 1609 1610 ssize_t 1611 j; 1612 1613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1614 if (radius > MagickEpsilon) 1615 return((size_t) (2.0*ceil(radius)+1.0)); 1616 gamma=fabs(sigma); 1617 if (gamma <= MagickEpsilon) 1618 return(3UL); 1619 alpha=PerceptibleReciprocal(2.0*gamma*gamma); 1620 beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma); 1621 for (width=5; ; ) 1622 { 1623 normalize=0.0; 1624 j=(ssize_t) (width-1)/2; 1625 for (i=(-j); i <= j; i++) 1626 normalize+=exp(-((double) (i*i))*alpha)*beta; 1627 value=exp(-((double) (j*j))*alpha)*beta/normalize; 1628 if ((value < QuantumScale) || (value < MagickEpsilon)) 1629 break; 1630 width+=2; 1631 } 1632 return((size_t) (width-2)); 1633} 1634 1635MagickPrivate size_t GetOptimalKernelWidth2D(const double radius, 1636 const double sigma) 1637{ 1638 double 1639 alpha, 1640 beta, 1641 gamma, 1642 normalize, 1643 value; 1644 1645 size_t 1646 width; 1647 1648 ssize_t 1649 j, 1650 u, 1651 v; 1652 1653 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1654 if (radius > MagickEpsilon) 1655 return((size_t) (2.0*ceil(radius)+1.0)); 1656 gamma=fabs(sigma); 1657 if (gamma <= MagickEpsilon) 1658 return(3UL); 1659 alpha=PerceptibleReciprocal(2.0*gamma*gamma); 1660 beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma); 1661 for (width=5; ; ) 1662 { 1663 normalize=0.0; 1664 j=(ssize_t) (width-1)/2; 1665 for (v=(-j); v <= j; v++) 1666 for (u=(-j); u <= j; u++) 1667 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta; 1668 value=exp(-((double) (j*j))*alpha)*beta/normalize; 1669 if ((value < QuantumScale) || (value < MagickEpsilon)) 1670 break; 1671 width+=2; 1672 } 1673 return((size_t) (width-2)); 1674} 1675 1676MagickPrivate size_t GetOptimalKernelWidth(const double radius, 1677 const double sigma) 1678{ 1679 return(GetOptimalKernelWidth1D(radius,sigma)); 1680} 1681