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