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 */
ConvertHCLToRGB(const double hue,const double chroma,const double luma,double * red,double * green,double * blue)88 MagickPrivate 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 */
ConvertHCLpToRGB(const double hue,const double chroma,const double luma,double * red,double * green,double * blue)181 MagickPrivate 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 */
ConvertHSBToRGB(const double hue,const double saturation,const double brightness,double * red,double * green,double * blue)286 MagickPrivate 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 */
ConvertHSIToRGB(const double hue,const double saturation,const double intensity,double * red,double * green,double * blue)389 MagickPrivate 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 */
ConvertHSLToRGB(const double hue,const double saturation,const double lightness,double * red,double * green,double * blue)462 MagickExport 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 */
ConvertHSVToRGB(const double hue,const double saturation,const double value,double * red,double * green,double * blue)566 MagickPrivate 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 */
ConvertHWBToRGB(const double hue,const double whiteness,const double blackness,double * red,double * green,double * blue)667 MagickPrivate 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
ConvertLCHabToXYZ(const double luma,const double chroma,const double hue,double * X,double * Y,double * Z)744 static 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
ConvertLCHabToRGB(const double luma,const double chroma,const double hue,double * red,double * green,double * blue)751 MagickPrivate 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
ConvertLCHuvToXYZ(const double luma,const double chroma,const double hue,double * X,double * Y,double * Z)797 static 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
ConvertLCHuvToRGB(const double luma,const double chroma,const double hue,double * red,double * green,double * blue)804 MagickPrivate 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 */
ConvertRGBToHCL(const double red,const double green,const double blue,double * hue,double * chroma,double * luma)850 MagickPrivate 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 */
ConvertRGBToHCLp(const double red,const double green,const double blue,double * hue,double * chroma,double * luma)911 MagickPrivate 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 */
ConvertRGBToHSB(const double red,const double green,const double blue,double * hue,double * saturation,double * brightness)972 MagickPrivate 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 */
ConvertRGBToHSI(const double red,const double green,const double blue,double * hue,double * saturation,double * intensity)1042 MagickPrivate 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 */
ConvertRGBToHSL(const double red,const double green,const double blue,double * hue,double * saturation,double * lightness)1099 MagickExport 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 */
ConvertRGBToHSV(const double red,const double green,const double blue,double * hue,double * saturation,double * value)1171 MagickPrivate 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 */
ConvertRGBToHWB(const double red,const double green,const double blue,double * hue,double * whiteness,double * blackness)1240 MagickPrivate 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
ConvertXYZToLCHab(const double X,const double Y,const double Z,double * luma,double * chroma,double * hue)1300 static 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
ConvertRGBToLCHab(const double red,const double green,const double blue,double * luma,double * chroma,double * hue)1314 MagickPrivate 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
ConvertXYZToLCHuv(const double X,const double Y,const double Z,double * luma,double * chroma,double * hue)1361 static 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
ConvertRGBToLCHuv(const double red,const double green,const double blue,double * luma,double * chroma,double * hue)1375 MagickPrivate 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 */
ExpandAffine(const AffineMatrix * affine)1420 MagickExport 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 */
GenerateDifferentialNoise(RandomInfo * random_info,const Quantum pixel,const NoiseType noise_type,const double attenuate)1455 MagickPrivate 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 */
GetOptimalKernelWidth1D(const double radius,const double sigma)1594 MagickPrivate 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
GetOptimalKernelWidth2D(const double radius,const double sigma)1635 MagickPrivate 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
GetOptimalKernelWidth(const double radius,const double sigma)1676 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
1677 const double sigma)
1678 {
1679 return(GetOptimalKernelWidth1D(radius,sigma));
1680 }
1681