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