1 /*
2   Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization
3   dedicated to making software imaging solutions freely available.
4 
5   You may not use this file except in compliance with the License.  You may
6   obtain a copy of the License at
7 
8     https://imagemagick.org/script/license.php
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 
16   MagickCore pixel accessor methods.
17 */
18 #ifndef MAGICKCORE_PIXEL_ACCESSOR_H
19 #define MAGICKCORE_PIXEL_ACCESSOR_H
20 
21 #include <assert.h>
22 #include "MagickCore/cache.h"
23 #include "MagickCore/cache-view.h"
24 #include "MagickCore/color.h"
25 #include "MagickCore/colorspace.h"
26 #include "MagickCore/gem.h"
27 #include "MagickCore/image.h"
28 #include "MagickCore/memory_.h"
29 
30 #if defined(__cplusplus) || defined(c_plusplus)
31 extern "C" {
32 #endif
33 
34 #undef index
35 
ClampPixel(const MagickRealType pixel)36 static inline Quantum ClampPixel(const MagickRealType pixel)
37 {
38   if (pixel < 0.0f)
39     return((Quantum) 0);
40   if (pixel >= (MagickRealType) QuantumRange)
41     return((Quantum) QuantumRange);
42 #if !defined(MAGICKCORE_HDRI_SUPPORT)
43   return((Quantum) (pixel+0.5f));
44 #else
45   return((Quantum) pixel);
46 #endif
47 }
48 
GetPixela(const Image * magick_restrict image,const Quantum * magick_restrict pixel)49 static inline Quantum GetPixela(const Image *magick_restrict image,
50   const Quantum *magick_restrict pixel)
51 {
52   return(pixel[image->channel_map[aPixelChannel].offset]);
53 }
54 
GetPixelAlpha(const Image * magick_restrict image,const Quantum * magick_restrict pixel)55 static inline Quantum GetPixelAlpha(const Image *magick_restrict image,
56   const Quantum *magick_restrict pixel)
57 {
58   if (image->channel_map[AlphaPixelChannel].traits == UndefinedPixelTrait)
59     return(OpaqueAlpha);
60   return(pixel[image->channel_map[AlphaPixelChannel].offset]);
61 }
62 
GetPixelAlphaTraits(const Image * magick_restrict image)63 static inline PixelTrait GetPixelAlphaTraits(
64   const Image *magick_restrict image)
65 {
66   return(image->channel_map[AlphaPixelChannel].traits);
67 }
68 
GetPixelb(const Image * magick_restrict image,const Quantum * magick_restrict pixel)69 static inline Quantum GetPixelb(const Image *magick_restrict image,
70   const Quantum *magick_restrict pixel)
71 {
72   return(pixel[image->channel_map[bPixelChannel].offset]);
73 }
74 
GetPixelBlack(const Image * magick_restrict image,const Quantum * magick_restrict pixel)75 static inline Quantum GetPixelBlack(const Image *magick_restrict image,
76   const Quantum *magick_restrict pixel)
77 {
78   if (image->channel_map[BlackPixelChannel].traits == UndefinedPixelTrait)
79     return((Quantum) 0);
80   return(pixel[image->channel_map[BlackPixelChannel].offset]);
81 }
82 
GetPixelBlackTraits(const Image * magick_restrict image)83 static inline PixelTrait GetPixelBlackTraits(
84   const Image *magick_restrict image)
85 {
86   return(image->channel_map[BlackPixelChannel].traits);
87 }
88 
GetPixelBlue(const Image * magick_restrict image,const Quantum * magick_restrict pixel)89 static inline Quantum GetPixelBlue(const Image *magick_restrict image,
90   const Quantum *magick_restrict pixel)
91 {
92   return(pixel[image->channel_map[BluePixelChannel].offset]);
93 }
94 
GetPixelBlueTraits(const Image * magick_restrict image)95 static inline PixelTrait GetPixelBlueTraits(const Image *magick_restrict image)
96 {
97   return(image->channel_map[BluePixelChannel].traits);
98 }
99 
GetPixelCb(const Image * magick_restrict image,const Quantum * magick_restrict pixel)100 static inline Quantum GetPixelCb(const Image *magick_restrict image,
101   const Quantum *magick_restrict pixel)
102 {
103   return(pixel[image->channel_map[CbPixelChannel].offset]);
104 }
105 
GetPixelCbTraits(const Image * magick_restrict image)106 static inline PixelTrait GetPixelCbTraits(const Image *magick_restrict image)
107 {
108   return(image->channel_map[CbPixelChannel].traits);
109 }
110 
GetPixelChannel(const Image * magick_restrict image,const PixelChannel channel,const Quantum * magick_restrict pixel)111 static inline Quantum GetPixelChannel(const Image *magick_restrict image,
112   const PixelChannel channel,const Quantum *magick_restrict pixel)
113 {
114   if (image->channel_map[channel].traits == UndefinedPixelTrait)
115     return((Quantum) 0);
116   return(pixel[image->channel_map[channel].offset]);
117 }
118 
GetPixelChannelChannel(const Image * magick_restrict image,const ssize_t offset)119 static inline PixelChannel GetPixelChannelChannel(
120   const Image *magick_restrict image,const ssize_t offset)
121 {
122   return(image->channel_map[offset].channel);
123 }
124 
GetPixelChannelOffset(const Image * magick_restrict image,const PixelChannel channel)125 static inline ssize_t GetPixelChannelOffset(const Image *magick_restrict image,
126   const PixelChannel channel)
127 {
128   return(image->channel_map[channel].offset);
129 }
130 
GetPixelChannelTraits(const Image * magick_restrict image,const PixelChannel channel)131 static inline PixelTrait GetPixelChannelTraits(
132   const Image *magick_restrict image,const PixelChannel channel)
133 {
134   return(image->channel_map[channel].traits);
135 }
136 
GetPixelChannels(const Image * magick_restrict image)137 static inline size_t GetPixelChannels(const Image *magick_restrict image)
138 {
139   return(image->number_channels);
140 }
141 
GetPixelCompositeMask(const Image * magick_restrict image,const Quantum * magick_restrict pixel)142 static inline Quantum GetPixelCompositeMask(const Image *magick_restrict image,
143   const Quantum *magick_restrict pixel)
144 {
145   if (image->channel_map[CompositeMaskPixelChannel].traits == UndefinedPixelTrait)
146     return((Quantum) QuantumRange);
147   return(pixel[image->channel_map[CompositeMaskPixelChannel].offset]);
148 }
149 
GetPixelCr(const Image * magick_restrict image,const Quantum * magick_restrict pixel)150 static inline Quantum GetPixelCr(const Image *magick_restrict image,
151   const Quantum *magick_restrict pixel)
152 {
153   return(pixel[image->channel_map[CrPixelChannel].offset]);
154 }
155 
GetPixelCrTraits(const Image * magick_restrict image)156 static inline PixelTrait GetPixelCrTraits(const Image *magick_restrict image)
157 {
158   return(image->channel_map[CrPixelChannel].traits);
159 }
160 
GetPixelCyan(const Image * magick_restrict image,const Quantum * magick_restrict pixel)161 static inline Quantum GetPixelCyan(const Image *magick_restrict image,
162   const Quantum *magick_restrict pixel)
163 {
164   return(pixel[image->channel_map[CyanPixelChannel].offset]);
165 }
166 
GetPixelCyanTraits(const Image * magick_restrict image)167 static inline PixelTrait GetPixelCyanTraits(const Image *magick_restrict image)
168 {
169   return(image->channel_map[CyanPixelChannel].traits);
170 }
171 
GetPixelGray(const Image * magick_restrict image,const Quantum * magick_restrict pixel)172 static inline Quantum GetPixelGray(const Image *magick_restrict image,
173   const Quantum *magick_restrict pixel)
174 {
175   return(pixel[image->channel_map[GrayPixelChannel].offset]);
176 }
177 
GetPixelGrayTraits(const Image * magick_restrict image)178 static inline PixelTrait GetPixelGrayTraits(const Image *magick_restrict image)
179 {
180   return(image->channel_map[GrayPixelChannel].traits);
181 }
182 
GetPixelGreen(const Image * magick_restrict image,const Quantum * magick_restrict pixel)183 static inline Quantum GetPixelGreen(const Image *magick_restrict image,
184   const Quantum *magick_restrict pixel)
185 {
186   return(pixel[image->channel_map[GreenPixelChannel].offset]);
187 }
188 
GetPixelGreenTraits(const Image * magick_restrict image)189 static inline PixelTrait GetPixelGreenTraits(
190   const Image *magick_restrict image)
191 {
192   return(image->channel_map[GreenPixelChannel].traits);
193 }
194 
GetPixelIndex(const Image * magick_restrict image,const Quantum * magick_restrict pixel)195 static inline Quantum GetPixelIndex(const Image *magick_restrict image,
196   const Quantum *magick_restrict pixel)
197 {
198   if (image->channel_map[IndexPixelChannel].traits == UndefinedPixelTrait)
199     return((Quantum) 0);
200   return(pixel[image->channel_map[IndexPixelChannel].offset]);
201 }
202 
GetPixelIndexTraits(const Image * magick_restrict image)203 static inline PixelTrait GetPixelIndexTraits(
204   const Image *magick_restrict image)
205 {
206   return(image->channel_map[IndexPixelChannel].traits);
207 }
208 
GetPixelInfoChannel(const PixelInfo * magick_restrict pixel_info,const PixelChannel channel)209 static inline MagickRealType GetPixelInfoChannel(
210   const PixelInfo *magick_restrict pixel_info,const PixelChannel channel)
211 {
212   switch (channel)
213   {
214     case RedPixelChannel: return(pixel_info->red);
215     case GreenPixelChannel: return(pixel_info->green);
216     case BluePixelChannel: return(pixel_info->blue);
217     case BlackPixelChannel: return(pixel_info->black);
218     case AlphaPixelChannel: return(pixel_info->alpha);
219     case IndexPixelChannel: return(pixel_info->index);
220     default: return((MagickRealType) 0.0);
221   }
222 }
223 
PerceptibleReciprocal(const double x)224 static inline double PerceptibleReciprocal(const double x)
225 {
226   double
227     sign;
228 
229   /*
230     Return 1/x where x is perceptible (not unlimited or infinitesimal).
231   */
232   sign=x < 0.0 ? -1.0 : 1.0;
233   if ((sign*x) >= MagickEpsilon)
234     return(1.0/x);
235   return(sign/MagickEpsilon);
236 }
237 
GetPixelInfoLuma(const PixelInfo * magick_restrict pixel)238 static inline MagickRealType GetPixelInfoLuma(
239   const PixelInfo *magick_restrict pixel)
240 {
241   MagickRealType
242     intensity;
243 
244   if (pixel->colorspace == sRGBColorspace)
245     {
246       intensity=(MagickRealType) (0.212656f*pixel->red+0.715158f*pixel->green+
247         0.072186f*pixel->blue);
248       return(intensity);
249     }
250   intensity=(MagickRealType) (0.212656f*EncodePixelGamma(pixel->red)+
251     0.715158f*EncodePixelGamma(pixel->green)+
252     0.072186f*EncodePixelGamma(pixel->blue));
253   return(intensity);
254 }
255 
GetPixelInfoLuminance(const PixelInfo * magick_restrict pixel)256 static inline MagickRealType GetPixelInfoLuminance(
257   const PixelInfo *magick_restrict pixel)
258 {
259   MagickRealType
260     intensity;
261 
262   if (pixel->colorspace != sRGBColorspace)
263     {
264       intensity=(MagickRealType) (0.212656f*pixel->red+0.715158f*pixel->green+
265         0.072186f*pixel->blue);
266       return(intensity);
267     }
268   intensity=(MagickRealType) (0.212656f*DecodePixelGamma(pixel->red)+
269     0.715158f*DecodePixelGamma(pixel->green)+
270     0.072186f*DecodePixelGamma(pixel->blue));
271   return(intensity);
272 }
273 
GetPixelL(const Image * magick_restrict image,const Quantum * magick_restrict pixel)274 static inline Quantum GetPixelL(const Image *magick_restrict image,
275   const Quantum *magick_restrict pixel)
276 {
277   return(pixel[image->channel_map[LPixelChannel].offset]);
278 }
279 
GetPixelLabel(const Image * magick_restrict image,const Quantum * magick_restrict pixel)280 static inline ssize_t GetPixelLabel(const Image *magick_restrict image,
281   const Quantum *magick_restrict pixel)
282 {
283   return((ssize_t) pixel[image->channel_map[LabelPixelChannel].offset]);
284 }
285 
GetPixelLuma(const Image * magick_restrict image,const Quantum * magick_restrict pixel)286 static inline MagickRealType GetPixelLuma(const Image *magick_restrict image,
287   const Quantum *magick_restrict pixel)
288 {
289   MagickRealType
290     intensity;
291 
292   intensity=(MagickRealType) (
293     0.212656f*pixel[image->channel_map[RedPixelChannel].offset]+
294     0.715158f*pixel[image->channel_map[GreenPixelChannel].offset]+
295     0.072186f*pixel[image->channel_map[BluePixelChannel].offset]);
296   return(intensity);
297 }
298 
GetPixelLuminance(const Image * magick_restrict image,const Quantum * magick_restrict pixel)299 static inline MagickRealType GetPixelLuminance(
300   const Image *magick_restrict image,const Quantum *magick_restrict pixel)
301 {
302   MagickRealType
303     intensity;
304 
305   if (image->colorspace != sRGBColorspace)
306     {
307       intensity=(MagickRealType) (
308         0.212656f*pixel[image->channel_map[RedPixelChannel].offset]+
309         0.715158f*pixel[image->channel_map[GreenPixelChannel].offset]+
310         0.072186f*pixel[image->channel_map[BluePixelChannel].offset]);
311       return(intensity);
312     }
313   intensity=(MagickRealType) (0.212656f*DecodePixelGamma((MagickRealType)
314     pixel[image->channel_map[RedPixelChannel].offset])+0.715158f*
315     DecodePixelGamma((MagickRealType)
316     pixel[image->channel_map[GreenPixelChannel].offset])+0.072186f*
317     DecodePixelGamma((MagickRealType)
318     pixel[image->channel_map[BluePixelChannel].offset]));
319   return(intensity);
320 }
321 
GetPixelMagenta(const Image * magick_restrict image,const Quantum * magick_restrict pixel)322 static inline Quantum GetPixelMagenta(const Image *magick_restrict image,
323   const Quantum *magick_restrict pixel)
324 {
325   return(pixel[image->channel_map[MagentaPixelChannel].offset]);
326 }
327 
GetPixelMagentaTraits(const Image * magick_restrict image)328 static inline PixelTrait GetPixelMagentaTraits(
329   const Image *magick_restrict image)
330 {
331   return(image->channel_map[MagentaPixelChannel].traits);
332 }
333 
GetPixelReadMask(const Image * magick_restrict image,const Quantum * magick_restrict pixel)334 static inline Quantum GetPixelReadMask(const Image *magick_restrict image,
335   const Quantum *magick_restrict pixel)
336 {
337   if (image->channel_map[ReadMaskPixelChannel].traits == UndefinedPixelTrait)
338     return((Quantum) QuantumRange);
339   return(pixel[image->channel_map[ReadMaskPixelChannel].offset]);
340 }
341 
GetPixelWriteMask(const Image * magick_restrict image,const Quantum * magick_restrict pixel)342 static inline Quantum GetPixelWriteMask(const Image *magick_restrict image,
343   const Quantum *magick_restrict pixel)
344 {
345   if (image->channel_map[WriteMaskPixelChannel].traits == UndefinedPixelTrait)
346     return((Quantum) QuantumRange);
347   return(pixel[image->channel_map[WriteMaskPixelChannel].offset]);
348 }
349 
GetPixelReadMaskTraits(const Image * magick_restrict image)350 static inline PixelTrait GetPixelReadMaskTraits(
351   const Image *magick_restrict image)
352 {
353   return(image->channel_map[ReadMaskPixelChannel].traits);
354 }
355 
GetPixelMetaChannels(const Image * magick_restrict image)356 static inline size_t GetPixelMetaChannels(const Image *magick_restrict image)
357 {
358   return(image->number_meta_channels);
359 }
360 
GetPixelMetacontentExtent(const Image * magick_restrict image)361 static inline size_t GetPixelMetacontentExtent(
362   const Image *magick_restrict image)
363 {
364   return(image->metacontent_extent);
365 }
366 
GetPixelOpacity(const Image * magick_restrict image,const Quantum * magick_restrict pixel)367 static inline Quantum GetPixelOpacity(const Image *magick_restrict image,
368   const Quantum *magick_restrict pixel)
369 {
370   if (image->channel_map[AlphaPixelChannel].traits != BlendPixelTrait)
371     return(QuantumRange-OpaqueAlpha);
372   return(QuantumRange-pixel[image->channel_map[AlphaPixelChannel].offset]);
373 }
374 
GetPixelRed(const Image * magick_restrict image,const Quantum * magick_restrict pixel)375 static inline Quantum GetPixelRed(const Image *magick_restrict image,
376   const Quantum *magick_restrict pixel)
377 {
378   return(pixel[image->channel_map[RedPixelChannel].offset]);
379 }
380 
GetPixelRedTraits(const Image * magick_restrict image)381 static inline PixelTrait GetPixelRedTraits(const Image *magick_restrict image)
382 {
383   return(image->channel_map[RedPixelChannel].traits);
384 }
385 
GetPixelInfoPixel(const Image * magick_restrict image,const Quantum * magick_restrict pixel,PixelInfo * magick_restrict pixel_info)386 static inline void GetPixelInfoPixel(const Image *magick_restrict image,
387   const Quantum *magick_restrict pixel,PixelInfo *magick_restrict pixel_info)
388 {
389   (void) ResetMagickMemory(pixel_info,0,sizeof(*pixel_info));
390   pixel_info->storage_class=DirectClass;
391   pixel_info->colorspace=sRGBColorspace;
392   pixel_info->depth=MAGICKCORE_QUANTUM_DEPTH;
393   pixel_info->alpha_trait=UndefinedPixelTrait;
394   pixel_info->alpha=(MagickRealType) OpaqueAlpha;
395   if (image != (Image *) NULL)
396     {
397       pixel_info->storage_class=image->storage_class;
398       pixel_info->colorspace=image->colorspace;
399       pixel_info->fuzz=image->fuzz;
400       pixel_info->depth=image->depth;
401       pixel_info->alpha_trait=image->alpha_trait;
402       if (pixel != (Quantum *) NULL)
403         {
404           pixel_info->red=(MagickRealType)
405             pixel[image->channel_map[RedPixelChannel].offset];
406           pixel_info->green=(MagickRealType)
407             pixel[image->channel_map[GreenPixelChannel].offset];
408           pixel_info->blue=(MagickRealType)
409             pixel[image->channel_map[BluePixelChannel].offset];
410           if (image->channel_map[BlackPixelChannel].traits != UndefinedPixelTrait)
411             pixel_info->black=(MagickRealType)
412               pixel[image->channel_map[BlackPixelChannel].offset];
413           if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
414             {
415               pixel_info->alpha=(MagickRealType)
416                 pixel[image->channel_map[AlphaPixelChannel].offset];
417               pixel_info->alpha_trait=BlendPixelTrait;
418             }
419           if (image->channel_map[IndexPixelChannel].traits != UndefinedPixelTrait)
420             pixel_info->index=(MagickRealType)
421           pixel[image->channel_map[IndexPixelChannel].offset];
422         }
423     }
424 }
425 
GetPixelTraits(const Image * magick_restrict image,const PixelChannel channel)426 static inline PixelTrait GetPixelTraits(const Image *magick_restrict image,
427   const PixelChannel channel)
428 {
429   return(image->channel_map[channel].traits);
430 }
431 
GetPixelY(const Image * magick_restrict image,const Quantum * magick_restrict pixel)432 static inline Quantum GetPixelY(const Image *magick_restrict image,
433   const Quantum *magick_restrict pixel)
434 {
435   return(pixel[image->channel_map[YPixelChannel].offset]);
436 }
437 
GetPixelYTraits(const Image * magick_restrict image)438 static inline PixelTrait GetPixelYTraits(const Image *magick_restrict image)
439 {
440   return(image->channel_map[YPixelChannel].traits);
441 }
442 
GetPixelYellow(const Image * magick_restrict image,const Quantum * magick_restrict pixel)443 static inline Quantum GetPixelYellow(const Image *magick_restrict image,
444   const Quantum *magick_restrict pixel)
445 {
446   return(pixel[image->channel_map[YellowPixelChannel].offset]);
447 }
448 
GetPixelYellowTraits(const Image * magick_restrict image)449 static inline PixelTrait GetPixelYellowTraits(
450   const Image *magick_restrict image)
451 {
452   return(image->channel_map[YellowPixelChannel].traits);
453 }
454 
AbsolutePixelValue(const MagickRealType x)455 static inline MagickRealType AbsolutePixelValue(const MagickRealType x)
456 {
457   return(x < 0.0f ? -x : x);
458 }
459 
IsPixelAtDepth(const Quantum pixel,const QuantumAny range)460 static inline MagickBooleanType IsPixelAtDepth(const Quantum pixel,
461   const QuantumAny range)
462 {
463   Quantum
464     quantum;
465 
466   if (range == 0)
467     return(MagickTrue);
468 #if !defined(MAGICKCORE_HDRI_SUPPORT)
469   quantum=(Quantum) (((MagickRealType) QuantumRange*((QuantumAny)
470     (((MagickRealType) range*pixel)/QuantumRange+0.5)))/range+0.5);
471 #else
472   quantum=(Quantum) (((MagickRealType) QuantumRange*((QuantumAny)
473     (((MagickRealType) range*pixel)/QuantumRange+0.5)))/range);
474 #endif
475   return(pixel == quantum ? MagickTrue : MagickFalse);
476 }
477 
IsPixelEquivalent(const Image * magick_restrict image,const Quantum * magick_restrict p,const PixelInfo * magick_restrict q)478 static inline MagickBooleanType IsPixelEquivalent(
479   const Image *magick_restrict image,const Quantum *magick_restrict p,
480   const PixelInfo *magick_restrict q)
481 {
482   MagickRealType
483     alpha,
484     beta,
485     color;
486 
487   color=(MagickRealType) p[image->channel_map[AlphaPixelChannel].offset];
488   alpha=image->alpha_trait == UndefinedPixelTrait ? (MagickRealType)
489     OpaqueAlpha : color;
490   beta=q->alpha_trait == UndefinedPixelTrait ? (MagickRealType) OpaqueAlpha :
491     q->alpha;
492   if (AbsolutePixelValue(alpha-beta) >= MagickEpsilon)
493     return(MagickFalse);
494   if ((AbsolutePixelValue(alpha-TransparentAlpha) < MagickEpsilon) ||
495       (AbsolutePixelValue(beta-TransparentAlpha) < MagickEpsilon))
496     return(MagickTrue);  /* no color component if pixel is transparent */
497   color=(MagickRealType) p[image->channel_map[RedPixelChannel].offset];
498   if (AbsolutePixelValue(color-q->red) >= MagickEpsilon)
499     return(MagickFalse);
500   color=(MagickRealType) p[image->channel_map[GreenPixelChannel].offset];
501   if (AbsolutePixelValue(color-q->green) >= MagickEpsilon)
502     return(MagickFalse);
503   color=(MagickRealType) p[image->channel_map[BluePixelChannel].offset];
504   if (AbsolutePixelValue(color-q->blue) >= MagickEpsilon)
505     return(MagickFalse);
506   if (image->colorspace == CMYKColorspace)
507     {
508       color=(MagickRealType) p[image->channel_map[BlackPixelChannel].offset];
509       if (AbsolutePixelValue(color-q->black) >= MagickEpsilon)
510         return(MagickFalse);
511     }
512   return(MagickTrue);
513 }
514 
IsPixelGray(const Image * magick_restrict image,const Quantum * magick_restrict pixel)515 static inline MagickBooleanType IsPixelGray(const Image *magick_restrict image,
516   const Quantum *magick_restrict pixel)
517 {
518   MagickRealType
519     green_blue,
520     red_green;
521 
522   red_green=(MagickRealType) pixel[image->channel_map[RedPixelChannel].offset]-
523     pixel[image->channel_map[GreenPixelChannel].offset];
524   green_blue=(MagickRealType)
525     pixel[image->channel_map[GreenPixelChannel].offset]-
526     pixel[image->channel_map[BluePixelChannel].offset];
527   if ((AbsolutePixelValue(red_green) < MagickEpsilon) &&
528       (AbsolutePixelValue(green_blue) < MagickEpsilon))
529     return(MagickTrue);
530   return(MagickFalse);
531 }
532 
IsPixelInfoEquivalent(const PixelInfo * magick_restrict p,const PixelInfo * magick_restrict q)533 static inline MagickBooleanType IsPixelInfoEquivalent(
534   const PixelInfo *magick_restrict p,const PixelInfo *magick_restrict q)
535 {
536   MagickRealType
537     alpha,
538     beta;
539 
540   alpha=p->alpha_trait == UndefinedPixelTrait ? (MagickRealType) OpaqueAlpha :
541     p->alpha;
542   beta=q->alpha_trait == UndefinedPixelTrait ? (MagickRealType) OpaqueAlpha :
543     q->alpha;
544   if (AbsolutePixelValue(alpha-beta) >= MagickEpsilon)
545     return(MagickFalse);
546   if ((AbsolutePixelValue(alpha-TransparentAlpha) < MagickEpsilon) ||
547       (AbsolutePixelValue(beta-TransparentAlpha) < MagickEpsilon))
548     return(MagickTrue);  /* no color component if pixel is transparent */
549   if (AbsolutePixelValue(p->red-q->red) >= MagickEpsilon)
550     return(MagickFalse);
551   if (AbsolutePixelValue(p->green-q->green) >= MagickEpsilon)
552     return(MagickFalse);
553   if (AbsolutePixelValue(p->blue-q->blue) >= MagickEpsilon)
554     return(MagickFalse);
555   if (p->colorspace == CMYKColorspace)
556     {
557       if (AbsolutePixelValue(p->black-q->black) >= MagickEpsilon)
558         return(MagickFalse);
559     }
560   return(MagickTrue);
561 }
562 
IsPixelMonochrome(const Image * magick_restrict image,const Quantum * magick_restrict pixel)563 static inline MagickBooleanType IsPixelMonochrome(
564   const Image *magick_restrict image,const Quantum *magick_restrict pixel)
565 {
566   MagickRealType
567     green_blue,
568     red,
569     red_green;
570 
571   red=(MagickRealType) pixel[image->channel_map[RedPixelChannel].offset];
572   if ((AbsolutePixelValue(red) >= MagickEpsilon) &&
573       (AbsolutePixelValue(red-QuantumRange) >= MagickEpsilon))
574     return(MagickFalse);
575   red_green=(MagickRealType) pixel[image->channel_map[RedPixelChannel].offset]-
576     pixel[image->channel_map[GreenPixelChannel].offset];
577   green_blue=(MagickRealType)
578     pixel[image->channel_map[GreenPixelChannel].offset]-
579     pixel[image->channel_map[BluePixelChannel].offset];
580   if ((AbsolutePixelValue(red_green) < MagickEpsilon) &&
581       (AbsolutePixelValue(green_blue) < MagickEpsilon))
582     return(MagickTrue);
583   return(MagickFalse);
584 }
585 
IsPixelInfoGray(const PixelInfo * magick_restrict pixel)586 static inline MagickBooleanType IsPixelInfoGray(
587   const PixelInfo *magick_restrict pixel)
588 {
589   if ((AbsolutePixelValue(pixel->red-pixel->green) < MagickEpsilon) &&
590       (AbsolutePixelValue(pixel->green-pixel->blue) < MagickEpsilon))
591     return(MagickTrue);
592   return(MagickFalse);
593 }
594 
IsPixelInfoMonochrome(const PixelInfo * magick_restrict pixel_info)595 static inline MagickBooleanType IsPixelInfoMonochrome(
596   const PixelInfo *magick_restrict pixel_info)
597 {
598   MagickRealType
599     green_blue,
600     red_green;
601 
602   if ((AbsolutePixelValue(pixel_info->red) >= MagickEpsilon) ||
603       (AbsolutePixelValue(pixel_info->red-QuantumRange) >= MagickEpsilon))
604     return(MagickFalse);
605   red_green=pixel_info->red-pixel_info->green;
606   green_blue=pixel_info->green-pixel_info->blue;
607   if ((AbsolutePixelValue(red_green) < MagickEpsilon) &&
608       (AbsolutePixelValue(green_blue) < MagickEpsilon))
609     return(MagickTrue);
610   return(MagickFalse);
611 }
612 
SetPixela(const Image * magick_restrict image,const Quantum a,Quantum * magick_restrict pixel)613 static inline void SetPixela(const Image *magick_restrict image,
614   const Quantum a,Quantum *magick_restrict pixel)
615 {
616   if (image->channel_map[aPixelChannel].traits != UndefinedPixelTrait)
617     pixel[image->channel_map[aPixelChannel].offset]=a;
618 }
619 
SetPixelAlpha(const Image * magick_restrict image,const Quantum alpha,Quantum * magick_restrict pixel)620 static inline void SetPixelAlpha(const Image *magick_restrict image,
621   const Quantum alpha,Quantum *magick_restrict pixel)
622 {
623   if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
624     pixel[image->channel_map[AlphaPixelChannel].offset]=alpha;
625 }
626 
SetPixelAlphaTraits(Image * image,const PixelTrait traits)627 static inline void SetPixelAlphaTraits(Image *image,const PixelTrait traits)
628 {
629   image->channel_map[AlphaPixelChannel].traits=traits;
630 }
631 
SetPixelb(const Image * magick_restrict image,const Quantum b,Quantum * magick_restrict pixel)632 static inline void SetPixelb(const Image *magick_restrict image,
633   const Quantum b,Quantum *magick_restrict pixel)
634 {
635   if (image->channel_map[bPixelChannel].traits != UndefinedPixelTrait)
636     pixel[image->channel_map[bPixelChannel].offset]=b;
637 }
638 
SetPixelBackgoundColor(const Image * magick_restrict image,Quantum * magick_restrict pixel)639 static inline void SetPixelBackgoundColor(const Image *magick_restrict image,
640   Quantum *magick_restrict pixel)
641 {
642   ssize_t
643     i;
644 
645   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
646     pixel[i]=(Quantum) 0;
647   pixel[image->channel_map[RedPixelChannel].offset]=
648     ClampToQuantum(image->background_color.red);
649   pixel[image->channel_map[GreenPixelChannel].offset]=
650     ClampToQuantum(image->background_color.green);
651   pixel[image->channel_map[BluePixelChannel].offset]=
652     ClampToQuantum(image->background_color.blue);
653   if (image->channel_map[BlackPixelChannel].traits != UndefinedPixelTrait)
654     pixel[image->channel_map[BlackPixelChannel].offset]=
655       ClampToQuantum(image->background_color.black);
656   if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
657     pixel[image->channel_map[AlphaPixelChannel].offset]=
658       image->background_color.alpha_trait == UndefinedPixelTrait ? OpaqueAlpha :
659       ClampToQuantum(image->background_color.alpha);
660 }
661 
SetPixelBlack(const Image * magick_restrict image,const Quantum black,Quantum * magick_restrict pixel)662 static inline void SetPixelBlack(const Image *magick_restrict image,
663   const Quantum black,Quantum *magick_restrict pixel)
664 {
665   if (image->channel_map[BlackPixelChannel].traits != UndefinedPixelTrait)
666     pixel[image->channel_map[BlackPixelChannel].offset]=black;
667 }
668 
SetPixelBlackTraits(Image * image,const PixelTrait traits)669 static inline void SetPixelBlackTraits(Image *image,const PixelTrait traits)
670 {
671   image->channel_map[BlackPixelChannel].traits=traits;
672 }
673 
SetPixelBlue(const Image * magick_restrict image,const Quantum blue,Quantum * magick_restrict pixel)674 static inline void SetPixelBlue(const Image *magick_restrict image,
675   const Quantum blue,Quantum *magick_restrict pixel)
676 {
677   pixel[image->channel_map[BluePixelChannel].offset]=blue;
678 }
679 
SetPixelBlueTraits(Image * image,const PixelTrait traits)680 static inline void SetPixelBlueTraits(Image *image,const PixelTrait traits)
681 {
682   image->channel_map[BluePixelChannel].traits=traits;
683 }
684 
SetPixelCb(const Image * magick_restrict image,const Quantum cb,Quantum * magick_restrict pixel)685 static inline void SetPixelCb(const Image *magick_restrict image,
686   const Quantum cb,Quantum *magick_restrict pixel)
687 {
688   pixel[image->channel_map[CbPixelChannel].offset]=cb;
689 }
690 
SetPixelCbTraits(Image * image,const PixelTrait traits)691 static inline void SetPixelCbTraits(Image *image,const PixelTrait traits)
692 {
693   image->channel_map[CbPixelChannel].traits=traits;
694 }
695 
SetPixelChannel(const Image * magick_restrict image,const PixelChannel channel,const Quantum quantum,Quantum * magick_restrict pixel)696 static inline void SetPixelChannel(const Image *magick_restrict image,
697   const PixelChannel channel,const Quantum quantum,
698   Quantum *magick_restrict pixel)
699 {
700   if (image->channel_map[channel].traits != UndefinedPixelTrait)
701     pixel[image->channel_map[channel].offset]=quantum;
702 }
703 
SetPixelChannelAttributes(const Image * magick_restrict image,const PixelChannel channel,const PixelTrait traits,const ssize_t offset)704 static inline void SetPixelChannelAttributes(
705   const Image *magick_restrict image,const PixelChannel channel,
706   const PixelTrait traits,const ssize_t offset)
707 {
708   assert((ssize_t) channel < MaxPixelChannels);
709   assert(offset < MaxPixelChannels);
710   image->channel_map[offset].channel=channel;
711   image->channel_map[channel].offset=offset;
712   image->channel_map[channel].traits=traits;
713 }
714 
SetPixelChannelChannel(const Image * magick_restrict image,const PixelChannel channel,const ssize_t offset)715 static inline void SetPixelChannelChannel(const Image *magick_restrict image,
716   const PixelChannel channel,const ssize_t offset)
717 {
718   image->channel_map[offset].channel=channel;
719   image->channel_map[channel].offset=offset;
720 }
721 
SetPixelChannels(Image * image,const size_t number_channels)722 static inline void SetPixelChannels(Image *image,const size_t number_channels)
723 {
724   image->number_channels=number_channels;
725 }
726 
SetPixelChannelTraits(Image * image,const PixelChannel channel,const PixelTrait traits)727 static inline void SetPixelChannelTraits(Image *image,
728   const PixelChannel channel,const PixelTrait traits)
729 {
730   image->channel_map[channel].traits=traits;
731 }
732 
SetPixelCompositeMask(const Image * magick_restrict image,const Quantum mask,Quantum * magick_restrict pixel)733 static inline void SetPixelCompositeMask(const Image *magick_restrict image,
734   const Quantum mask,Quantum *magick_restrict pixel)
735 {
736   if (image->channel_map[CompositeMaskPixelChannel].traits != UndefinedPixelTrait)
737     pixel[image->channel_map[CompositeMaskPixelChannel].offset]=mask;
738 }
739 
SetPixelCr(const Image * magick_restrict image,const Quantum cr,Quantum * magick_restrict pixel)740 static inline void SetPixelCr(const Image *magick_restrict image,
741   const Quantum cr,Quantum *magick_restrict pixel)
742 {
743   pixel[image->channel_map[CrPixelChannel].offset]=cr;
744 }
745 
SetPixelCrTraits(Image * image,const PixelTrait traits)746 static inline void SetPixelCrTraits(Image *image,const PixelTrait traits)
747 {
748   image->channel_map[CrPixelChannel].traits=traits;
749 }
750 
SetPixelCyan(const Image * magick_restrict image,const Quantum cyan,Quantum * magick_restrict pixel)751 static inline void SetPixelCyan(const Image *magick_restrict image,
752   const Quantum cyan,Quantum *magick_restrict pixel)
753 {
754   pixel[image->channel_map[CyanPixelChannel].offset]=cyan;
755 }
756 
SetPixelGray(const Image * magick_restrict image,const Quantum gray,Quantum * magick_restrict pixel)757 static inline void SetPixelGray(const Image *magick_restrict image,
758   const Quantum gray,Quantum *magick_restrict pixel)
759 {
760   pixel[image->channel_map[GrayPixelChannel].offset]=gray;
761 }
762 
SetPixelGrayTraits(Image * image,const PixelTrait traits)763 static inline void SetPixelGrayTraits(Image *image,const PixelTrait traits)
764 {
765   image->channel_map[GrayPixelChannel].traits=traits;
766 }
767 
SetPixelGreen(const Image * magick_restrict image,const Quantum green,Quantum * magick_restrict pixel)768 static inline void SetPixelGreen(const Image *magick_restrict image,
769   const Quantum green,Quantum *magick_restrict pixel)
770 {
771   pixel[image->channel_map[GreenPixelChannel].offset]=green;
772 }
773 
SetPixelGreenTraits(Image * image,const PixelTrait traits)774 static inline void SetPixelGreenTraits(Image *image,const PixelTrait traits)
775 {
776   image->channel_map[GreenPixelChannel].traits=traits;
777 }
778 
SetPixelIndex(const Image * magick_restrict image,const Quantum index,Quantum * magick_restrict pixel)779 static inline void SetPixelIndex(const Image *magick_restrict image,
780   const Quantum index,Quantum *magick_restrict pixel)
781 {
782   if (image->channel_map[IndexPixelChannel].traits != UndefinedPixelTrait)
783     pixel[image->channel_map[IndexPixelChannel].offset]=index;
784 }
785 
SetPixelIndexTraits(Image * image,const PixelTrait traits)786 static inline void SetPixelIndexTraits(Image *image,const PixelTrait traits)
787 {
788   image->channel_map[IndexPixelChannel].traits=traits;
789 }
790 
SetPixelViaPixelInfo(const Image * magick_restrict image,const PixelInfo * magick_restrict pixel_info,Quantum * magick_restrict pixel)791 static inline void SetPixelViaPixelInfo(const Image *magick_restrict image,
792   const PixelInfo *magick_restrict pixel_info,Quantum *magick_restrict pixel)
793 {
794   pixel[image->channel_map[RedPixelChannel].offset]=
795     ClampToQuantum(pixel_info->red);
796   pixel[image->channel_map[GreenPixelChannel].offset]=
797     ClampToQuantum(pixel_info->green);
798   pixel[image->channel_map[BluePixelChannel].offset]=
799     ClampToQuantum(pixel_info->blue);
800   if (image->channel_map[BlackPixelChannel].traits != UndefinedPixelTrait)
801     pixel[image->channel_map[BlackPixelChannel].offset]=
802       ClampToQuantum(pixel_info->black);
803   if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
804     pixel[image->channel_map[AlphaPixelChannel].offset]=
805       pixel_info->alpha_trait == UndefinedPixelTrait ? OpaqueAlpha :
806       ClampToQuantum(pixel_info->alpha);
807 }
808 
SetPixelL(const Image * magick_restrict image,const Quantum L,Quantum * magick_restrict pixel)809 static inline void SetPixelL(const Image *magick_restrict image,const Quantum L,
810   Quantum *magick_restrict pixel)
811 {
812   if (image->channel_map[LPixelChannel].traits != UndefinedPixelTrait)
813     pixel[image->channel_map[LPixelChannel].offset]=L;
814 }
815 
SetPixelMagenta(const Image * magick_restrict image,const Quantum magenta,Quantum * magick_restrict pixel)816 static inline void SetPixelMagenta(const Image *magick_restrict image,
817   const Quantum magenta,Quantum *magick_restrict pixel)
818 {
819   pixel[image->channel_map[MagentaPixelChannel].offset]=magenta;
820 }
821 
SetPixelMagentaTraits(Image * image,const PixelTrait traits)822 static inline void SetPixelMagentaTraits(Image *image,const PixelTrait traits)
823 {
824   image->channel_map[MagentaPixelChannel].traits=traits;
825 }
826 
SetPixelReadMask(const Image * magick_restrict image,const Quantum mask,Quantum * magick_restrict pixel)827 static inline void SetPixelReadMask(const Image *magick_restrict image,
828   const Quantum mask,Quantum *magick_restrict pixel)
829 {
830   if (image->channel_map[ReadMaskPixelChannel].traits != UndefinedPixelTrait)
831     pixel[image->channel_map[ReadMaskPixelChannel].offset]=mask;
832 }
833 
SetPixelWriteMask(const Image * magick_restrict image,const Quantum mask,Quantum * magick_restrict pixel)834 static inline void SetPixelWriteMask(const Image *magick_restrict image,
835   const Quantum mask,Quantum *magick_restrict pixel)
836 {
837   if (image->channel_map[WriteMaskPixelChannel].traits != UndefinedPixelTrait)
838     pixel[image->channel_map[WriteMaskPixelChannel].offset]=mask;
839 }
840 
SetPixelMetacontentExtent(Image * image,const size_t extent)841 static inline void SetPixelMetacontentExtent(Image *image,const size_t extent)
842 {
843   image->metacontent_extent=extent;
844 }
845 
SetPixelOpacity(const Image * magick_restrict image,const Quantum alpha,Quantum * magick_restrict pixel)846 static inline void SetPixelOpacity(const Image *magick_restrict image,
847   const Quantum alpha,Quantum *magick_restrict pixel)
848 {
849   if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait)
850     pixel[image->channel_map[AlphaPixelChannel].offset]=QuantumRange-alpha;
851 }
852 
SetPixelRed(const Image * magick_restrict image,const Quantum red,Quantum * magick_restrict pixel)853 static inline void SetPixelRed(const Image *magick_restrict image,
854   const Quantum red,Quantum *magick_restrict pixel)
855 {
856   pixel[image->channel_map[RedPixelChannel].offset]=red;
857 }
858 
SetPixelRedTraits(Image * image,const PixelTrait traits)859 static inline void SetPixelRedTraits(Image *image,const PixelTrait traits)
860 {
861   image->channel_map[RedPixelChannel].traits=traits;
862 }
863 
SetPixelYellow(const Image * magick_restrict image,const Quantum yellow,Quantum * magick_restrict pixel)864 static inline void SetPixelYellow(const Image *magick_restrict image,
865   const Quantum yellow,Quantum *magick_restrict pixel)
866 {
867   pixel[image->channel_map[YellowPixelChannel].offset]=yellow;
868 }
869 
SetPixelYellowTraits(Image * image,const PixelTrait traits)870 static inline void SetPixelYellowTraits(Image *image,const PixelTrait traits)
871 {
872   image->channel_map[YellowPixelChannel].traits=traits;
873 }
874 
SetPixelY(const Image * magick_restrict image,const Quantum y,Quantum * magick_restrict pixel)875 static inline void SetPixelY(const Image *magick_restrict image,
876   const Quantum y,Quantum *magick_restrict pixel)
877 {
878   pixel[image->channel_map[YPixelChannel].offset]=y;
879 }
880 
SetPixelYTraits(Image * image,const PixelTrait traits)881 static inline void SetPixelYTraits(Image *image,const PixelTrait traits)
882 {
883   image->channel_map[YPixelChannel].traits=traits;
884 }
885 
886 #if defined(__cplusplus) || defined(c_plusplus)
887 }
888 #endif
889 
890 #endif
891