1 /*
2 % Copyright (C) 2004 - 2018 GraphicsMagick Group
3 %
4 % This program is covered by multiple licenses, which are described in
5 % Copyright.txt. You should have received a copy of Copyright.txt with this
6 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
7 %
8 % Interfaces to support quantum operators.
9 % Written by Bob Friesenhahn, March 2004.
10 %
11 */
12 
13 /*
14   Include declarations.
15 */
16 #include "magick/studio.h"
17 #include "magick/enum_strings.h"
18 #include "magick/gem.h"
19 #include "magick/pixel_iterator.h"
20 #include "magick/random.h"
21 #include "magick/utility.h"
22 #include "magick/operator.h"
23 
24 /*
25   Types.
26 */
27 typedef struct _QuantumImmutableContext
28 {
29   ChannelType channel;
30   Quantum quantum_value;
31   double double_value;
32 } QuantumImmutableContext;
33 
34 typedef struct _QuantumMutableContext
35 {
36   Quantum *channel_lut;
37 } QuantumMutableContext;
38 
39 typedef struct _ChannelOptions_t
40 {
41   DoublePixelPacket
42     values;
43 
44   MagickBool
45     red_enabled,
46     green_enabled,
47     blue_enabled,
48     opacity_enabled;
49 } ChannelOptions_t;
50 
51 /*
52 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 %                                                                             %
54 %                                                                             %
55 %                                                                             %
56 %   Q u a n t u m O p e r a t o r I m a g e                                   %
57 %                                                                             %
58 %                                                                             %
59 %                                                                             %
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61 %
62 %  QuantumOperatorImage() performs the requested arithmetic,
63 %  bitwise-logical, or value operation on the selected channels of
64 %  the entire image.  The AllChannels channel option operates on all
65 %  color channels whereas the GrayChannel channel option treats the
66 %  color channels as a grayscale intensity.
67 %
68 %  These operations are on the DirectClass pixels of the image and do not
69 %  update pixel indexes or colormap.
70 %
71 %  The format of the QuantumOperatorImage method is:
72 %
73 %      MagickPassFail QuantumOperatorImage(Image *image,
74 %        ChannelType channel, QuantumOperator operator,
75 %        double rvalue)
76 %
77 %  A description of each parameter follows:
78 %
79 %    o image: The image.
80 %
81 %    o channel: Channel to operate on (RedChannel, CyanChannel,
82 %        GreenChannel, MagentaChannel, BlueChannel, YellowChannel,
83 %        OpacityChannel, BlackChannel, MatteChannel, AllChannels,
84 %        GrayChannel).  The AllChannels type only updates color
85 %        channels.  The GrayChannel type treats the color channels
86 %        as if they represent an intensity.
87 %
88 %    o quantum_operator: Operator to use (AddQuantumOp, AndQuantumOp,
89 %        AssignQuantumOp, DepthQuantumOp, DivideQuantumOp, GammaQuantumOp,
90 %        LShiftQuantumOp, MultiplyQuantumOp,  NegateQuantumOp,
91 %        NoiseGaussianQuantumOp, NoiseImpulseQuantumOp,
92 %        NoiseLaplacianQuantumOp, NoiseMultiplicativeQuantumOp,
93 %        NoisePoissonQuantumOp, NoiseRandomQuantumOp, NoiseUniformQuantumOp,
94 %        OrQuantumOp, RShiftQuantumOp, SubtractQuantumOp,
95 %        ThresholdBlackQuantumOp, ThresholdQuantumOp, ThresholdWhiteQuantumOp,
96 %        ThresholdBlackNegateQuantumOp, ThresholdWhiteNegateQuantumOp,
97 %        XorQuantumOp).
98 %
99 %    o rvalue: Operator argument.
100 %
101 %    o exception: Updated with error description.
102 %
103 */
QuantumOperatorImage(Image * image,const ChannelType channel,const QuantumOperator quantum_operator,const double rvalue,ExceptionInfo * exception)104 MagickExport MagickPassFail QuantumOperatorImage(Image *image,
105   const ChannelType channel,const QuantumOperator quantum_operator,
106   const double rvalue,ExceptionInfo *exception)
107 {
108   return QuantumOperatorRegionImage(image,0,0,image->columns,image->rows,
109                                     channel,quantum_operator,rvalue,exception);
110 }
111 
112 /*
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %                                                                             %
115 %                                                                             %
116 %                                                                             %
117 +   Q u a n t u m O p e r a t o r I m a g e M u l t i v a l u e               %
118 %                                                                             %
119 %                                                                             %
120 %                                                                             %
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 %
123 %  QuantumOperatorImageMultivalue() is a semi-private implementation
124 %  fuction which accepts a comma delimited string of per-channel values
125 %  and applies a specified operator to the channels of the image.  The
126 %  main reason for this function to exist is to support
127 %  ChannelThresholdPixels(), BlackThresholdImage(), WhiteThresholdImage(),
128 %  or any other legacy style function which needs to be implemented.
129 %
130 %  The format of the QuantumOperatorImageMultivalue method is:
131 %
132 %      MagickPassFail QuantumOperatorImageMultivalue(
133 %                                 Image *image,
134 %                                 const QuantumOperator quantum_operator,
135 %                                 const char *values)
136 %
137 %  A description of each parameter follows:
138 %
139 %    o image: The image.
140 %
141 %    o values: define the rvalues, <red>{<green>,<blue>,<opacity>}{%}.
142 %
143 */
144 MagickExport MagickPassFail
QuantumOperatorImageMultivalue(Image * image,const QuantumOperator quantum_operator,const char * values)145 QuantumOperatorImageMultivalue(Image *image,
146                                const QuantumOperator quantum_operator,
147                                const char *values)
148 {
149   ChannelOptions_t
150     options;
151 
152   int
153     count;
154 
155   MagickPassFail
156     status;
157 
158   assert(image != (Image *) NULL);
159   assert(image->signature == MagickSignature);
160   if (values == (const char *) NULL)
161     return MagickFail;;
162 
163   options.red_enabled        = MagickFalse;
164   options.green_enabled      = MagickFalse;
165   options.blue_enabled       = MagickFalse;
166   options.opacity_enabled    = MagickFalse;
167 
168   options.values.red       = -1.0;
169   options.values.green     = -1.0;
170   options.values.blue      = -1.0;
171   options.values.opacity   = -1.0;
172   count=sscanf(values,"%lf%*[/,%%]%lf%*[/,%%]%lf%*[/,%%]%lf",
173                &options.values.red,
174                &options.values.green,
175                &options.values.blue,
176                &options.values.opacity);
177 
178   if ((count > 3) && (options.values.opacity >= 0.0))
179     options.opacity_enabled = MagickTrue;
180   if ((count > 2) && (options.values.blue >= 0.0))
181     options.blue_enabled = MagickTrue;
182   if ((count > 1) && (options.values.green >= 0.0))
183     options.green_enabled = MagickTrue;
184   if ((count > 0) && (options.values.red >= 0.0))
185     options.red_enabled = MagickTrue;
186 
187   if (strchr(values,'%') != (char *) NULL)
188     {
189       if (options.red_enabled)
190         options.values.red     *= MaxRGB/100.0;
191       if (options.green_enabled)
192         options.values.green   *= MaxRGB/100.0;
193       if (options.blue_enabled)
194         options.values.blue    *= MaxRGB/100.0;
195       if (options.opacity_enabled)
196         options.values.opacity *= MaxRGB/100.0;
197     }
198 
199   status=MagickPass;
200 
201   if ((IsRGBColorspace(image->colorspace)) &&
202       ((count == 1) ||
203        ((options.values.red == options.values.green) &&
204         (options.values.green == options.values.blue))))
205     {
206       /*
207         Apply operation to all channels in gray or RGB space.
208       */
209       if (IsGrayColorspace(image->colorspace))
210         status=QuantumOperatorImage(image,GrayChannel,quantum_operator,
211                                     options.values.red,&image->exception);
212       else
213         status=QuantumOperatorImage(image,AllChannels,quantum_operator,
214                                     options.values.red,&image->exception);
215     }
216   else
217     {
218       /*
219         Apply operator to individual RGB(A) channels.
220       */
221       if ((MagickPass == status) && (options.red_enabled))
222         {
223           status=QuantumOperatorImage(image,RedChannel,quantum_operator,
224                                       options.values.red,&image->exception);
225         }
226 
227       if ((MagickPass == status) && (options.green_enabled))
228         {
229           status=QuantumOperatorImage(image,GreenChannel,quantum_operator,
230                                       options.values.green,&image->exception);
231         }
232 
233       if ((MagickPass == status) && (options.blue_enabled))
234         {
235           status=QuantumOperatorImage(image,BlueChannel,quantum_operator,
236                                       options.values.blue,&image->exception);
237         }
238 
239       if ((MagickPass == status) && (options.opacity_enabled))
240         {
241           status=QuantumOperatorImage(image,OpacityChannel,quantum_operator,
242                                       options.values.opacity,&image->exception);
243         }
244     }
245 
246   if ((MagickPass == status) && (options.opacity_enabled))
247     {
248       status=QuantumOperatorImage(image,OpacityChannel,quantum_operator,
249                                   options.values.opacity,&image->exception);
250     }
251 
252   return status;
253 }
254 
255 /*
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 %                                                                             %
258 %                                                                             %
259 %                                                                             %
260 %   Q u a n t u m O p e r a t o r R e g i o n I m a g e                       %
261 %                                                                             %
262 %                                                                             %
263 %                                                                             %
264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265 %
266 %  QuantumOperatorRegionImage() performs the requested arithmetic,
267 %  bitwise-logical, or value operation on the selected channels of
268 %  the image over the specified region. The AllChannels channel option
269 %  operates on all color channels whereas the GrayChannel channel option
270 %  treats the color channels as a grayscale intensity.
271 %
272 %  These operations are on the DirectClass pixels of the image and do not
273 %  update pixel indexes or colormap.
274 %
275 %  The format of the QuantumOperatorRegionImage method is:
276 %
277 %      MagickPassFail QuantumOperatorRegionImage(Image *image,
278 %        long x, long y, unsigned long columns, unsigned long rows,
279 %        ChannelType channel, QuantumOperator quantum_operator,
280 %        double rvalue)
281 %
282 %  A description of each parameter follows:
283 %
284 %    o image: The image.
285 %
286 %    o channel: Channel to operate on (RedChannel, CyanChannel,
287 %        GreenChannel, MagentaChannel, BlueChannel, YellowChannel,
288 %        OpacityChannel, BlackChannel, MatteChannel, AllChannels,
289 %        GrayChannel).  The AllChannels type only updates color
290 %        channels.  The GrayChannel type treats the color channels
291 %        as if they represent an intensity.
292 %
293 %    o x: Ordinate of left row of region.
294 %
295 %    o y: Orginate of top column of region.
296 %
297 %    o columns: Width of region.
298 %
299 %    o rows: Height of region.
300 %
301 %    o quantum_operator: Operator to use (AddQuantumOp,AndQuantumOp,
302 %        AssignQuantumOp, DepthQuantumOp, DivideQuantumOp, GammaQuantumOp,
303 %        LShiftQuantumOp, MultiplyQuantumOp,  NegateQuantumOp,
304 %        NoiseGaussianQuantumOp, NoiseImpulseQuantumOp,
305 %        NoiseLaplacianQuantumOp, NoiseMultiplicativeQuantumOp,
306 %        NoisePoissonQuantumOp, NoiseRandomQuantumOp, NoiseUniformQuantumOp,
307 %        OrQuantumOp, RShiftQuantumOp, SubtractQuantumOp,
308 %        ThresholdBlackQuantumOp, ThresholdQuantumOp, ThresholdWhiteQuantumOp,
309 %        XorQuantumOp).
310 %
311 %    o rvalue: Operator argument.
312 %
313 %    o exception: Updated with error description.
314 %
315 */
316 
317 #define ApplyArithmeticOperator(lvalue,op,rvalue)       \
318 {                                                       \
319     double                                              \
320       result;                                           \
321                                                         \
322     result=(double) lvalue op (double) rvalue;          \
323     lvalue=RoundDoubleToQuantum(result);                \
324 }
325 
326 static MagickPassFail
QuantumAddCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)327 QuantumAddCB(void *mutable_data,
328              const void *immutable_data,
329              Image * restrict image,
330              PixelPacket * restrict pixels,
331              IndexPacket * restrict indexes,
332              const long npixels,
333              ExceptionInfo *exception)
334 {
335   const QuantumImmutableContext
336     *context=(const QuantumImmutableContext *) immutable_data;
337 
338   register long
339     i;
340 
341   ARG_NOT_USED(mutable_data);
342   ARG_NOT_USED(image);
343   ARG_NOT_USED(indexes);
344   ARG_NOT_USED(exception);
345 
346   switch (context->channel)
347     {
348     case RedChannel:
349     case CyanChannel:
350       for (i=0; i < npixels; i++)
351         ApplyArithmeticOperator(pixels[i].red,+,context->double_value);
352       break;
353     case GreenChannel:
354     case MagentaChannel:
355       for (i=0; i < npixels; i++)
356         ApplyArithmeticOperator(pixels[i].green,+,context->double_value);
357       break;
358     case BlueChannel:
359     case YellowChannel:
360       for (i=0; i < npixels; i++)
361         ApplyArithmeticOperator(pixels[i].blue,+,context->double_value);
362       break;
363     case BlackChannel:
364     case MatteChannel:
365     case OpacityChannel:
366       for (i=0; i < npixels; i++)
367         ApplyArithmeticOperator(pixels[i].opacity,+,context->double_value);
368       break;
369     case UndefinedChannel:
370     case AllChannels:
371       for (i=0; i < npixels; i++)
372         {
373           ApplyArithmeticOperator(pixels[i].red,+,context->double_value);
374           ApplyArithmeticOperator(pixels[i].green,+,context->double_value);
375           ApplyArithmeticOperator(pixels[i].blue,+,context->double_value);
376         }
377       break;
378     case GrayChannel:
379       for (i=0; i < npixels; i++)
380         {
381           Quantum
382             intensity;
383 
384           intensity = PixelIntensity(&pixels[i]);
385           ApplyArithmeticOperator(intensity,+,context->double_value);
386           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
387         }
388       break;
389     }
390 
391   return (MagickPass);
392 }
393 static MagickPassFail
QuantumAndCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)394 QuantumAndCB(void *mutable_data,
395              const void *immutable_data,
396              Image * restrict image,
397              PixelPacket * restrict pixels,
398              IndexPacket * restrict indexes,
399              const long npixels,
400              ExceptionInfo *exception)
401 {
402   const QuantumImmutableContext
403     *context=(const QuantumImmutableContext *) immutable_data;
404 
405   register long
406     i;
407 
408   ARG_NOT_USED(mutable_data);
409   ARG_NOT_USED(image);
410   ARG_NOT_USED(indexes);
411   ARG_NOT_USED(exception);
412 
413   switch (context->channel)
414     {
415     case RedChannel:
416     case CyanChannel:
417       for (i=0; i < npixels; i++)
418         pixels[i].red &= context->quantum_value;
419       break;
420     case GreenChannel:
421     case MagentaChannel:
422       for (i=0; i < npixels; i++)
423         pixels[i].green &= context->quantum_value;
424       break;
425     case BlueChannel:
426     case YellowChannel:
427       for (i=0; i < npixels; i++)
428         pixels[i].blue &= context->quantum_value;
429       break;
430     case BlackChannel:
431     case MatteChannel:
432     case OpacityChannel:
433       for (i=0; i < npixels; i++)
434         pixels[i].opacity &= context->quantum_value;
435       break;
436     case UndefinedChannel:
437     case AllChannels:
438       for (i=0; i < npixels; i++)
439         {
440           pixels[i].red &= context->quantum_value;
441           pixels[i].green &= context->quantum_value;
442           pixels[i].blue &= context->quantum_value;
443         }
444       break;
445     case GrayChannel:
446       for (i=0; i < npixels; i++)
447         {
448           Quantum
449             intensity;
450 
451           intensity = PixelIntensity(&pixels[i]);
452           intensity &= context->quantum_value;
453           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
454         }
455       break;
456     }
457 
458   return (MagickPass);
459 }
460 static MagickPassFail
QuantumAssignCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)461 QuantumAssignCB(void *mutable_data,
462                 const void *immutable_data,
463                 Image * restrict image,
464                 PixelPacket * restrict pixels,
465                 IndexPacket * restrict indexes,
466                 const long npixels,
467                 ExceptionInfo *exception)
468 {
469   const QuantumImmutableContext
470     *context=(const QuantumImmutableContext *) immutable_data;
471 
472   register long
473     i;
474 
475   ARG_NOT_USED(mutable_data);
476   ARG_NOT_USED(image);
477   ARG_NOT_USED(indexes);
478   ARG_NOT_USED(exception);
479 
480   switch (context->channel)
481     {
482     case RedChannel:
483     case CyanChannel:
484       for (i=0; i < npixels; i++)
485         pixels[i].red = context->quantum_value;
486       break;
487     case GreenChannel:
488     case MagentaChannel:
489       for (i=0; i < npixels; i++)
490         pixels[i].green = context->quantum_value;
491       break;
492     case BlueChannel:
493     case YellowChannel:
494       for (i=0; i < npixels; i++)
495         pixels[i].blue = context->quantum_value;
496       break;
497     case BlackChannel:
498     case MatteChannel:
499     case OpacityChannel:
500       for (i=0; i < npixels; i++)
501         pixels[i].opacity = context->quantum_value;
502       break;
503     case UndefinedChannel:
504     case AllChannels:
505       for (i=0; i < npixels; i++)
506         {
507           pixels[i].red = context->quantum_value;
508           pixels[i].green = context->quantum_value;
509           pixels[i].blue = context->quantum_value;
510         }
511       break;
512     case GrayChannel:
513       for (i=0; i < npixels; i++)
514         {
515           pixels[i].red = pixels[i].green = pixels[i].blue =
516             context->quantum_value;
517         }
518       break;
519     }
520 
521   return (MagickPass);
522 }
523 #define ApplyChannelDepth(parameter)                                    \
524   {                                                                     \
525     for (i=0; i < npixels; i++)                                         \
526       parameter=scale*((parameter)/scale);                              \
527   }
528 #if MaxRGB > MaxMap
529 #  define CrushChannelDepth(parameter) (scale*((parameter)/scale))
530 #else
531 #  define CrushChannelDepth(parameter) (mutable_context->channel_lut[ScaleQuantumToMap(parameter)])
532 #endif
533 static MagickPassFail
QuantumDepthCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)534 QuantumDepthCB(void *mutable_data,
535                const void *immutable_data,
536                Image * restrict image,
537                PixelPacket * restrict pixels,
538                IndexPacket * restrict indexes,
539                const long npixels,
540                ExceptionInfo *exception)
541 {
542   QuantumMutableContext
543     *mutable_context=(QuantumMutableContext *) mutable_data;
544 
545   const QuantumImmutableContext
546     *immutable_context=(const QuantumImmutableContext *) immutable_data;
547 
548   unsigned int
549     depth;
550 
551   register unsigned int
552     scale;
553 
554   register long
555     i;
556 
557   MagickPassFail
558     status=MagickPass;
559 
560   ARG_NOT_USED(mutable_data);
561   ARG_NOT_USED(exception);
562 
563   depth=immutable_context->quantum_value;
564   if (depth < 1)
565     depth=1;
566   else if (depth > QuantumDepth)
567     depth=QuantumDepth;
568 
569   if (depth < QuantumDepth)
570     {
571       scale=MaxRGB / (MaxRGB >> (QuantumDepth-depth));
572 
573       /*
574         Build LUT for Q8 and Q16 builds
575       */
576 #if MaxRGB <= MaxMap
577 #  if defined(HAVE_OPENMP)
578 #    pragma omp critical (GM_QuantumDepthCB)
579 #  endif
580       if (mutable_context->channel_lut == (Quantum *) NULL)
581         {
582           mutable_context->channel_lut=MagickAllocateArray(Quantum *, MaxMap+1,sizeof(Quantum));
583           if (mutable_context->channel_lut == (Quantum *) NULL)
584             status=MagickFail;
585 
586           if (mutable_context->channel_lut != (Quantum *) NULL)
587             {
588               for (i=0; i <= (long) MaxMap; i++)
589                 mutable_context->channel_lut[i] = scale*(i/scale);
590             }
591         }
592 #else
593       ARG_NOT_USED(*mutable_context);
594 #endif
595 
596       if (MagickFail == status)
597         return status;
598 
599       switch (immutable_context->channel)
600         {
601         case RedChannel:
602         case CyanChannel:
603           for (i=0; i < npixels; i++)
604             pixels[i].red=CrushChannelDepth(pixels[i].red);
605           break;
606         case GreenChannel:
607         case MagentaChannel:
608           for (i=0; i < npixels; i++)
609             pixels[i].green=CrushChannelDepth(pixels[i].green);
610           break;
611         case BlueChannel:
612         case YellowChannel:
613           for (i=0; i < npixels; i++)
614             pixels[i].blue=CrushChannelDepth(pixels[i].blue);
615           break;
616         case MatteChannel:
617         case OpacityChannel:
618           if (image->colorspace == CMYKColorspace)
619             for (i=0; i < npixels; i++)
620               indexes[i]=CrushChannelDepth(indexes[i]);
621           else
622             for (i=0; i < npixels; i++)
623               pixels[i].opacity=CrushChannelDepth(pixels[i].opacity);
624           break;
625         case BlackChannel:
626           for (i=0; i < npixels; i++)
627             pixels[i].opacity=CrushChannelDepth(pixels[i].opacity);
628           break;
629         case UndefinedChannel:
630         case AllChannels:
631           for (i=0; i < npixels; i++)
632             {
633               pixels[i].red=CrushChannelDepth(pixels[i].red);
634               pixels[i].green=CrushChannelDepth(pixels[i].green);
635               pixels[i].blue=CrushChannelDepth(pixels[i].blue);
636               if (image->colorspace == CMYKColorspace)
637                 pixels[i].opacity=CrushChannelDepth(pixels[i].opacity);
638             }
639           break;
640         case GrayChannel:
641           for (i=0; i < npixels; i++)
642             {
643               Quantum
644                 intensity;
645 
646               intensity = PixelIntensity(&pixels[i]);
647               intensity=CrushChannelDepth(intensity);
648               pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
649             }
650           break;
651         }
652     }
653 
654   return MagickPass;
655 }
656 static MagickPassFail
QuantumDivideCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)657 QuantumDivideCB(void *mutable_data,
658                 const void *immutable_data,
659                 Image * restrict image,
660                 PixelPacket * restrict pixels,
661                 IndexPacket * restrict indexes,
662                 const long npixels,
663                 ExceptionInfo *exception)
664 {
665   const QuantumImmutableContext
666     *context=(const QuantumImmutableContext *) immutable_data;
667 
668   register long
669     i;
670 
671   ARG_NOT_USED(mutable_data);
672   ARG_NOT_USED(image);
673   ARG_NOT_USED(indexes);
674   ARG_NOT_USED(exception);
675 
676   switch (context->channel)
677     {
678     case RedChannel:
679     case CyanChannel:
680       for (i=0; i < npixels; i++)
681         ApplyArithmeticOperator(pixels[i].red,/,context->double_value);
682       break;
683     case GreenChannel:
684     case MagentaChannel:
685       for (i=0; i < npixels; i++)
686         ApplyArithmeticOperator(pixels[i].green,/,context->double_value);
687       break;
688     case BlueChannel:
689     case YellowChannel:
690       for (i=0; i < npixels; i++)
691         ApplyArithmeticOperator(pixels[i].blue,/,context->double_value);
692       break;
693     case BlackChannel:
694     case MatteChannel:
695     case OpacityChannel:
696       for (i=0; i < npixels; i++)
697         ApplyArithmeticOperator(pixels[i].opacity,/,context->double_value);
698       break;
699     case UndefinedChannel:
700     case AllChannels:
701       for (i=0; i < npixels; i++)
702         {
703           ApplyArithmeticOperator(pixels[i].red,/,context->double_value);
704           ApplyArithmeticOperator(pixels[i].green,/,context->double_value);
705           ApplyArithmeticOperator(pixels[i].blue,/,context->double_value);
706         }
707       break;
708     case GrayChannel:
709       for (i=0; i < npixels; i++)
710         {
711           Quantum
712             intensity;
713 
714           intensity = PixelIntensity(&pixels[i]);
715           ApplyArithmeticOperator(intensity,/,context->double_value);
716           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
717         }
718       break;
719     }
720 
721   return (MagickPass);
722 }
723 #if MaxRGB > MaxMap
724 #  define GammaAdjustQuantum(quantum) (MaxRGBDouble*pow(quantum/MaxRGBDouble,1.0/immutable_context->double_value)+0.5)
725 #else
726 #  define GammaAdjustQuantum(quantum) (mutable_context->channel_lut[ScaleQuantumToMap(quantum)])
727 #endif
728 static MagickPassFail
QuantumGammaCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)729 QuantumGammaCB(void *mutable_data,
730                const void *immutable_data,
731                Image * restrict image,
732                PixelPacket * restrict pixels,
733                IndexPacket * restrict indexes,
734                const long npixels,
735                ExceptionInfo *exception)
736 {
737   QuantumMutableContext
738     *mutable_context=(QuantumMutableContext *) mutable_data;
739 
740   const QuantumImmutableContext
741     *immutable_context=(const QuantumImmutableContext *) immutable_data;
742 
743   register long
744     i;
745 
746   MagickPassFail
747     status=MagickPass;
748 
749   ARG_NOT_USED(image);
750   ARG_NOT_USED(indexes);
751   ARG_NOT_USED(exception);
752 
753   /*
754     Build LUT for Q8 and Q16 builds
755   */
756 #if MaxRGB <= MaxMap
757 #  if defined(HAVE_OPENMP)
758 #    pragma omp critical (GM_QuantumGammaCB)
759 #  endif
760   if (mutable_context->channel_lut == (Quantum *) NULL)
761     {
762       mutable_context->channel_lut=MagickAllocateArray(Quantum *, MaxMap+1,sizeof(Quantum));
763       if (mutable_context->channel_lut == (Quantum *) NULL)
764         status=MagickFail;
765 
766       if (mutable_context->channel_lut != (Quantum *) NULL)
767         {
768           for (i=0; i <= (long) MaxMap; i++)
769             mutable_context->channel_lut[i] =
770               ScaleMapToQuantum(MaxMap*pow((double) i/MaxMap,
771                                            1.0/immutable_context->double_value));
772         }
773     }
774 #else
775   ARG_NOT_USED(*mutable_context);
776 #endif
777   if (MagickFail == status)
778     return status;
779 
780   switch (immutable_context->channel)
781     {
782     case RedChannel:
783     case CyanChannel:
784       for (i=0; i < npixels; i++)
785         pixels[i].red=GammaAdjustQuantum(pixels[i].red);
786       break;
787     case GreenChannel:
788     case MagentaChannel:
789       for (i=0; i < npixels; i++)
790         pixels[i].green=GammaAdjustQuantum(pixels[i].green);
791       break;
792     case BlueChannel:
793     case YellowChannel:
794       for (i=0; i < npixels; i++)
795         pixels[i].blue=GammaAdjustQuantum(pixels[i].blue);
796       break;
797     case BlackChannel:
798     case MatteChannel:
799     case OpacityChannel:
800       for (i=0; i < npixels; i++)
801         pixels[i].opacity=GammaAdjustQuantum(pixels[i].opacity);
802       break;
803     case UndefinedChannel:
804     case AllChannels:
805       for (i=0; i < npixels; i++)
806         {
807           pixels[i].red=GammaAdjustQuantum(pixels[i].red);
808           pixels[i].green=GammaAdjustQuantum(pixels[i].green);
809           pixels[i].blue=GammaAdjustQuantum(pixels[i].blue);
810         }
811       break;
812     case GrayChannel:
813       for (i=0; i < npixels; i++)
814         {
815           Quantum
816             intensity;
817 
818           intensity = PixelIntensity(&pixels[i]);
819           intensity = GammaAdjustQuantum(intensity);
820           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
821         }
822       break;
823     }
824 
825   return status;
826 }
827 static MagickPassFail
QuantumNegateCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)828 QuantumNegateCB(void *mutable_data,
829                 const void *immutable_data,
830                 Image * restrict image,
831                 PixelPacket * restrict pixels,
832                 IndexPacket * restrict indexes,
833                 const long npixels,
834                 ExceptionInfo *exception)
835 {
836   const QuantumImmutableContext
837     *context=(const QuantumImmutableContext *) immutable_data;
838 
839   register long
840     i;
841 
842   ARG_NOT_USED(mutable_data);
843   ARG_NOT_USED(image);
844   ARG_NOT_USED(indexes);
845   ARG_NOT_USED(exception);
846 
847   switch (context->channel)
848     {
849     case RedChannel:
850     case CyanChannel:
851       for (i=0; i < npixels; i++)
852         pixels[i].red=MaxRGB-pixels[i].red;
853       break;
854     case GreenChannel:
855     case MagentaChannel:
856       for (i=0; i < npixels; i++)
857         pixels[i].green=MaxRGB-pixels[i].green;
858       break;
859     case BlueChannel:
860     case YellowChannel:
861       for (i=0; i < npixels; i++)
862         pixels[i].blue=MaxRGB-pixels[i].blue;
863       break;
864     case BlackChannel:
865     case MatteChannel:
866     case OpacityChannel:
867       for (i=0; i < npixels; i++)
868         pixels[i].opacity=MaxRGB-pixels[i].opacity;
869       break;
870     case UndefinedChannel:
871     case AllChannels:
872       for (i=0; i < npixels; i++)
873         {
874           pixels[i].red=MaxRGB-pixels[i].red;
875           pixels[i].green=MaxRGB-pixels[i].green;
876           pixels[i].blue=MaxRGB-pixels[i].blue;
877         }
878       break;
879     case GrayChannel:
880       for (i=0; i < npixels; i++)
881         {
882           Quantum
883             intensity;
884 
885           intensity = PixelIntensity(&pixels[i]);
886           intensity = MaxRGB-intensity;
887           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
888         }
889       break;
890     }
891 
892   return (MagickPass);
893 }
894 /* log(quantum*value+1)/log(value+1) */
895 #if MaxRGB > MaxMap
896 #  define LogAdjustQuantum(quantum) \
897   ((MaxRGBDouble*log((quantum/MaxRGBDouble)*immutable_context->double_value+1.0)/ \
898     log(immutable_context->double_value+1.0))+0.5)
899 #else
900 #  define LogAdjustQuantum(quantum) (mutable_context->channel_lut[ScaleQuantumToMap(quantum)])
901 #endif
902 static MagickPassFail
QuantumLogCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)903 QuantumLogCB(void *mutable_data,
904              const void *immutable_data,
905              Image * restrict image,
906              PixelPacket * restrict pixels,
907              IndexPacket * restrict indexes,
908              const long npixels,
909              ExceptionInfo *exception)
910 {
911   QuantumMutableContext
912     *mutable_context=(QuantumMutableContext *) mutable_data;
913 
914   const QuantumImmutableContext
915     *immutable_context=(const QuantumImmutableContext *) immutable_data;
916 
917   register long
918     i;
919 
920   MagickPassFail
921     status=MagickPass;
922 
923   ARG_NOT_USED(image);
924   ARG_NOT_USED(indexes);
925   ARG_NOT_USED(exception);
926 
927   /*
928     Build LUT for Q8 and Q16 builds
929   */
930 #if MaxRGB <= MaxMap
931 #  if defined(HAVE_OPENMP)
932 #    pragma omp critical (GM_QuantumLogCB)
933 #  endif
934   if (mutable_context->channel_lut == (Quantum *) NULL)
935     {
936       mutable_context->channel_lut=MagickAllocateArray(Quantum *, MaxMap+1,sizeof(Quantum));
937       if (mutable_context->channel_lut == (Quantum *) NULL)
938         status=MagickFail;
939 
940       if (mutable_context->channel_lut != (Quantum *) NULL)
941         {
942           for (i=0; i <= (long) MaxMap; i++)
943             {
944               double
945                 value;
946 
947               value=MaxRGBDouble*(log((ScaleMapToQuantum(i)/MaxRGBDouble)*
948                                      immutable_context->double_value+1.0)/
949                                   log(immutable_context->double_value+1.0));
950               mutable_context->channel_lut[i] = RoundDoubleToQuantum(value);
951             }
952         }
953     }
954 #else
955   ARG_NOT_USED(*mutable_context);
956 #endif
957   if (MagickFail == status)
958     return status;
959 
960   switch (immutable_context->channel)
961     {
962     case RedChannel:
963     case CyanChannel:
964       for (i=0; i < npixels; i++)
965         pixels[i].red=LogAdjustQuantum(pixels[i].red);
966       break;
967     case GreenChannel:
968     case MagentaChannel:
969       for (i=0; i < npixels; i++)
970         pixels[i].green=LogAdjustQuantum(pixels[i].green);
971       break;
972     case BlueChannel:
973     case YellowChannel:
974       for (i=0; i < npixels; i++)
975         pixels[i].blue=LogAdjustQuantum(pixels[i].blue);
976       break;
977     case BlackChannel:
978     case MatteChannel:
979     case OpacityChannel:
980       for (i=0; i < npixels; i++)
981         pixels[i].opacity=LogAdjustQuantum(pixels[i].opacity);
982       break;
983     case UndefinedChannel:
984     case AllChannels:
985       for (i=0; i < npixels; i++)
986         {
987           pixels[i].red=LogAdjustQuantum(pixels[i].red);
988           pixels[i].green=LogAdjustQuantum(pixels[i].green);
989           pixels[i].blue=LogAdjustQuantum(pixels[i].blue);
990         }
991       break;
992     case GrayChannel:
993       for (i=0; i < npixels; i++)
994         {
995           Quantum
996             intensity;
997 
998           intensity = PixelIntensity(&pixels[i]);
999           intensity = LogAdjustQuantum(intensity);
1000           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1001         }
1002       break;
1003     }
1004 
1005   return status;
1006 }
1007 static MagickPassFail
QuantumLShiftCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1008 QuantumLShiftCB(void *mutable_data,
1009                 const void *immutable_data,
1010                 Image * restrict image,
1011                 PixelPacket * restrict pixels,
1012                 IndexPacket * restrict indexes,
1013                 const long npixels,
1014                 ExceptionInfo *exception)
1015 {
1016   const QuantumImmutableContext
1017     *context=(const QuantumImmutableContext *) immutable_data;
1018 
1019   register long
1020     i;
1021 
1022   ARG_NOT_USED(mutable_data);
1023   ARG_NOT_USED(image);
1024   ARG_NOT_USED(indexes);
1025   ARG_NOT_USED(exception);
1026 
1027   switch (context->channel)
1028     {
1029     case RedChannel:
1030     case CyanChannel:
1031       for (i=0; i < npixels; i++)
1032         pixels[i].red <<= context->quantum_value;
1033       break;
1034     case GreenChannel:
1035     case MagentaChannel:
1036       for (i=0; i < npixels; i++)
1037         pixels[i].green <<= context->quantum_value;
1038       break;
1039     case BlueChannel:
1040     case YellowChannel:
1041       for (i=0; i < npixels; i++)
1042         pixels[i].blue <<= context->quantum_value;
1043       break;
1044     case BlackChannel:
1045     case MatteChannel:
1046     case OpacityChannel:
1047       for (i=0; i < npixels; i++)
1048         pixels[i].opacity <<= context->quantum_value;
1049       break;
1050     case UndefinedChannel:
1051     case AllChannels:
1052       for (i=0; i < npixels; i++)
1053         {
1054           pixels[i].red <<= context->quantum_value;
1055           pixels[i].green <<= context->quantum_value;
1056           pixels[i].blue <<= context->quantum_value;
1057         }
1058       break;
1059     case GrayChannel:
1060       for (i=0; i < npixels; i++)
1061         {
1062           Quantum
1063             intensity;
1064 
1065           intensity = PixelIntensity(&pixels[i]);
1066           intensity <<= context->quantum_value;
1067           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1068         }
1069       break;
1070     }
1071 
1072   return (MagickPass);
1073 }
1074 static MagickPassFail
QuantumMaxCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1075 QuantumMaxCB(void *mutable_data,
1076              const void *immutable_data,
1077              Image * restrict image,
1078              PixelPacket * restrict pixels,
1079              IndexPacket * restrict indexes,
1080              const long npixels,
1081              ExceptionInfo *exception)
1082 {
1083   const QuantumImmutableContext
1084     *context=(const QuantumImmutableContext *) immutable_data;
1085 
1086   register long
1087     i;
1088 
1089   ARG_NOT_USED(mutable_data);
1090   ARG_NOT_USED(image);
1091   ARG_NOT_USED(indexes);
1092   ARG_NOT_USED(exception);
1093 
1094   switch (context->channel)
1095     {
1096     case RedChannel:
1097     case CyanChannel:
1098       for (i=0; i < npixels; i++)
1099         if (context->quantum_value > pixels[i].red)
1100           pixels[i].red = context->quantum_value;
1101       break;
1102     case GreenChannel:
1103     case MagentaChannel:
1104       for (i=0; i < npixels; i++)
1105         if (context->quantum_value > pixels[i].green)
1106           pixels[i].green = context->quantum_value;
1107       break;
1108     case BlueChannel:
1109     case YellowChannel:
1110       for (i=0; i < npixels; i++)
1111         if (context->quantum_value > pixels[i].blue)
1112           pixels[i].blue = context->quantum_value;
1113       break;
1114     case BlackChannel:
1115     case MatteChannel:
1116     case OpacityChannel:
1117       for (i=0; i < npixels; i++)
1118         if (context->quantum_value > pixels[i].opacity)
1119           pixels[i].opacity = context->quantum_value;
1120       break;
1121     case UndefinedChannel:
1122     case AllChannels:
1123       for (i=0; i < npixels; i++)
1124         {
1125           if (context->quantum_value > pixels[i].red)
1126             pixels[i].red = context->quantum_value;
1127           if (context->quantum_value > pixels[i].green)
1128             pixels[i].green = context->quantum_value;
1129           if (context->quantum_value > pixels[i].blue)
1130             pixels[i].blue = context->quantum_value;
1131         }
1132       break;
1133     case GrayChannel:
1134       for (i=0; i < npixels; i++)
1135         {
1136           Quantum
1137             intensity;
1138 
1139           intensity = PixelIntensity(&pixels[i]);
1140           if (context->quantum_value > intensity)
1141             intensity = context->quantum_value;
1142           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1143         }
1144       break;
1145     }
1146 
1147   return (MagickPass);
1148 }
1149 static MagickPassFail
QuantumMinCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1150 QuantumMinCB(void *mutable_data,
1151              const void *immutable_data,
1152              Image * restrict image,
1153              PixelPacket * restrict pixels,
1154              IndexPacket * restrict indexes,
1155              const long npixels,
1156              ExceptionInfo *exception)
1157 {
1158   const QuantumImmutableContext
1159     *context=(const QuantumImmutableContext *) immutable_data;
1160 
1161   register long
1162     i;
1163 
1164   ARG_NOT_USED(mutable_data);
1165   ARG_NOT_USED(image);
1166   ARG_NOT_USED(indexes);
1167   ARG_NOT_USED(exception);
1168 
1169   switch (context->channel)
1170     {
1171     case RedChannel:
1172     case CyanChannel:
1173       for (i=0; i < npixels; i++)
1174         if (context->quantum_value < pixels[i].red)
1175           pixels[i].red = context->quantum_value;
1176       break;
1177     case GreenChannel:
1178     case MagentaChannel:
1179       for (i=0; i < npixels; i++)
1180         if (context->quantum_value < pixels[i].green)
1181           pixels[i].green = context->quantum_value;
1182       break;
1183     case BlueChannel:
1184     case YellowChannel:
1185       for (i=0; i < npixels; i++)
1186         if (context->quantum_value < pixels[i].blue)
1187           pixels[i].blue = context->quantum_value;
1188       break;
1189     case BlackChannel:
1190     case MatteChannel:
1191     case OpacityChannel:
1192       for (i=0; i < npixels; i++)
1193         if (context->quantum_value < pixels[i].opacity)
1194           pixels[i].opacity = context->quantum_value;
1195       break;
1196     case UndefinedChannel:
1197     case AllChannels:
1198       for (i=0; i < npixels; i++)
1199         {
1200           if (context->quantum_value < pixels[i].red)
1201             pixels[i].red = context->quantum_value;
1202           if (context->quantum_value < pixels[i].green)
1203             pixels[i].green = context->quantum_value;
1204           if (context->quantum_value < pixels[i].blue)
1205             pixels[i].blue = context->quantum_value;
1206         }
1207       break;
1208     case GrayChannel:
1209       for (i=0; i < npixels; i++)
1210         {
1211           Quantum
1212             intensity;
1213 
1214           intensity = PixelIntensity(&pixels[i]);
1215           if (context->quantum_value < intensity)
1216             intensity = context->quantum_value;
1217           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1218         }
1219       break;
1220     }
1221 
1222   return (MagickPass);
1223 }
1224 static MagickPassFail
QuantumMultiplyCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1225 QuantumMultiplyCB(void *mutable_data,
1226                   const void *immutable_data,
1227                   Image * restrict image,
1228                   PixelPacket * restrict pixels,
1229                   IndexPacket * restrict indexes,
1230                   const long npixels,
1231                   ExceptionInfo *exception)
1232 {
1233   const QuantumImmutableContext
1234     *context=(const QuantumImmutableContext *) immutable_data;
1235 
1236   register long
1237     i;
1238 
1239   ARG_NOT_USED(mutable_data);
1240   ARG_NOT_USED(image);
1241   ARG_NOT_USED(indexes);
1242   ARG_NOT_USED(exception);
1243 
1244   switch (context->channel)
1245     {
1246     case RedChannel:
1247     case CyanChannel:
1248       for (i=0; i < npixels; i++)
1249         ApplyArithmeticOperator(pixels[i].red,*,context->double_value);
1250       break;
1251     case GreenChannel:
1252     case MagentaChannel:
1253       for (i=0; i < npixels; i++)
1254         ApplyArithmeticOperator(pixels[i].green,*,context->double_value);
1255       break;
1256     case BlueChannel:
1257     case YellowChannel:
1258       for (i=0; i < npixels; i++)
1259         ApplyArithmeticOperator(pixels[i].blue,*,context->double_value);
1260       break;
1261     case BlackChannel:
1262     case MatteChannel:
1263     case OpacityChannel:
1264       for (i=0; i < npixels; i++)
1265         ApplyArithmeticOperator(pixels[i].opacity,*,context->double_value);
1266       break;
1267     case UndefinedChannel:
1268     case AllChannels:
1269       for (i=0; i < npixels; i++)
1270         {
1271           ApplyArithmeticOperator(pixels[i].red,*,context->double_value);
1272           ApplyArithmeticOperator(pixels[i].green,*,context->double_value);
1273           ApplyArithmeticOperator(pixels[i].blue,*,context->double_value);
1274         }
1275       break;
1276     case GrayChannel:
1277       for (i=0; i < npixels; i++)
1278         {
1279           Quantum
1280             intensity;
1281 
1282           intensity = PixelIntensity(&pixels[i]);
1283           ApplyArithmeticOperator(intensity,*,context->double_value);
1284           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1285         }
1286       break;
1287     }
1288 
1289   return (MagickPass);
1290 }
1291 
1292 static inline Quantum
GenerateQuantumNoise(const Quantum quantum,const NoiseType noise_type,const double factor,MagickRandomKernel * kernel)1293 GenerateQuantumNoise(const Quantum quantum,const NoiseType noise_type,
1294                      const double factor,MagickRandomKernel *kernel)
1295 {
1296   double
1297     value;
1298 
1299   value = (double) quantum+
1300     factor*GenerateDifferentialNoise((double) quantum,noise_type,kernel);
1301   return RoundDoubleToQuantum(value);
1302 }
1303 
1304 static MagickPassFail
QuantumNoiseCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception,const NoiseType noise_type)1305 QuantumNoiseCB(void *mutable_data,
1306                const void *immutable_data,
1307                Image * restrict image,
1308                PixelPacket * restrict pixels,
1309                IndexPacket * restrict indexes,
1310                const long npixels,
1311                ExceptionInfo *exception,
1312                const NoiseType noise_type
1313                )
1314 {
1315   const QuantumImmutableContext
1316     *context=(const QuantumImmutableContext *) immutable_data;
1317 
1318   register long
1319     i;
1320 
1321   double
1322     factor;
1323 
1324   MagickRandomKernel
1325     *kernel;
1326 
1327   ARG_NOT_USED(mutable_data);
1328   ARG_NOT_USED(image);
1329   ARG_NOT_USED(indexes);
1330   ARG_NOT_USED(exception);
1331 
1332   kernel=AcquireMagickRandomKernel();
1333   factor=context->double_value/MaxRGBDouble;
1334 
1335   switch (context->channel)
1336     {
1337     case RedChannel:
1338     case CyanChannel:
1339       for (i=0; i < npixels; i++)
1340         pixels[i].red = GenerateQuantumNoise(pixels[i].red,noise_type,factor,kernel);
1341       break;
1342     case GreenChannel:
1343     case MagentaChannel:
1344       for (i=0; i < npixels; i++)
1345         pixels[i].green = GenerateQuantumNoise(pixels[i].green,noise_type,factor,kernel);
1346       break;
1347     case BlueChannel:
1348     case YellowChannel:
1349       for (i=0; i < npixels; i++)
1350         pixels[i].blue = GenerateQuantumNoise(pixels[i].blue,noise_type,factor,kernel);
1351       break;
1352     case BlackChannel:
1353     case MatteChannel:
1354     case OpacityChannel:
1355       for (i=0; i < npixels; i++)
1356         pixels[i].opacity = GenerateQuantumNoise(pixels[i].opacity,noise_type,factor,kernel);
1357       break;
1358     case UndefinedChannel:
1359     case AllChannels:
1360       for (i=0; i < npixels; i++)
1361         {
1362           pixels[i].red   = GenerateQuantumNoise(pixels[i].red,noise_type,factor,kernel);
1363           pixels[i].green = GenerateQuantumNoise(pixels[i].green,noise_type,factor,kernel);
1364           pixels[i].blue  = GenerateQuantumNoise(pixels[i].blue,noise_type,factor,kernel);
1365         }
1366       break;
1367     case GrayChannel:
1368       for (i=0; i < npixels; i++)
1369         {
1370           Quantum
1371             intensity;
1372 
1373           intensity = PixelIntensity(&pixels[i]);
1374           pixels[i].red = pixels[i].green = pixels[i].blue =
1375             GenerateQuantumNoise(intensity,noise_type,factor,kernel);
1376         }
1377       break;
1378     }
1379 
1380   return (MagickPass);
1381 }
1382 static MagickPassFail
QuantumNoiseGaussianCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1383 QuantumNoiseGaussianCB(void *mutable_data,
1384                        const void *immutable_data,
1385                        Image * restrict image,
1386                        PixelPacket * restrict pixels,
1387                        IndexPacket * restrict indexes,
1388                        const long npixels,
1389                        ExceptionInfo *exception)
1390 {
1391   return
1392     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,exception,GaussianNoise);
1393 }
1394 static MagickPassFail
QuantumNoiseImpulseCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1395 QuantumNoiseImpulseCB(void *mutable_data,
1396                       const void *immutable_data,
1397                       Image * restrict image,
1398                       PixelPacket * restrict pixels,
1399                       IndexPacket * restrict indexes,
1400                       const long npixels,
1401                       ExceptionInfo *exception)
1402 {
1403   return
1404     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,exception,ImpulseNoise);
1405 }
1406 static MagickPassFail
QuantumNoiseLaplacianCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1407 QuantumNoiseLaplacianCB(void *mutable_data,
1408                         const void *immutable_data,
1409                         Image * restrict image,
1410                         PixelPacket * restrict pixels,
1411                         IndexPacket * restrict indexes,
1412                         const long npixels,
1413                         ExceptionInfo *exception)
1414 {
1415   return
1416     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,exception,LaplacianNoise);
1417 }
1418 static MagickPassFail
QuantumNoiseMultiplicativeCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1419 QuantumNoiseMultiplicativeCB(void *mutable_data,
1420                              const void *immutable_data,
1421                              Image * restrict image,
1422                              PixelPacket * restrict pixels,
1423                              IndexPacket * restrict indexes,
1424                              const long npixels,
1425                              ExceptionInfo *exception)
1426 {
1427   return
1428     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,
1429                  exception,MultiplicativeGaussianNoise);
1430 }
1431 static MagickPassFail
QuantumNoisePoissonCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1432 QuantumNoisePoissonCB(void *mutable_data,
1433                       const void *immutable_data,
1434                       Image * restrict image,
1435                       PixelPacket * restrict pixels,
1436                       IndexPacket * restrict indexes,
1437                       const long npixels,
1438                       ExceptionInfo *exception)
1439 {
1440   return
1441     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,exception,PoissonNoise);
1442 }
1443 
1444 
1445 static MagickPassFail
QuantumNoiseRandomCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1446 QuantumNoiseRandomCB(void *mutable_data,
1447                      const void *immutable_data,
1448                       Image * restrict image,
1449                       PixelPacket * restrict pixels,
1450                       IndexPacket * restrict indexes,
1451                       const long npixels,
1452                       ExceptionInfo *exception)
1453 {
1454   return
1455     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,exception,RandomNoise);
1456 }
1457 
1458 static MagickPassFail
QuantumNoiseUniformCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1459 QuantumNoiseUniformCB(void *mutable_data,
1460                       const void *immutable_data,
1461                       Image * restrict image,
1462                       PixelPacket * restrict pixels,
1463                       IndexPacket * restrict indexes,
1464                       const long npixels,
1465                       ExceptionInfo *exception)
1466 {
1467   return
1468     QuantumNoiseCB(mutable_data,immutable_data,image,pixels,indexes,npixels,exception,UniformNoise);
1469 }
1470 static MagickPassFail
QuantumOrCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1471 QuantumOrCB(void *mutable_data,
1472             const void *immutable_data,
1473             Image * restrict image,
1474             PixelPacket * restrict pixels,
1475             IndexPacket * restrict indexes,
1476             const long npixels,
1477             ExceptionInfo *exception)
1478 {
1479   const QuantumImmutableContext
1480     *context=(const QuantumImmutableContext *) immutable_data;
1481 
1482   register long
1483     i;
1484 
1485   ARG_NOT_USED(mutable_data);
1486   ARG_NOT_USED(image);
1487   ARG_NOT_USED(indexes);
1488   ARG_NOT_USED(exception);
1489 
1490   switch (context->channel)
1491     {
1492     case RedChannel:
1493     case CyanChannel:
1494       for (i=0; i < npixels; i++)
1495         pixels[i].red |= context->quantum_value;
1496       break;
1497     case GreenChannel:
1498     case MagentaChannel:
1499       for (i=0; i < npixels; i++)
1500         pixels[i].green |= context->quantum_value;
1501       break;
1502     case BlueChannel:
1503     case YellowChannel:
1504       for (i=0; i < npixels; i++)
1505         pixels[i].blue |= context->quantum_value;
1506       break;
1507     case BlackChannel:
1508     case MatteChannel:
1509     case OpacityChannel:
1510       for (i=0; i < npixels; i++)
1511         pixels[i].opacity |= context->quantum_value;
1512       break;
1513     case UndefinedChannel:
1514     case AllChannels:
1515       for (i=0; i < npixels; i++)
1516         {
1517           pixels[i].red |= context->quantum_value;
1518           pixels[i].green |= context->quantum_value;
1519           pixels[i].blue |= context->quantum_value;
1520         }
1521       break;
1522     case GrayChannel:
1523       for (i=0; i < npixels; i++)
1524         {
1525           Quantum
1526             intensity;
1527 
1528           intensity = PixelIntensity(&pixels[i]);
1529           intensity |= context->quantum_value;
1530           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1531         }
1532       break;
1533     }
1534 
1535   return (MagickPass);
1536 }
1537 #if MaxRGB > MaxMap
1538 #  define PowAdjustQuantum(quantum) (MaxRGBDouble*pow(quantum/MaxRGBDouble,immutable_context->double_value)+0.5)
1539 #else
1540 #  define PowAdjustQuantum(quantum) (mutable_context->channel_lut[ScaleQuantumToMap(quantum)])
1541 #endif
1542 static MagickPassFail
QuantumPowCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1543 QuantumPowCB(void *mutable_data,
1544              const void *immutable_data,
1545              Image * restrict image,
1546              PixelPacket * restrict pixels,
1547              IndexPacket * restrict indexes,
1548              const long npixels,
1549              ExceptionInfo *exception)
1550 {
1551   QuantumMutableContext
1552     *mutable_context=(QuantumMutableContext *) mutable_data;
1553 
1554   const QuantumImmutableContext
1555     *immutable_context=(const QuantumImmutableContext *) immutable_data;
1556 
1557   register long
1558     i;
1559 
1560   MagickPassFail
1561     status=MagickPass;
1562 
1563   ARG_NOT_USED(image);
1564   ARG_NOT_USED(indexes);
1565   ARG_NOT_USED(exception);
1566 
1567   /*
1568     Build LUT for Q8 and Q16 builds
1569   */
1570 #if MaxRGB <= MaxMap
1571 #  if defined(HAVE_OPENMP)
1572 #    pragma omp critical (GM_QuantumPowCB)
1573 #  endif
1574   if (mutable_context->channel_lut == (Quantum *) NULL)
1575     {
1576       mutable_context->channel_lut=MagickAllocateArray(Quantum *, MaxMap+1,sizeof(Quantum));
1577       if (mutable_context->channel_lut == (Quantum *) NULL)
1578         status=MagickFail;
1579 
1580       if (mutable_context->channel_lut != (Quantum *) NULL)
1581         {
1582           for (i=0; i <= (long) MaxMap; i++)
1583             mutable_context->channel_lut[i] =
1584               ScaleMapToQuantum(MaxMap*pow((double) i/MaxMap,
1585                                            immutable_context->double_value));
1586         }
1587     }
1588 #else
1589   ARG_NOT_USED(*mutable_context);
1590 #endif
1591   if (MagickFail == status)
1592     return status;
1593 
1594   switch (immutable_context->channel)
1595     {
1596     case RedChannel:
1597     case CyanChannel:
1598       for (i=0; i < npixels; i++)
1599         pixels[i].red=PowAdjustQuantum(pixels[i].red);
1600       break;
1601     case GreenChannel:
1602     case MagentaChannel:
1603       for (i=0; i < npixels; i++)
1604         pixels[i].green=PowAdjustQuantum(pixels[i].green);
1605       break;
1606     case BlueChannel:
1607     case YellowChannel:
1608       for (i=0; i < npixels; i++)
1609         pixels[i].blue=PowAdjustQuantum(pixels[i].blue);
1610       break;
1611     case BlackChannel:
1612     case MatteChannel:
1613     case OpacityChannel:
1614       for (i=0; i < npixels; i++)
1615         pixels[i].opacity=PowAdjustQuantum(pixels[i].opacity);
1616       break;
1617     case UndefinedChannel:
1618     case AllChannels:
1619       for (i=0; i < npixels; i++)
1620         {
1621           pixels[i].red=PowAdjustQuantum(pixels[i].red);
1622           pixels[i].green=PowAdjustQuantum(pixels[i].green);
1623           pixels[i].blue=PowAdjustQuantum(pixels[i].blue);
1624         }
1625       break;
1626     case GrayChannel:
1627       for (i=0; i < npixels; i++)
1628         {
1629           Quantum
1630             intensity;
1631 
1632           intensity = PixelIntensity(&pixels[i]);
1633           intensity = PowAdjustQuantum(intensity);
1634           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1635         }
1636       break;
1637     }
1638 
1639   return status;
1640 }
1641 static MagickPassFail
QuantumRShiftCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1642 QuantumRShiftCB(void *mutable_data,
1643                 const void *immutable_data,
1644                 Image * restrict image,
1645                 PixelPacket * restrict pixels,
1646                 IndexPacket * restrict indexes,
1647                 const long npixels,
1648                 ExceptionInfo *exception)
1649 {
1650   const QuantumImmutableContext
1651     *context=(const QuantumImmutableContext *) immutable_data;
1652 
1653   register long
1654     i;
1655 
1656   ARG_NOT_USED(mutable_data);
1657   ARG_NOT_USED(image);
1658   ARG_NOT_USED(indexes);
1659   ARG_NOT_USED(exception);
1660 
1661   switch (context->channel)
1662     {
1663     case RedChannel:
1664     case CyanChannel:
1665       for (i=0; i < npixels; i++)
1666         pixels[i].red >>= context->quantum_value;
1667       break;
1668     case GreenChannel:
1669     case MagentaChannel:
1670       for (i=0; i < npixels; i++)
1671         pixels[i].green >>= context->quantum_value;
1672       break;
1673     case BlueChannel:
1674     case YellowChannel:
1675       for (i=0; i < npixels; i++)
1676         pixels[i].blue >>= context->quantum_value;
1677       break;
1678     case BlackChannel:
1679     case MatteChannel:
1680     case OpacityChannel:
1681       for (i=0; i < npixels; i++)
1682         pixels[i].opacity >>= context->quantum_value;
1683       break;
1684     case UndefinedChannel:
1685     case AllChannels:
1686       for (i=0; i < npixels; i++)
1687         {
1688           pixels[i].red >>= context->quantum_value;
1689           pixels[i].green >>= context->quantum_value;
1690           pixels[i].blue >>= context->quantum_value;
1691         }
1692       break;
1693     case GrayChannel:
1694       for (i=0; i < npixels; i++)
1695         {
1696           Quantum
1697             intensity;
1698 
1699           intensity = PixelIntensity(&pixels[i]);
1700           intensity >>= context->quantum_value;
1701           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1702         }
1703       break;
1704     }
1705 
1706   return (MagickPass);
1707 }
1708 static MagickPassFail
QuantumSubtractCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1709 QuantumSubtractCB(void *mutable_data,
1710                   const void *immutable_data,
1711                   Image * restrict image,
1712                   PixelPacket * restrict pixels,
1713                   IndexPacket * restrict indexes,
1714                   const long npixels,
1715                   ExceptionInfo *exception)
1716 {
1717   const QuantumImmutableContext
1718     *context=(const QuantumImmutableContext *) immutable_data;
1719 
1720   register long
1721     i;
1722 
1723   ARG_NOT_USED(mutable_data);
1724   ARG_NOT_USED(image);
1725   ARG_NOT_USED(indexes);
1726   ARG_NOT_USED(exception);
1727 
1728   switch (context->channel)
1729     {
1730     case RedChannel:
1731     case CyanChannel:
1732       for (i=0; i < npixels; i++)
1733         ApplyArithmeticOperator(pixels[i].red,-,context->double_value);
1734       break;
1735     case GreenChannel:
1736     case MagentaChannel:
1737       for (i=0; i < npixels; i++)
1738         ApplyArithmeticOperator(pixels[i].green,-,context->double_value);
1739       break;
1740     case BlueChannel:
1741     case YellowChannel:
1742       for (i=0; i < npixels; i++)
1743         ApplyArithmeticOperator(pixels[i].blue,-,context->double_value);
1744       break;
1745     case BlackChannel:
1746     case MatteChannel:
1747     case OpacityChannel:
1748       for (i=0; i < npixels; i++)
1749         ApplyArithmeticOperator(pixels[i].opacity,-,context->double_value);
1750       break;
1751     case UndefinedChannel:
1752     case AllChannels:
1753       for (i=0; i < npixels; i++)
1754         {
1755           ApplyArithmeticOperator(pixels[i].red,-,context->double_value);
1756           ApplyArithmeticOperator(pixels[i].green,-,context->double_value);
1757           ApplyArithmeticOperator(pixels[i].blue,-,context->double_value);
1758         }
1759       break;
1760     case GrayChannel:
1761       for (i=0; i < npixels; i++)
1762         {
1763           Quantum
1764             intensity;
1765 
1766           intensity = PixelIntensity(&pixels[i]);
1767           ApplyArithmeticOperator(intensity,-,context->double_value);
1768           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
1769         }
1770       break;
1771     }
1772 
1773   return (MagickPass);
1774 }
1775 
ApplyThresholdOperator(const Quantum quantum,const Quantum threshold)1776 static inline Quantum ApplyThresholdOperator(const Quantum quantum,
1777                                              const Quantum threshold)
1778 {
1779   Quantum
1780     result;
1781 
1782   if (quantum > threshold)
1783     result=MaxRGB;
1784   else
1785     result=0U;
1786 
1787   return result;
1788 }
1789 static MagickPassFail
QuantumThresholdCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1790 QuantumThresholdCB(void *mutable_data,
1791                    const void *immutable_data,
1792                    Image * restrict image,
1793                    PixelPacket * restrict pixels,
1794                    IndexPacket * restrict indexes,
1795                    const long npixels,
1796                    ExceptionInfo *exception)
1797 {
1798   const QuantumImmutableContext
1799     *context=(const QuantumImmutableContext *) immutable_data;
1800 
1801   register long
1802     i;
1803 
1804   ARG_NOT_USED(mutable_data);
1805   ARG_NOT_USED(image);
1806   ARG_NOT_USED(indexes);
1807   ARG_NOT_USED(exception);
1808 
1809   switch (context->channel)
1810     {
1811     case RedChannel:
1812     case CyanChannel:
1813       for (i=0; i < npixels; i++)
1814         pixels[i].red = ApplyThresholdOperator(pixels[i].red,context->quantum_value);
1815       break;
1816     case GreenChannel:
1817     case MagentaChannel:
1818       for (i=0; i < npixels; i++)
1819         pixels[i].green = ApplyThresholdOperator(pixels[i].green,context->quantum_value);
1820       break;
1821     case BlueChannel:
1822     case YellowChannel:
1823       for (i=0; i < npixels; i++)
1824         pixels[i].blue = ApplyThresholdOperator(pixels[i].blue,context->quantum_value);
1825       break;
1826     case BlackChannel:
1827     case MatteChannel:
1828     case OpacityChannel:
1829       for (i=0; i < npixels; i++)
1830         pixels[i].opacity = ApplyThresholdOperator(pixels[i].opacity,context->quantum_value);
1831       break;
1832     case UndefinedChannel:
1833     case AllChannels:
1834     case GrayChannel:
1835       for (i=0; i < npixels; i++)
1836         {
1837           Quantum
1838             intensity;
1839 
1840           intensity = PixelIntensity(&pixels[i]);
1841           pixels[i].red = pixels[i].green = pixels[i].blue =
1842             ApplyThresholdOperator(intensity,context->quantum_value);
1843         }
1844       break;
1845     }
1846   return (MagickPass);
1847 }
1848 
ApplyThresholdBlackOperator(const Quantum quantum,const Quantum threshold)1849 static inline Quantum ApplyThresholdBlackOperator(const Quantum quantum,
1850                                                   const Quantum threshold)
1851 {
1852   Quantum
1853     result;
1854 
1855   if (quantum < threshold)
1856     result=0U;
1857   else
1858     result=quantum;
1859 
1860   return result;
1861 }
1862 static MagickPassFail
QuantumThresholdBlackCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1863 QuantumThresholdBlackCB(void *mutable_data,
1864                         const void *immutable_data,
1865                         Image * restrict image,
1866                         PixelPacket * restrict pixels,
1867                         IndexPacket * restrict indexes,
1868                         const long npixels,
1869                         ExceptionInfo *exception)
1870 {
1871   const QuantumImmutableContext
1872     *context=(const QuantumImmutableContext *) immutable_data;
1873 
1874   register long
1875     i;
1876 
1877   ARG_NOT_USED(mutable_data);
1878   ARG_NOT_USED(image);
1879   ARG_NOT_USED(indexes);
1880   ARG_NOT_USED(exception);
1881 
1882   switch (context->channel)
1883     {
1884     case RedChannel:
1885     case CyanChannel:
1886       for (i=0; i < npixels; i++)
1887         pixels[i].red = ApplyThresholdBlackOperator(pixels[i].red,context->quantum_value);
1888       break;
1889     case GreenChannel:
1890     case MagentaChannel:
1891       for (i=0; i < npixels; i++)
1892         pixels[i].green = ApplyThresholdBlackOperator(pixels[i].green,context->quantum_value);
1893       break;
1894     case BlueChannel:
1895     case YellowChannel:
1896       for (i=0; i < npixels; i++)
1897         pixels[i].blue = ApplyThresholdBlackOperator(pixels[i].blue,context->quantum_value);
1898       break;
1899     case BlackChannel:
1900     case MatteChannel:
1901     case OpacityChannel:
1902       for (i=0; i < npixels; i++)
1903         pixels[i].opacity = ApplyThresholdBlackOperator(pixels[i].opacity,context->quantum_value);
1904       break;
1905     case UndefinedChannel:
1906     case AllChannels:
1907       /*
1908         For the all-channels case we bend the rules a bit and only
1909         threshold to black if the computed intensity of the color
1910         channels is less than the threshold.  This allows black
1911         thresholding to work without causing a color shift.  If
1912         individual channels need to be thresholded, then per-channel
1913         thresholding will be required for each channel to be
1914         thresholded.
1915       */
1916       for (i=0; i < npixels; i++)
1917         {
1918           Quantum
1919             intensity;
1920 
1921           intensity = PixelIntensity(&pixels[i]);
1922           if (0U == ApplyThresholdBlackOperator(intensity,context->quantum_value))
1923             pixels[i].red=pixels[i].green=pixels[i].blue=0U;
1924         }
1925       break;
1926     case GrayChannel:
1927       for (i=0; i < npixels; i++)
1928         {
1929           Quantum
1930             intensity;
1931 
1932           intensity = PixelIntensity(&pixels[i]);
1933           pixels[i].red = pixels[i].green = pixels[i].blue =
1934             ApplyThresholdBlackOperator(intensity,context->quantum_value);
1935         }
1936       break;
1937     }
1938   return (MagickPass);
1939 }
1940 
ApplyThresholdWhiteOperator(const Quantum quantum,const Quantum threshold)1941 static inline Quantum ApplyThresholdWhiteOperator(const Quantum quantum,
1942                                                   const Quantum threshold)
1943 {
1944   Quantum
1945     result;
1946 
1947   if (quantum > threshold)
1948     result=MaxRGB;
1949   else
1950     result=quantum;
1951 
1952   return result;
1953 }
1954 static MagickPassFail
QuantumThresholdWhiteCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)1955 QuantumThresholdWhiteCB(void *mutable_data,
1956                         const void *immutable_data,
1957                         Image * restrict image,
1958                         PixelPacket * restrict pixels,
1959                         IndexPacket * restrict indexes,
1960                         const long npixels,
1961                         ExceptionInfo *exception)
1962 {
1963   const QuantumImmutableContext
1964     *context=(const QuantumImmutableContext *) immutable_data;
1965 
1966   register long
1967     i;
1968 
1969   ARG_NOT_USED(mutable_data);
1970   ARG_NOT_USED(image);
1971   ARG_NOT_USED(indexes);
1972   ARG_NOT_USED(exception);
1973 
1974   switch (context->channel)
1975     {
1976     case RedChannel:
1977     case CyanChannel:
1978       for (i=0; i < npixels; i++)
1979         pixels[i].red = ApplyThresholdWhiteOperator(pixels[i].red,context->quantum_value);
1980       break;
1981     case GreenChannel:
1982     case MagentaChannel:
1983       for (i=0; i < npixels; i++)
1984         pixels[i].green = ApplyThresholdWhiteOperator(pixels[i].green,context->quantum_value);
1985       break;
1986     case BlueChannel:
1987     case YellowChannel:
1988       for (i=0; i < npixels; i++)
1989         pixels[i].blue = ApplyThresholdWhiteOperator(pixels[i].blue,context->quantum_value);
1990       break;
1991     case BlackChannel:
1992     case MatteChannel:
1993     case OpacityChannel:
1994       for (i=0; i < npixels; i++)
1995         pixels[i].opacity = ApplyThresholdWhiteOperator(pixels[i].opacity,context->quantum_value);
1996       break;
1997     case UndefinedChannel:
1998     case AllChannels:
1999       /*
2000         For the all-channels case we bend the rules a bit and only
2001         threshold to white if the computed intensity of the color
2002         channels exceeds the threshold.  This allows white
2003         thresholding to work without causing a color shift.  If
2004         individual channels need to be thresholded, then per-channel
2005         thresholding will be required for each channel to be
2006         thresholded.
2007       */
2008       for (i=0; i < npixels; i++)
2009         {
2010           Quantum
2011             intensity;
2012 
2013           intensity = PixelIntensity(&pixels[i]);
2014           if (MaxRGB == ApplyThresholdWhiteOperator(intensity,context->quantum_value))
2015             pixels[i].red=pixels[i].green=pixels[i].blue=MaxRGB;
2016         }
2017       break;
2018     case GrayChannel:
2019       for (i=0; i < npixels; i++)
2020         {
2021           Quantum
2022             intensity;
2023 
2024           intensity = PixelIntensity(&pixels[i]);
2025           pixels[i].red = pixels[i].green = pixels[i].blue =
2026             ApplyThresholdWhiteOperator(intensity,context->quantum_value);
2027         }
2028       break;
2029     }
2030   return (MagickPass);
2031 }
2032 
ApplyThresholdBlackNegateOperator(const Quantum intensity,const Quantum quantum,const Quantum threshold)2033 static inline Quantum ApplyThresholdBlackNegateOperator(const Quantum intensity,
2034                                                         const Quantum quantum,
2035                                                         const Quantum threshold)
2036 {
2037   Quantum
2038     result;
2039 
2040   if (intensity < threshold)
2041     result=MaxRGB;
2042   else
2043     result=quantum;
2044 
2045   return result;
2046 }
2047 static MagickPassFail
QuantumThresholdBlackNegateCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)2048 QuantumThresholdBlackNegateCB(void *mutable_data,
2049                               const void *immutable_data,
2050                               Image * restrict image,
2051                               PixelPacket * restrict pixels,
2052                               IndexPacket * restrict indexes,
2053                               const long npixels,
2054                               ExceptionInfo *exception)
2055 {
2056   const QuantumImmutableContext
2057     *context=(const QuantumImmutableContext *) immutable_data;
2058 
2059   register long
2060     i;
2061 
2062   ARG_NOT_USED(mutable_data);
2063   ARG_NOT_USED(image);
2064   ARG_NOT_USED(indexes);
2065   ARG_NOT_USED(exception);
2066 
2067   switch (context->channel)
2068     {
2069     case RedChannel:
2070     case CyanChannel:
2071       for (i=0; i < npixels; i++)
2072         pixels[i].red = ApplyThresholdBlackNegateOperator(pixels[i].red,pixels[i].red,context->quantum_value);
2073       break;
2074     case GreenChannel:
2075     case MagentaChannel:
2076       for (i=0; i < npixels; i++)
2077         pixels[i].green = ApplyThresholdBlackNegateOperator(pixels[i].green,pixels[i].green,context->quantum_value);
2078       break;
2079     case BlueChannel:
2080     case YellowChannel:
2081       for (i=0; i < npixels; i++)
2082         pixels[i].blue = ApplyThresholdBlackNegateOperator(pixels[i].blue,pixels[i].blue,context->quantum_value);
2083       break;
2084     case BlackChannel:
2085     case MatteChannel:
2086     case OpacityChannel:
2087       for (i=0; i < npixels; i++)
2088         pixels[i].opacity = ApplyThresholdBlackNegateOperator(pixels[i].opacity,pixels[i].opacity,context->quantum_value);
2089       break;
2090     case UndefinedChannel:
2091     case AllChannels:
2092       /*
2093         For the all-channels case we bend the rules a bit and only
2094         threshold to black if the computed intensity of the color
2095         channels is less than the threshold.  This allows black
2096         thresholding to work without causing a color shift.  If
2097         individual channels need to be thresholded, then per-channel
2098         thresholding will be required for each channel to be
2099         thresholded.
2100       */
2101       for (i=0; i < npixels; i++)
2102         {
2103           Quantum
2104             intensity;
2105 
2106           intensity = PixelIntensity(&pixels[i]);
2107           pixels[i].red=ApplyThresholdBlackNegateOperator(intensity,pixels[i].red,context->quantum_value);
2108           pixels[i].green=ApplyThresholdBlackNegateOperator(intensity,pixels[i].green,context->quantum_value);
2109           pixels[i].blue=ApplyThresholdBlackNegateOperator(intensity,pixels[i].blue,context->quantum_value);
2110         }
2111       break;
2112     case GrayChannel:
2113       for (i=0; i < npixels; i++)
2114         {
2115           Quantum
2116             intensity;
2117 
2118           intensity = PixelIntensity(&pixels[i]);
2119           pixels[i].red = pixels[i].green = pixels[i].blue =
2120             ApplyThresholdBlackNegateOperator(intensity,intensity,context->quantum_value);
2121         }
2122       break;
2123     }
2124   return (MagickPass);
2125 }
2126 
ApplyThresholdWhiteNegateOperator(const Quantum intensity,const Quantum quantum,const Quantum threshold)2127 static inline Quantum ApplyThresholdWhiteNegateOperator(const Quantum intensity,
2128                                                         const Quantum quantum,
2129                                                         const Quantum threshold)
2130 {
2131   Quantum
2132     result;
2133 
2134   if (intensity > threshold)
2135     result=0U;
2136   else
2137     result=quantum;
2138 
2139   return result;
2140 }
2141 static MagickPassFail
QuantumThresholdWhiteNegateCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)2142 QuantumThresholdWhiteNegateCB(void *mutable_data,
2143                               const void *immutable_data,
2144                               Image * restrict image,
2145                               PixelPacket * restrict pixels,
2146                               IndexPacket * restrict indexes,
2147                               const long npixels,
2148                               ExceptionInfo *exception)
2149 {
2150   const QuantumImmutableContext
2151     *context=(const QuantumImmutableContext *) immutable_data;
2152 
2153   register long
2154     i;
2155 
2156   ARG_NOT_USED(mutable_data);
2157   ARG_NOT_USED(image);
2158   ARG_NOT_USED(indexes);
2159   ARG_NOT_USED(exception);
2160 
2161   switch (context->channel)
2162     {
2163     case RedChannel:
2164     case CyanChannel:
2165       for (i=0; i < npixels; i++)
2166         pixels[i].red = ApplyThresholdWhiteNegateOperator(pixels[i].red,pixels[i].red,context->quantum_value);
2167       break;
2168     case GreenChannel:
2169     case MagentaChannel:
2170       for (i=0; i < npixels; i++)
2171         pixels[i].green = ApplyThresholdWhiteNegateOperator(pixels[i].green,pixels[i].green,context->quantum_value);
2172       break;
2173     case BlueChannel:
2174     case YellowChannel:
2175       for (i=0; i < npixels; i++)
2176         pixels[i].blue = ApplyThresholdWhiteNegateOperator(pixels[i].blue,pixels[i].blue,context->quantum_value);
2177       break;
2178     case BlackChannel:
2179     case MatteChannel:
2180     case OpacityChannel:
2181       for (i=0; i < npixels; i++)
2182         pixels[i].opacity = ApplyThresholdWhiteNegateOperator(pixels[i].opacity,pixels[i].opacity,context->quantum_value);
2183       break;
2184     case UndefinedChannel:
2185     case AllChannels:
2186       /*
2187         For the all-channels case we bend the rules a bit and only
2188         threshold to white if the computed intensity of the color
2189         channels exceeds the threshold.  This allows white
2190         thresholding to work without causing a color shift.  If
2191         individual channels need to be thresholded, then per-channel
2192         thresholding will be required for each channel to be
2193         thresholded.
2194       */
2195       for (i=0; i < npixels; i++)
2196         {
2197           Quantum
2198             intensity;
2199 
2200           intensity = PixelIntensity(&pixels[i]);
2201           pixels[i].red = ApplyThresholdWhiteNegateOperator(intensity,pixels[i].red,context->quantum_value);
2202           pixels[i].green = ApplyThresholdWhiteNegateOperator(intensity,pixels[i].green,context->quantum_value);
2203           pixels[i].blue = ApplyThresholdWhiteNegateOperator(intensity,pixels[i].blue,context->quantum_value);
2204         }
2205       break;
2206     case GrayChannel:
2207       for (i=0; i < npixels; i++)
2208         {
2209           Quantum
2210             intensity;
2211 
2212           intensity = PixelIntensity(&pixels[i]);
2213           pixels[i].red = pixels[i].green = pixels[i].blue =
2214             ApplyThresholdWhiteNegateOperator(intensity,intensity,context->quantum_value);
2215         }
2216       break;
2217     }
2218   return (MagickPass);
2219 }
2220 
2221 static MagickPassFail
QuantumXorCB(void * mutable_data,const void * immutable_data,Image * restrict image,PixelPacket * restrict pixels,IndexPacket * restrict indexes,const long npixels,ExceptionInfo * exception)2222 QuantumXorCB(void *mutable_data,
2223              const void *immutable_data,
2224              Image * restrict image,
2225              PixelPacket * restrict pixels,
2226              IndexPacket * restrict indexes,
2227              const long npixels,
2228              ExceptionInfo *exception)
2229 {
2230   const QuantumImmutableContext
2231     *context=(const QuantumImmutableContext *) immutable_data;
2232 
2233   register long
2234     i;
2235 
2236   ARG_NOT_USED(mutable_data);
2237   ARG_NOT_USED(image);
2238   ARG_NOT_USED(indexes);
2239   ARG_NOT_USED(exception);
2240 
2241   switch (context->channel)
2242     {
2243     case RedChannel:
2244     case CyanChannel:
2245       for (i=0; i < npixels; i++)
2246         pixels[i].red ^= context->quantum_value;
2247       break;
2248     case GreenChannel:
2249     case MagentaChannel:
2250       for (i=0; i < npixels; i++)
2251         pixels[i].green ^= context->quantum_value;
2252       break;
2253     case BlueChannel:
2254     case YellowChannel:
2255       for (i=0; i < npixels; i++)
2256         pixels[i].blue ^= context->quantum_value;
2257       break;
2258     case BlackChannel:
2259     case MatteChannel:
2260     case OpacityChannel:
2261       for (i=0; i < npixels; i++)
2262         pixels[i].opacity ^= context->quantum_value;
2263       break;
2264     case UndefinedChannel:
2265     case AllChannels:
2266       for (i=0; i < npixels; i++)
2267         {
2268           pixels[i].red ^= context->quantum_value;
2269           pixels[i].green ^= context->quantum_value;
2270           pixels[i].blue ^= context->quantum_value;
2271         }
2272       break;
2273     case GrayChannel:
2274       for (i=0; i < npixels; i++)
2275         {
2276           Quantum
2277             intensity;
2278 
2279           intensity = PixelIntensity(&pixels[i]);
2280           intensity ^= context->quantum_value;
2281           pixels[i].red = pixels[i].green = pixels[i].blue = intensity;
2282         }
2283       break;
2284     }
2285   return (MagickPass);
2286 }
2287 MagickExport MagickPassFail
QuantumOperatorRegionImage(Image * image,const long x,const long y,const unsigned long columns,const unsigned long rows,const ChannelType channel,const QuantumOperator quantum_operator,const double rvalue,ExceptionInfo * exception)2288 QuantumOperatorRegionImage(Image *image,
2289                            const long x,const long y,
2290                            const unsigned long columns,
2291                            const unsigned long rows,
2292                            const ChannelType channel,
2293                            const QuantumOperator quantum_operator,
2294                            const double rvalue,
2295                            ExceptionInfo *exception)
2296 {
2297   char
2298     description[MaxTextExtent];
2299 
2300   QuantumImmutableContext
2301     immutable_context;
2302 
2303   QuantumMutableContext
2304     mutable_context;
2305 
2306   MagickPassFail
2307     status = MagickFail;
2308 
2309   PixelIteratorMonoModifyCallback
2310     call_back = 0;
2311 
2312   image->storage_class=DirectClass;
2313 
2314   immutable_context.channel=channel;
2315   immutable_context.double_value=rvalue;
2316   immutable_context.quantum_value=RoundDoubleToQuantum(rvalue);
2317 
2318   mutable_context.channel_lut=(Quantum *) NULL;
2319 
2320   switch (quantum_operator)
2321     {
2322     case UndefinedQuantumOp:
2323       break;
2324     case AddQuantumOp:
2325       call_back=QuantumAddCB;
2326       break;
2327     case AndQuantumOp:
2328       call_back=QuantumAndCB;
2329       break;
2330     case AssignQuantumOp:
2331       call_back=QuantumAssignCB;
2332       break;
2333     case DivideQuantumOp:
2334       call_back=QuantumDivideCB;
2335       break;
2336     case LShiftQuantumOp:
2337       call_back=QuantumLShiftCB;
2338       break;
2339     case MultiplyQuantumOp:
2340       call_back=QuantumMultiplyCB;
2341       break;
2342     case OrQuantumOp:
2343       call_back=QuantumOrCB;
2344       break;
2345     case RShiftQuantumOp:
2346       call_back=QuantumRShiftCB;
2347       break;
2348     case SubtractQuantumOp:
2349       call_back=QuantumSubtractCB;
2350       break;
2351     case ThresholdQuantumOp:
2352       call_back=QuantumThresholdCB;
2353       break;
2354     case ThresholdBlackQuantumOp:
2355       call_back=QuantumThresholdBlackCB;
2356       break;
2357     case ThresholdWhiteQuantumOp:
2358       call_back=QuantumThresholdWhiteCB;
2359       break;
2360     case ThresholdBlackNegateQuantumOp:
2361       call_back=QuantumThresholdBlackNegateCB;
2362       break;
2363     case ThresholdWhiteNegateQuantumOp:
2364       call_back=QuantumThresholdWhiteNegateCB;
2365       break;
2366     case XorQuantumOp:
2367       call_back=QuantumXorCB;
2368       break;
2369     case NoiseGaussianQuantumOp:
2370       call_back=QuantumNoiseGaussianCB;
2371       break;
2372     case NoiseImpulseQuantumOp:
2373       call_back=QuantumNoiseImpulseCB;
2374       break;
2375     case NoiseLaplacianQuantumOp:
2376       call_back=QuantumNoiseLaplacianCB;
2377       break;
2378     case NoiseMultiplicativeQuantumOp:
2379       call_back=QuantumNoiseMultiplicativeCB;
2380       break;
2381     case NoisePoissonQuantumOp:
2382       call_back=QuantumNoisePoissonCB;
2383       break;
2384     case NoiseUniformQuantumOp:
2385       call_back=QuantumNoiseUniformCB;
2386       break;
2387     case NegateQuantumOp:
2388       call_back=QuantumNegateCB;
2389       break;
2390     case GammaQuantumOp:
2391       call_back=QuantumGammaCB;
2392       break;
2393     case DepthQuantumOp:
2394       call_back=QuantumDepthCB;
2395       break;
2396     case LogQuantumOp:
2397       call_back=QuantumLogCB;
2398       break;
2399     case MaxQuantumOp:
2400       call_back=QuantumMaxCB;
2401       break;
2402     case MinQuantumOp:
2403       call_back=QuantumMinCB;
2404       break;
2405     case PowQuantumOp:
2406       call_back=QuantumPowCB;
2407       break;
2408     case NoiseRandomQuantumOp:
2409       call_back=QuantumNoiseRandomCB;
2410       break;
2411     }
2412 
2413   if (call_back)
2414     {
2415       FormatString(description,"[%%s] Apply operator '%s %g (%g%%%%)' to channel '%s'...",
2416                    QuantumOperatorToString(quantum_operator),rvalue,
2417                    ((rvalue/MaxRGBFloat)*100),
2418                    ChannelTypeToString(channel));
2419       status=PixelIterateMonoModify(call_back,
2420                                     NULL,
2421                                     description,
2422                                     &mutable_context,&immutable_context,x,y,columns,rows,
2423                                     image,exception);
2424 
2425       /*
2426         Free any channel LUT.
2427       */
2428       MagickFreeMemory(mutable_context.channel_lut);
2429 
2430       /*
2431         If we are assigning all the color channels in the entire image
2432         then set monochrome and grayscale flags.
2433       */
2434       if ((quantum_operator == AssignQuantumOp) &&
2435           (channel == AllChannels) && (x == 0) && (y == 0) &&
2436           (columns == image->columns) && (rows == image->rows))
2437         {
2438           image->is_monochrome=MagickTrue;
2439           image->is_grayscale=MagickTrue;
2440         }
2441     }
2442   return (status);
2443 }
2444