MagickCore  7.0.3
channel.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC H H AAA N N N N EEEEE L %
7 % C H H A A NN N NN N E L %
8 % C HHHHH AAAAA N N N N N N EEE L %
9 % C H H A A N NN N NN E L %
10 % CCCC H H A A N N N N EEEEE LLLLL %
11 % %
12 % %
13 % MagickCore Image Channel Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % December 2003 %
18 % %
19 % %
20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39 
40 /*
41  Include declarations.
42 */
43 #include "MagickCore/studio.h"
45 #include "MagickCore/channel.h"
48 #include "MagickCore/enhance.h"
49 #include "MagickCore/image.h"
50 #include "MagickCore/list.h"
51 #include "MagickCore/log.h"
52 #include "MagickCore/monitor.h"
54 #include "MagickCore/option.h"
57 #include "MagickCore/resource_.h"
60 #include "MagickCore/token.h"
61 #include "MagickCore/utility.h"
62 #include "MagickCore/version.h"
63 
64 /*
65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66 % %
67 % %
68 % %
69 % C h a n n e l F x I m a g e %
70 % %
71 % %
72 % %
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 %
75 % ChannelFxImage() applies a channel expression to the specified image. The
76 % expression consists of one or more channels, either mnemonic or numeric (e.g.
77 % red, 1), separated by actions as follows:
78 %
79 % <=> exchange two channels (e.g. red<=>blue)
80 % => copy one channel to another channel (e.g. red=>green)
81 % = assign a constant value to a channel (e.g. red=50%)
82 % , write new image channels in the specified order (e.g. red, green)
83 % | add a new output image for the next set of channel operations
84 % ; move to the next input image for the source of channel data
85 %
86 % For example, to create 3 grayscale images from the red, green, and blue
87 % channels of an image, use:
88 %
89 % -channel-fx "red; green; blue"
90 %
91 % A channel without an operation symbol implies separate (i.e, semicolon).
92 %
93 % The format of the ChannelFxImage method is:
94 %
95 % Image *ChannelFxImage(const Image *image,const char *expression,
96 % ExceptionInfo *exception)
97 %
98 % A description of each parameter follows:
99 %
100 % o image: the image.
101 %
102 % o expression: A channel expression.
103 %
104 % o exception: return any errors or warnings in this structure.
105 %
106 */
107 
108 typedef enum
109 {
114 } ChannelFx;
115 
116 static MagickBooleanType ChannelImage(Image *destination_image,
117  const PixelChannel destination_channel,const ChannelFx channel_op,
118  const Image *source_image,const PixelChannel source_channel,
119  const Quantum pixel,ExceptionInfo *exception)
120 {
121  CacheView
122  *source_view,
123  *destination_view;
124 
126  status;
127 
128  size_t
129  height,
130  width;
131 
132  ssize_t
133  y;
134 
135  status=MagickTrue;
136  source_view=AcquireVirtualCacheView(source_image,exception);
137  destination_view=AcquireAuthenticCacheView(destination_image,exception);
138  height=MagickMin(source_image->rows,destination_image->rows);
139  width=MagickMin(source_image->columns,destination_image->columns);
140 #if defined(MAGICKCORE_OPENMP_SUPPORT)
141  #pragma omp parallel for schedule(static) shared(status) \
142  magick_number_threads(source_image,source_image,height,1)
143 #endif
144  for (y=0; y < (ssize_t) height; y++)
145  {
146  PixelTrait
147  destination_traits,
148  source_traits;
149 
150  register const Quantum
151  *magick_restrict p;
152 
153  register Quantum
154  *magick_restrict q;
155 
156  register ssize_t
157  x;
158 
159  if (status == MagickFalse)
160  continue;
161  p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
162  exception);
163  q=GetCacheViewAuthenticPixels(destination_view,0,y,
164  destination_image->columns,1,exception);
165  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
166  {
167  status=MagickFalse;
168  continue;
169  }
170  destination_traits=GetPixelChannelTraits(destination_image,
171  destination_channel);
172  source_traits=GetPixelChannelTraits(source_image,source_channel);
173  if ((destination_traits == UndefinedPixelTrait) ||
174  (source_traits == UndefinedPixelTrait))
175  continue;
176  for (x=0; x < (ssize_t) width; x++)
177  {
178  if (channel_op == AssignChannelOp)
179  SetPixelChannel(destination_image,destination_channel,pixel,q);
180  else
181  SetPixelChannel(destination_image,destination_channel,
182  GetPixelChannel(source_image,source_channel,p),q);
183  p+=GetPixelChannels(source_image);
184  q+=GetPixelChannels(destination_image);
185  }
186  if (SyncCacheViewAuthenticPixels(destination_view,exception) == MagickFalse)
187  status=MagickFalse;
188  }
189  destination_view=DestroyCacheView(destination_view);
190  source_view=DestroyCacheView(source_view);
191  return(status);
192 }
193 
194 MagickExport Image *ChannelFxImage(const Image *image,const char *expression,
195  ExceptionInfo *exception)
196 {
197 #define ChannelFxImageTag "ChannelFx/Image"
198 
199  ChannelFx
200  channel_op;
201 
203  channel_mask;
204 
205  char
206  token[MagickPathExtent];
207 
208  const char
209  *p;
210 
211  const Image
212  *source_image;
213 
214  double
215  pixel;
216 
217  Image
218  *destination_image;
219 
221  status;
222 
224  source_channel,
225  destination_channel;
226 
227  ssize_t
228  channels;
229 
230  assert(image != (Image *) NULL);
231  assert(image->signature == MagickCoreSignature);
232  if (image->debug != MagickFalse)
233  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
234  assert(exception != (ExceptionInfo *) NULL);
235  assert(exception->signature == MagickCoreSignature);
236  source_image=image;
237  destination_image=CloneImage(source_image,0,0,MagickTrue,exception);
238  if (destination_image == (Image *) NULL)
239  return((Image *) NULL);
240  if (expression == (const char *) NULL)
241  return(destination_image);
242  status=SetImageStorageClass(destination_image,DirectClass,exception);
243  if (status == MagickFalse)
244  {
245  destination_image=GetLastImageInList(destination_image);
246  return((Image *) NULL);
247  }
248  destination_channel=RedPixelChannel;
249  channel_mask=UndefinedChannel;
250  pixel=0.0;
251  p=(char *) expression;
252  (void) GetNextToken(p,&p,MagickPathExtent,token);
253  channel_op=ExtractChannelOp;
254  for (channels=0; *token != '\0'; )
255  {
256  ssize_t
257  i;
258 
259  /*
260  Interpret channel expression.
261  */
262  switch (*token)
263  {
264  case ',':
265  {
266  (void) GetNextToken(p,&p,MagickPathExtent,token);
267  break;
268  }
269  case '|':
270  {
271  if (GetNextImageInList(source_image) != (Image *) NULL)
272  source_image=GetNextImageInList(source_image);
273  else
274  source_image=GetFirstImageInList(source_image);
275  (void) GetNextToken(p,&p,MagickPathExtent,token);
276  break;
277  }
278  case ';':
279  {
280  Image
281  *canvas;
282 
283  (void) SetPixelChannelMask(destination_image,channel_mask);
284  if ((channel_op == ExtractChannelOp) && (channels == 1))
285  {
286  (void) SetPixelMetaChannels(destination_image,0,exception);
287  (void) SetImageColorspace(destination_image,GRAYColorspace,
288  exception);
289  }
290  canvas=CloneImage(source_image,0,0,MagickTrue,exception);
291  if (canvas == (Image *) NULL)
292  {
293  destination_image=DestroyImageList(destination_image);
294  return(destination_image);
295  }
296  AppendImageToList(&destination_image,canvas);
297  destination_image=GetLastImageInList(destination_image);
298  status=SetImageStorageClass(destination_image,DirectClass,exception);
299  if (status == MagickFalse)
300  {
301  destination_image=GetLastImageInList(destination_image);
302  return((Image *) NULL);
303  }
304  (void) GetNextToken(p,&p,MagickPathExtent,token);
305  channels=0;
306  destination_channel=RedPixelChannel;
307  channel_mask=UndefinedChannel;
308  break;
309  }
310  default:
311  break;
312  }
313  i=ParsePixelChannelOption(token);
314  if (i < 0)
315  {
317  "UnrecognizedChannelType","`%s'",token);
318  destination_image=DestroyImageList(destination_image);
319  return(destination_image);
320  }
321  source_channel=(PixelChannel) i;
322  channel_op=ExtractChannelOp;
323  (void) GetNextToken(p,&p,MagickPathExtent,token);
324  if (*token == '<')
325  {
326  channel_op=ExchangeChannelOp;
327  (void) GetNextToken(p,&p,MagickPathExtent,token);
328  }
329  if (*token == '=')
330  {
331  if (channel_op != ExchangeChannelOp)
332  channel_op=AssignChannelOp;
333  (void) GetNextToken(p,&p,MagickPathExtent,token);
334  }
335  if (*token == '>')
336  {
337  if (channel_op != ExchangeChannelOp)
338  channel_op=TransferChannelOp;
339  (void) GetNextToken(p,&p,MagickPathExtent,token);
340  }
341  switch (channel_op)
342  {
343  case AssignChannelOp:
344  case ExchangeChannelOp:
345  case TransferChannelOp:
346  {
347  if (channel_op == AssignChannelOp)
348  pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0);
349  else
350  {
351  i=ParsePixelChannelOption(token);
352  if (i < 0)
353  {
354  (void) ThrowMagickException(exception,GetMagickModule(),
355  OptionError,"UnrecognizedChannelType","`%s'",token);
356  destination_image=DestroyImageList(destination_image);
357  return(destination_image);
358  }
359  }
360  destination_channel=(PixelChannel) i;
361  if (i >= (ssize_t) GetPixelChannels(destination_image))
362  (void) SetPixelMetaChannels(destination_image,(size_t) (
363  destination_channel-GetPixelChannels(destination_image)+1),
364  exception);
365  if (image->colorspace != UndefinedColorspace)
366  switch (destination_channel)
367  {
368  case RedPixelChannel:
369  case GreenPixelChannel:
370  case BluePixelChannel:
371  case BlackPixelChannel:
372  case IndexPixelChannel:
373  break;
374  case AlphaPixelChannel:
375  {
376  destination_image->alpha_trait=BlendPixelTrait;
377  break;
378  }
380  {
381  destination_image->channels=(ChannelType)
382  (destination_image->channels | CompositeMaskChannel);
383  break;
384  }
386  {
387  destination_image->channels=(ChannelType)
388  (destination_image->channels | ReadMaskChannel);
389  break;
390  }
392  {
393  destination_image->channels=(ChannelType)
394  (destination_image->channels | WriteMaskChannel);
395  break;
396  }
397  case MetaPixelChannel:
398  default:
399  {
400  (void) SetPixelMetaChannels(destination_image,(size_t) (
401  destination_channel-GetPixelChannels(destination_image)+1),
402  exception);
403  break;
404  }
405  }
406  channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token));
407  if (((channels >= 1) || (destination_channel >= 1)) &&
408  (IsGrayColorspace(destination_image->colorspace) != MagickFalse))
409  (void) SetImageColorspace(destination_image,sRGBColorspace,exception);
410  (void) GetNextToken(p,&p,MagickPathExtent,token);
411  break;
412  }
413  default:
414  break;
415  }
416  status=ChannelImage(destination_image,destination_channel,channel_op,
417  source_image,source_channel,ClampToQuantum(pixel),exception);
418  if (status == MagickFalse)
419  {
420  destination_image=DestroyImageList(destination_image);
421  break;
422  }
423  channels++;
424  if (channel_op == ExchangeChannelOp)
425  {
426  status=ChannelImage(destination_image,source_channel,channel_op,
427  source_image,destination_channel,ClampToQuantum(pixel),exception);
428  if (status == MagickFalse)
429  {
430  destination_image=DestroyImageList(destination_image);
431  break;
432  }
433  channels++;
434  }
435  switch (channel_op)
436  {
437  case ExtractChannelOp:
438  {
439  channel_mask=(ChannelType) (channel_mask |
440  (1UL << destination_channel));
441  destination_channel=(PixelChannel) (destination_channel+1);
442  break;
443  }
444  default:
445  break;
446  }
447  status=SetImageProgress(source_image,ChannelFxImageTag,p-expression,
448  strlen(expression));
449  if (status == MagickFalse)
450  break;
451  }
452  (void) SetPixelChannelMask(destination_image,channel_mask);
453  if ((channel_op == ExtractChannelOp) && (channels == 1))
454  {
455  (void) SetPixelMetaChannels(destination_image,0,exception);
456  (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
457  }
458  return(GetFirstImageInList(destination_image));
459 }
460 
461 /*
462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463 % %
464 % %
465 % %
466 % C o m b i n e I m a g e s %
467 % %
468 % %
469 % %
470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 %
472 % CombineImages() combines one or more images into a single image. The
473 % grayscale value of the pixels of each image in the sequence is assigned in
474 % order to the specified channels of the combined image. The typical
475 % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
476 %
477 % The format of the CombineImages method is:
478 %
479 % Image *CombineImages(const Image *images,const ColorspaceType colorspace,
480 % ExceptionInfo *exception)
481 %
482 % A description of each parameter follows:
483 %
484 % o images: the image sequence.
485 %
486 % o colorspace: the image colorspace.
487 %
488 % o exception: return any errors or warnings in this structure.
489 %
490 */
492  const ColorspaceType colorspace,ExceptionInfo *exception)
493 {
494 #define CombineImageTag "Combine/Image"
495 
496  CacheView
497  *combine_view;
498 
499  Image
500  *combine_image;
501 
503  status;
504 
506  progress;
507 
508  ssize_t
509  y;
510 
511  /*
512  Ensure the image are the same size.
513  */
514  assert(image != (const Image *) NULL);
515  assert(image->signature == MagickCoreSignature);
516  if (image->debug != MagickFalse)
517  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
518  assert(exception != (ExceptionInfo *) NULL);
519  assert(exception->signature == MagickCoreSignature);
520  combine_image=CloneImage(image,0,0,MagickTrue,exception);
521  if (combine_image == (Image *) NULL)
522  return((Image *) NULL);
523  if (SetImageStorageClass(combine_image,DirectClass,exception) == MagickFalse)
524  {
525  combine_image=DestroyImage(combine_image);
526  return((Image *) NULL);
527  }
528  if (colorspace != UndefinedColorspace)
529  (void) SetImageColorspace(combine_image,colorspace,exception);
530  else
531  if (fabs(image->gamma-1.0) <= MagickEpsilon)
532  (void) SetImageColorspace(combine_image,RGBColorspace,exception);
533  else
534  (void) SetImageColorspace(combine_image,sRGBColorspace,exception);
535  switch (combine_image->colorspace)
536  {
537  case UndefinedColorspace:
538  case sRGBColorspace:
539  {
540  if (GetImageListLength(image) > 3)
541  combine_image->alpha_trait=BlendPixelTrait;
542  break;
543  }
545  case GRAYColorspace:
546  {
547  if (GetImageListLength(image) > 1)
548  combine_image->alpha_trait=BlendPixelTrait;
549  break;
550  }
551  case CMYKColorspace:
552  {
553  if (GetImageListLength(image) > 4)
554  combine_image->alpha_trait=BlendPixelTrait;
555  break;
556  }
557  default:
558  break;
559  }
560  /*
561  Combine images.
562  */
563  status=MagickTrue;
564  progress=0;
565  combine_view=AcquireAuthenticCacheView(combine_image,exception);
566  for (y=0; y < (ssize_t) combine_image->rows; y++)
567  {
568  CacheView
569  *image_view;
570 
571  const Image
572  *next;
573 
574  Quantum
575  *pixels;
576 
577  register const Quantum
578  *magick_restrict p;
579 
580  register Quantum
581  *magick_restrict q;
582 
583  register ssize_t
584  i;
585 
586  if (status == MagickFalse)
587  continue;
588  pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
589  1,exception);
590  if (pixels == (Quantum *) NULL)
591  {
592  status=MagickFalse;
593  continue;
594  }
595  next=image;
596  for (i=0; i < (ssize_t) GetPixelChannels(combine_image); i++)
597  {
598  register ssize_t
599  x;
600 
601  PixelChannel channel = GetPixelChannelChannel(combine_image,i);
602  PixelTrait traits = GetPixelChannelTraits(combine_image,channel);
603  if (traits == UndefinedPixelTrait)
604  continue;
605  if (next == (Image *) NULL)
606  continue;
607  image_view=AcquireVirtualCacheView(next,exception);
608  p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
609  if (p == (const Quantum *) NULL)
610  continue;
611  q=pixels;
612  for (x=0; x < (ssize_t) combine_image->columns; x++)
613  {
614  if (x < (ssize_t) next->columns)
615  {
616  q[i]=GetPixelGray(next,p);
617  p+=GetPixelChannels(next);
618  }
619  q+=GetPixelChannels(combine_image);
620  }
621  image_view=DestroyCacheView(image_view);
622  next=GetNextImageInList(next);
623  }
624  if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
625  status=MagickFalse;
626  if (image->progress_monitor != (MagickProgressMonitor) NULL)
627  {
629  proceed;
630 
631 #if defined(MAGICKCORE_OPENMP_SUPPORT)
632  #pragma omp atomic
633 #endif
634  progress++;
635  proceed=SetImageProgress(image,CombineImageTag,progress,
636  combine_image->rows);
637  if (proceed == MagickFalse)
638  status=MagickFalse;
639  }
640  }
641  combine_view=DestroyCacheView(combine_view);
642  if (status == MagickFalse)
643  combine_image=DestroyImage(combine_image);
644  return(combine_image);
645 }
646 
647 /*
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % %
650 % %
651 % %
652 % G e t I m a g e A l p h a C h a n n e l %
653 % %
654 % %
655 % %
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657 %
658 % GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
659 % not activated. That is, the image is RGB rather than RGBA or CMYK rather
660 % than CMYKA.
661 %
662 % The format of the GetImageAlphaChannel method is:
663 %
664 % MagickBooleanType GetImageAlphaChannel(const Image *image)
665 %
666 % A description of each parameter follows:
667 %
668 % o image: the image.
669 %
670 */
672 {
673  assert(image != (const Image *) NULL);
674  if (image->debug != MagickFalse)
675  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
676  assert(image->signature == MagickCoreSignature);
678 }
679 
680 /*
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 % %
683 % %
684 % %
685 % S e p a r a t e I m a g e %
686 % %
687 % %
688 % %
689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 %
691 % SeparateImage() separates a channel from the image and returns it as a
692 % grayscale image.
693 %
694 % The format of the SeparateImage method is:
695 %
696 % Image *SeparateImage(const Image *image,const ChannelType channel,
697 % ExceptionInfo *exception)
698 %
699 % A description of each parameter follows:
700 %
701 % o image: the image.
702 %
703 % o channel: the image channel.
704 %
705 % o exception: return any errors or warnings in this structure.
706 %
707 */
709  const ChannelType channel_type,ExceptionInfo *exception)
710 {
711 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
712 #define SeparateImageTag "Separate/Image"
713 
714  CacheView
715  *image_view,
716  *separate_view;
717 
718  Image
719  *separate_image;
720 
722  status;
723 
725  progress;
726 
727  ssize_t
728  y;
729 
730  /*
731  Initialize separate image attributes.
732  */
733  assert(image != (Image *) NULL);
734  assert(image->signature == MagickCoreSignature);
735  if (image->debug != MagickFalse)
736  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
737  assert(exception != (ExceptionInfo *) NULL);
738  assert(exception->signature == MagickCoreSignature);
739  separate_image=CloneImage(image,0,0,MagickTrue,exception);
740  if (separate_image == (Image *) NULL)
741  return((Image *) NULL);
742  if (SetImageStorageClass(separate_image,DirectClass,exception) == MagickFalse)
743  {
744  separate_image=DestroyImage(separate_image);
745  return((Image *) NULL);
746  }
747  separate_image->alpha_trait=UndefinedPixelTrait;
748  (void) SetImageColorspace(separate_image,GRAYColorspace,exception);
749  separate_image->gamma=image->gamma;
750  /*
751  Separate image.
752  */
753  status=MagickTrue;
754  progress=0;
755  image_view=AcquireVirtualCacheView(image,exception);
756  separate_view=AcquireAuthenticCacheView(separate_image,exception);
757 #if defined(MAGICKCORE_OPENMP_SUPPORT)
758  #pragma omp parallel for schedule(static) shared(progress,status) \
759  magick_number_threads(image,image,image->rows,1)
760 #endif
761  for (y=0; y < (ssize_t) image->rows; y++)
762  {
763  register const Quantum
764  *magick_restrict p;
765 
766  register Quantum
767  *magick_restrict q;
768 
769  register ssize_t
770  x;
771 
772  if (status == MagickFalse)
773  continue;
774  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
775  q=QueueCacheViewAuthenticPixels(separate_view,0,y,separate_image->columns,1,
776  exception);
777  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
778  {
779  status=MagickFalse;
780  continue;
781  }
782  for (x=0; x < (ssize_t) image->columns; x++)
783  {
784  register ssize_t
785  i;
786 
787  SetPixelChannel(separate_image,GrayPixelChannel,(Quantum) 0,q);
788  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
789  {
790  PixelChannel channel = GetPixelChannelChannel(image,i);
791  PixelTrait traits = GetPixelChannelTraits(image,channel);
792  if ((traits == UndefinedPixelTrait) ||
793  (GetChannelBit(channel_type,channel) == 0))
794  continue;
795  SetPixelChannel(separate_image,GrayPixelChannel,p[i],q);
796  }
797  p+=GetPixelChannels(image);
798  q+=GetPixelChannels(separate_image);
799  }
800  if (SyncCacheViewAuthenticPixels(separate_view,exception) == MagickFalse)
801  status=MagickFalse;
802  if (image->progress_monitor != (MagickProgressMonitor) NULL)
803  {
805  proceed;
806 
807 #if defined(MAGICKCORE_OPENMP_SUPPORT)
808  #pragma omp atomic
809 #endif
810  progress++;
811  proceed=SetImageProgress(image,SeparateImageTag,progress,image->rows);
812  if (proceed == MagickFalse)
813  status=MagickFalse;
814  }
815  }
816  separate_view=DestroyCacheView(separate_view);
817  image_view=DestroyCacheView(image_view);
818  (void) SetImageChannelMask(separate_image,DefaultChannels);
819  if (status == MagickFalse)
820  separate_image=DestroyImage(separate_image);
821  return(separate_image);
822 }
823 
824 /*
825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
826 % %
827 % %
828 % %
829 % S e p a r a t e I m a g e s %
830 % %
831 % %
832 % %
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834 %
835 % SeparateImages() returns a separate grayscale image for each channel
836 % specified.
837 %
838 % The format of the SeparateImages method is:
839 %
840 % Image *SeparateImages(const Image *image,ExceptionInfo *exception)
841 %
842 % A description of each parameter follows:
843 %
844 % o image: the image.
845 %
846 % o exception: return any errors or warnings in this structure.
847 %
848 */
850 {
851  Image
852  *images,
853  *separate_image;
854 
855  register ssize_t
856  i;
857 
858  assert(image != (Image *) NULL);
859  assert(image->signature == MagickCoreSignature);
860  if (image->debug != MagickFalse)
861  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
862  images=NewImageList();
863  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
864  {
865  PixelChannel channel = GetPixelChannelChannel(image,i);
866  PixelTrait traits = GetPixelChannelTraits(image,channel);
867  if ((traits == UndefinedPixelTrait) || ((traits & UpdatePixelTrait) == 0))
868  continue;
869  separate_image=SeparateImage(image,(ChannelType) (1UL << channel),
870  exception);
871  if (separate_image != (Image *) NULL)
872  AppendImageToList(&images,separate_image);
873  }
874  if (images == (Image *) NULL)
875  images=SeparateImage(image,UndefinedChannel,exception);
876  return(images);
877 }
878 
879 /*
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 % %
882 % %
883 % %
884 % S e t I m a g e A l p h a C h a n n e l %
885 % %
886 % %
887 % %
888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889 %
890 % SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
891 % channel.
892 %
893 % The format of the SetImageAlphaChannel method is:
894 %
895 % MagickBooleanType SetImageAlphaChannel(Image *image,
896 % const AlphaChannelOption alpha_type,ExceptionInfo *exception)
897 %
898 % A description of each parameter follows:
899 %
900 % o image: the image.
901 %
902 % o alpha_type: The alpha channel type: ActivateAlphaChannel,
903 % AssociateAlphaChannel, CopyAlphaChannel, DeactivateAlphaChannel,
904 % DisassociateAlphaChannel, ExtractAlphaChannel, OffAlphaChannel,
905 % OnAlphaChannel, OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel,
906 % and TransparentAlphaChannel.
907 %
908 % o exception: return any errors or warnings in this structure.
909 %
910 */
911 
912 static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p,
913  const double alpha,const Quantum *q,const double beta,
914  Quantum *composite)
915 {
916  double
917  Da,
918  gamma,
919  Sa;
920 
921  register ssize_t
922  i;
923 
924  /*
925  Compose pixel p over pixel q with the given alpha.
926  */
927  Sa=QuantumScale*alpha;
928  Da=QuantumScale*beta,
929  gamma=Sa*(-Da)+Sa+Da;
930  gamma=PerceptibleReciprocal(gamma);
931  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
932  {
933  PixelChannel channel = GetPixelChannelChannel(image,i);
934  PixelTrait traits = GetPixelChannelTraits(image,channel);
935  if (traits == UndefinedPixelTrait)
936  continue;
937  switch (channel)
938  {
939  case RedPixelChannel:
940  {
941  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
942  (double) p->red,alpha));
943  break;
944  }
945  case GreenPixelChannel:
946  {
947  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
948  (double) p->green,alpha));
949  break;
950  }
951  case BluePixelChannel:
952  {
953  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
954  (double) p->blue,alpha));
955  break;
956  }
957  case BlackPixelChannel:
958  {
959  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
960  (double) p->black,alpha));
961  break;
962  }
963  case AlphaPixelChannel:
964  {
965  composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
966  break;
967  }
968  default:
969  break;
970  }
971  }
972 }
973 
975  const AlphaChannelOption alpha_type,ExceptionInfo *exception)
976 {
977  CacheView
978  *image_view;
979 
981  status;
982 
983  ssize_t
984  y;
985 
986  assert(image != (Image *) NULL);
987  if (image->debug != MagickFalse)
988  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
989  assert(image->signature == MagickCoreSignature);
990  status=MagickTrue;
991  switch (alpha_type)
992  {
994  {
996  break;
997  }
999  {
1000  /*
1001  Associate alpha.
1002  */
1003  status=SetImageStorageClass(image,DirectClass,exception);
1004  if (status == MagickFalse)
1005  break;
1006  image_view=AcquireAuthenticCacheView(image,exception);
1007 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1008  #pragma omp parallel for schedule(static) shared(status) \
1009  magick_number_threads(image,image,image->rows,1)
1010 #endif
1011  for (y=0; y < (ssize_t) image->rows; y++)
1012  {
1013  register Quantum
1014  *magick_restrict q;
1015 
1016  register ssize_t
1017  x;
1018 
1019  if (status == MagickFalse)
1020  continue;
1021  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1022  exception);
1023  if (q == (Quantum *) NULL)
1024  {
1025  status=MagickFalse;
1026  continue;
1027  }
1028  for (x=0; x < (ssize_t) image->columns; x++)
1029  {
1030  double
1031  gamma;
1032 
1033  register ssize_t
1034  i;
1035 
1036  gamma=QuantumScale*GetPixelAlpha(image,q);
1037  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1038  {
1039  PixelChannel channel = GetPixelChannelChannel(image,i);
1040  PixelTrait traits = GetPixelChannelTraits(image,channel);
1041  if (channel == AlphaPixelChannel)
1042  continue;
1043  if ((traits & UpdatePixelTrait) == 0)
1044  continue;
1045  q[i]=ClampToQuantum(gamma*q[i]);
1046  }
1047  q+=GetPixelChannels(image);
1048  }
1049  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1050  status=MagickFalse;
1051  }
1052  image_view=DestroyCacheView(image_view);
1053  image->alpha_trait=CopyPixelTrait;
1054  return(status);
1055  }
1057  {
1058  /*
1059  Set transparent pixels to background color.
1060  */
1061  if (image->alpha_trait == UndefinedPixelTrait)
1062  break;
1063  status=SetImageStorageClass(image,DirectClass,exception);
1064  if (status == MagickFalse)
1065  break;
1066  image_view=AcquireAuthenticCacheView(image,exception);
1067 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1068  #pragma omp parallel for schedule(static) shared(status) \
1069  magick_number_threads(image,image,image->rows,1)
1070 #endif
1071  for (y=0; y < (ssize_t) image->rows; y++)
1072  {
1073  register Quantum
1074  *magick_restrict q;
1075 
1076  register ssize_t
1077  x;
1078 
1079  if (status == MagickFalse)
1080  continue;
1081  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1082  exception);
1083  if (q == (Quantum *) NULL)
1084  {
1085  status=MagickFalse;
1086  continue;
1087  }
1088  for (x=0; x < (ssize_t) image->columns; x++)
1089  {
1090  if (GetPixelAlpha(image,q) == TransparentAlpha)
1091  {
1092  SetPixelViaPixelInfo(image,&image->background_color,q);
1094  }
1095  q+=GetPixelChannels(image);
1096  }
1097  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1098  status=MagickFalse;
1099  }
1100  image_view=DestroyCacheView(image_view);
1101  return(status);
1102  }
1103  case CopyAlphaChannel:
1104  {
1106  status=CompositeImage(image,image,IntensityCompositeOp,MagickTrue,0,0,
1107  exception);
1108  break;
1109  }
1111  {
1112  if (image->alpha_trait == UndefinedPixelTrait)
1113  status=SetImageAlpha(image,OpaqueAlpha,exception);
1114  image->alpha_trait=CopyPixelTrait;
1115  break;
1116  }
1118  {
1119  /*
1120  Disassociate alpha.
1121  */
1122  status=SetImageStorageClass(image,DirectClass,exception);
1123  if (status == MagickFalse)
1124  break;
1126  image_view=AcquireAuthenticCacheView(image,exception);
1127 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1128  #pragma omp parallel for schedule(static) shared(status) \
1129  magick_number_threads(image,image,image->rows,1)
1130 #endif
1131  for (y=0; y < (ssize_t) image->rows; y++)
1132  {
1133  register Quantum
1134  *magick_restrict q;
1135 
1136  register ssize_t
1137  x;
1138 
1139  if (status == MagickFalse)
1140  continue;
1141  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1142  exception);
1143  if (q == (Quantum *) NULL)
1144  {
1145  status=MagickFalse;
1146  continue;
1147  }
1148  for (x=0; x < (ssize_t) image->columns; x++)
1149  {
1150  double
1151  gamma,
1152  Sa;
1153 
1154  register ssize_t
1155  i;
1156 
1157  Sa=QuantumScale*GetPixelAlpha(image,q);
1158  gamma=PerceptibleReciprocal(Sa);
1159  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1160  {
1161  PixelChannel channel = GetPixelChannelChannel(image,i);
1162  PixelTrait traits = GetPixelChannelTraits(image,channel);
1163  if (channel == AlphaPixelChannel)
1164  continue;
1165  if ((traits & UpdatePixelTrait) == 0)
1166  continue;
1167  q[i]=ClampToQuantum(gamma*q[i]);
1168  }
1169  q+=GetPixelChannels(image);
1170  }
1171  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1172  status=MagickFalse;
1173  }
1174  image_view=DestroyCacheView(image_view);
1176  return(status);
1177  }
1178  case DiscreteAlphaChannel:
1179  {
1180  if (image->alpha_trait == UndefinedPixelTrait)
1181  status=SetImageAlpha(image,OpaqueAlpha,exception);
1183  break;
1184  }
1185  case ExtractAlphaChannel:
1186  {
1187  status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0,
1188  exception);
1190  break;
1191  }
1192  case OffAlphaChannel:
1193  {
1195  break;
1196  }
1197  case OnAlphaChannel:
1198  {
1199  if (image->alpha_trait == UndefinedPixelTrait)
1200  status=SetImageAlpha(image,OpaqueAlpha,exception);
1202  break;
1203  }
1204  case OpaqueAlphaChannel:
1205  {
1206  status=SetImageAlpha(image,OpaqueAlpha,exception);
1207  break;
1208  }
1209  case RemoveAlphaChannel:
1210  {
1211  /*
1212  Remove transparency.
1213  */
1214  if (image->alpha_trait == UndefinedPixelTrait)
1215  break;
1216  status=SetImageStorageClass(image,DirectClass,exception);
1217  if (status == MagickFalse)
1218  break;
1219  image_view=AcquireAuthenticCacheView(image,exception);
1220 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1221  #pragma omp parallel for schedule(static) shared(status) \
1222  magick_number_threads(image,image,image->rows,1)
1223 #endif
1224  for (y=0; y < (ssize_t) image->rows; y++)
1225  {
1226  register Quantum
1227  *magick_restrict q;
1228 
1229  register ssize_t
1230  x;
1231 
1232  if (status == MagickFalse)
1233  continue;
1234  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1235  exception);
1236  if (q == (Quantum *) NULL)
1237  {
1238  status=MagickFalse;
1239  continue;
1240  }
1241  for (x=0; x < (ssize_t) image->columns; x++)
1242  {
1243  FlattenPixelInfo(image,&image->background_color,
1244  image->background_color.alpha,q,(double) GetPixelAlpha(image,q),q);
1245  q+=GetPixelChannels(image);
1246  }
1247  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1248  status=MagickFalse;
1249  }
1250  image_view=DestroyCacheView(image_view);
1252  break;
1253  }
1254  case SetAlphaChannel:
1255  {
1256  if (image->alpha_trait == UndefinedPixelTrait)
1257  status=SetImageAlpha(image,OpaqueAlpha,exception);
1258  break;
1259  }
1260  case ShapeAlphaChannel:
1261  {
1262  /*
1263  Remove transparency.
1264  */
1266  status=SetImageStorageClass(image,DirectClass,exception);
1267  if (status == MagickFalse)
1268  break;
1269  image_view=AcquireAuthenticCacheView(image,exception);
1270 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1271  #pragma omp parallel for schedule(static) shared(status) \
1272  magick_number_threads(image,image,image->rows,1)
1273 #endif
1274  for (y=0; y < (ssize_t) image->rows; y++)
1275  {
1276  PixelInfo
1277  background;
1278 
1279  register Quantum
1280  *magick_restrict q;
1281 
1282  register ssize_t
1283  x;
1284 
1285  if (status == MagickFalse)
1286  continue;
1287  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1288  exception);
1289  if (q == (Quantum *) NULL)
1290  {
1291  status=MagickFalse;
1292  continue;
1293  }
1294  ConformPixelInfo(image,&image->background_color,&background,exception);
1295  background.alpha_trait=BlendPixelTrait;
1296  for (x=0; x < (ssize_t) image->columns; x++)
1297  {
1298  background.alpha=GetPixelIntensity(image,q);
1299  SetPixelViaPixelInfo(image,&background,q);
1300  q+=GetPixelChannels(image);
1301  }
1302  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1303  status=MagickFalse;
1304  }
1305  image_view=DestroyCacheView(image_view);
1306  break;
1307  }
1309  {
1310  status=SetImageAlpha(image,TransparentAlpha,exception);
1311  break;
1312  }
1313  case UndefinedAlphaChannel:
1314  break;
1315  }
1316  if (status == MagickFalse)
1317  return(status);
1318  (void) SetPixelChannelMask(image,image->channel_mask);
1319  return(SyncImagePixelCache(image,exception));
1320 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
static double MagickOver_(const double p, const double alpha, const double q, const double beta)
#define TransparentAlpha
Definition: image.h:26
#define GetChannelBit(mask, bit)
MagickProgressMonitor progress_monitor
Definition: image.h:303
static Quantum GetPixelAlpha(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
PixelTrait alpha_trait
Definition: pixel.h:178
AlphaChannelOption
Definition: image.h:28
static Quantum GetPixelGray(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
size_t signature
Definition: exception.h:123
ChannelFx
Definition: channel.c:108
#define CombineImageTag
#define OpaqueAlpha
Definition: image.h:25
static Quantum GetPixelChannel(const Image *magick_restrict image, const PixelChannel channel, const Quantum *magick_restrict pixel)
MagickPrivate MagickBooleanType SyncImagePixelCache(Image *, ExceptionInfo *)
Definition: cache.c:5493
MagickRealType red
Definition: pixel.h:190
MagickExport MagickBooleanType SetImageAlpha(Image *image, const Quantum alpha, ExceptionInfo *exception)
Definition: image.c:2337
static PixelTrait GetPixelChannelTraits(const Image *magick_restrict image, const PixelChannel channel)
MagickExport Image * ChannelFxImage(const Image *image, const char *expression, ExceptionInfo *exception)
Definition: channel.c:194
static void SetPixelViaPixelInfo(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel_info, Quantum *magick_restrict pixel)
static MagickBooleanType IsGrayColorspace(const ColorspaceType colorspace)
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:651
MagickRealType alpha
Definition: pixel.h:190
#define MagickEpsilon
Definition: magick-type.h:110
MagickExport size_t GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition: token.c:173
MagickExport MagickBooleanType CompositeImage(Image *image, const Image *composite, const CompositeOperator compose, const MagickBooleanType clip_to_self, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
Definition: composite.c:528
MagickExport Image * CombineImages(const Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: channel.c:491
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:129
MagickExport ssize_t ParseChannelOption(const char *channels)
Definition: option.c:2848
Definition: image.h:151
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:299
MagickExport Image * GetFirstImageInList(const Image *images)
Definition: list.c:561
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelOption alpha_type, ExceptionInfo *exception)
Definition: channel.c:974
MagickBooleanType
Definition: magick-type.h:158
MagickExport Image * NewImageList(void)
Definition: list.c:938
static double PerceptibleReciprocal(const double x)
static void FlattenPixelInfo(const Image *image, const PixelInfo *p, const double alpha, const Quantum *q, const double beta, Quantum *composite)
Definition: channel.c:912
MagickExport Image * SeparateImage(const Image *image, const ChannelType channel_type, ExceptionInfo *exception)
Definition: channel.c:708
ChannelType channel_mask
Definition: image.h:288
#define MagickPathExtent
PixelTrait alpha_trait
Definition: image.h:280
MagickRealType blue
Definition: pixel.h:190
MagickExport ChannelType SetPixelChannelMask(Image *image, const ChannelType channel_mask)
Definition: pixel.c:6277
MagickExport ChannelType SetImageChannelMask(Image *image, const ChannelType channel_mask)
Definition: image.c:2499
MagickExport Quantum * QueueCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:977
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1413
size_t signature
Definition: image.h:354
#define QuantumScale
Definition: magick-type.h:115
size_t columns
Definition: image.h:172
MagickExport Image * GetLastImageInList(const Image *images)
Definition: list.c:737
ChannelType
Definition: pixel.h:33
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2615
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:462
PixelChannel
Definition: pixel.h:67
static size_t GetPixelChannels(const Image *magick_restrict image)
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
MagickExport void ConformPixelInfo(Image *image, const PixelInfo *source, PixelInfo *destination, ExceptionInfo *exception)
Definition: pixel.c:212
static Quantum ClampToQuantum(const MagickRealType value)
Definition: quantum.h:84
static PixelChannel GetPixelChannelChannel(const Image *magick_restrict image, const ssize_t offset)
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:149
static double StringToDoubleInterval(const char *string, const double interval)
unsigned short Quantum
Definition: magick-type.h:82
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1135
MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
Definition: channel.c:671
ChannelType channels
Definition: image.h:366
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:771
MagickRealType black
Definition: pixel.h:190
#define SeparateImageTag
static void SetPixelChannel(const Image *magick_restrict image, const PixelChannel channel, const Quantum quantum, Quantum *magick_restrict pixel)
MagickExport void AppendImageToList(Image **images, const Image *append)
Definition: list.c:78
#define MagickMin(x, y)
Definition: image-private.h:27
ColorspaceType
Definition: colorspace.h:25
#define ChannelFxImageTag
MagickRealType green
Definition: pixel.h:190
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
MagickExport ssize_t ParsePixelChannelOption(const char *channels)
Definition: option.c:3074
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
MagickExport MagickBooleanType SetPixelMetaChannels(Image *image, const size_t number_meta_channels, ExceptionInfo *exception)
Definition: pixel.c:6361
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
PixelTrait
Definition: pixel.h:134
MagickExport MagickRealType GetPixelIntensity(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
Definition: pixel.c:2358
PixelInfo background_color
Definition: image.h:179
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:696
static MagickBooleanType ChannelImage(Image *destination_image, const PixelChannel destination_channel, const ChannelFx channel_op, const Image *source_image, const PixelChannel source_channel, const Quantum pixel, ExceptionInfo *exception)
Definition: channel.c:116
MagickExport Image * SeparateImages(const Image *image, ExceptionInfo *exception)
Definition: channel.c:849
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1181
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:796
double gamma
Definition: image.h:186
ColorspaceType colorspace
Definition: image.h:157
#define QuantumRange
Definition: magick-type.h:83
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickBooleanType debug
Definition: image.h:334