MagickCore  7.0.7
Convert, Edit, Or Compose Bitmap Images
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-2018 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://www.imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39 
40 /*
41  Include declarations.
42 */
43 #include "MagickCore/studio.h"
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,4) 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  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  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  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  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  GetNextToken(p,&p,MagickPathExtent,token);
324  if (*token == '<')
325  {
326  channel_op=ExchangeChannelOp;
327  GetNextToken(p,&p,MagickPathExtent,token);
328  }
329  if (*token == '=')
330  {
331  if (channel_op != ExchangeChannelOp)
332  channel_op=AssignChannelOp;
333  GetNextToken(p,&p,MagickPathExtent,token);
334  }
335  if (*token == '>')
336  {
337  if (channel_op != ExchangeChannelOp)
338  channel_op=TransferChannelOp;
339  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->read_mask=MagickTrue;
382  break;
383  }
385  {
386  destination_image->write_mask=MagickTrue;
387  break;
388  }
389  case MetaPixelChannel:
390  default:
391  {
392  (void) SetPixelMetaChannels(destination_image,(size_t) (
393  destination_channel-GetPixelChannels(destination_image)+1),
394  exception);
395  break;
396  }
397  }
398  channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token));
399  if (((channels >= 1) || (destination_channel >= 1)) &&
400  (IsGrayColorspace(destination_image->colorspace) != MagickFalse))
401  (void) SetImageColorspace(destination_image,sRGBColorspace,exception);
402  GetNextToken(p,&p,MagickPathExtent,token);
403  break;
404  }
405  default:
406  break;
407  }
408  status=ChannelImage(destination_image,destination_channel,channel_op,
409  source_image,source_channel,ClampToQuantum(pixel),exception);
410  if (status == MagickFalse)
411  {
412  destination_image=DestroyImageList(destination_image);
413  break;
414  }
415  channels++;
416  if (channel_op == ExchangeChannelOp)
417  {
418  status=ChannelImage(destination_image,source_channel,channel_op,
419  source_image,destination_channel,ClampToQuantum(pixel),exception);
420  if (status == MagickFalse)
421  {
422  destination_image=DestroyImageList(destination_image);
423  break;
424  }
425  channels++;
426  }
427  switch (channel_op)
428  {
429  case ExtractChannelOp:
430  {
431  channel_mask=(ChannelType) (channel_mask | (1 << destination_channel));
432  destination_channel=(PixelChannel) (destination_channel+1);
433  break;
434  }
435  default:
436  break;
437  }
438  status=SetImageProgress(source_image,ChannelFxImageTag,p-expression,
439  strlen(expression));
440  if (status == MagickFalse)
441  break;
442  }
443  (void) SetPixelChannelMask(destination_image,channel_mask);
444  if ((channel_op == ExtractChannelOp) && (channels == 1))
445  {
446  (void) SetPixelMetaChannels(destination_image,0,exception);
447  (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
448  }
449  return(GetFirstImageInList(destination_image));
450 }
451 
452 /*
453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 % %
455 % %
456 % %
457 % C o m b i n e I m a g e s %
458 % %
459 % %
460 % %
461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 %
463 % CombineImages() combines one or more images into a single image. The
464 % grayscale value of the pixels of each image in the sequence is assigned in
465 % order to the specified channels of the combined image. The typical
466 % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
467 %
468 % The format of the CombineImages method is:
469 %
470 % Image *CombineImages(const Image *images,const ColorspaceType colorspace,
471 % ExceptionInfo *exception)
472 %
473 % A description of each parameter follows:
474 %
475 % o images: the image sequence.
476 %
477 % o colorspace: the image colorspace.
478 %
479 % o exception: return any errors or warnings in this structure.
480 %
481 */
483  const ColorspaceType colorspace,ExceptionInfo *exception)
484 {
485 #define CombineImageTag "Combine/Image"
486 
487  CacheView
488  *combine_view;
489 
490  Image
491  *combine_image;
492 
494  status;
495 
497  progress;
498 
499  ssize_t
500  y;
501 
502  /*
503  Ensure the image are the same size.
504  */
505  assert(image != (const Image *) NULL);
506  assert(image->signature == MagickCoreSignature);
507  if (image->debug != MagickFalse)
508  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
509  assert(exception != (ExceptionInfo *) NULL);
510  assert(exception->signature == MagickCoreSignature);
511  combine_image=CloneImage(image,0,0,MagickTrue,exception);
512  if (combine_image == (Image *) NULL)
513  return((Image *) NULL);
514  if (SetImageStorageClass(combine_image,DirectClass,exception) == MagickFalse)
515  {
516  combine_image=DestroyImage(combine_image);
517  return((Image *) NULL);
518  }
519  if (colorspace != UndefinedColorspace)
520  (void) SetImageColorspace(combine_image,colorspace,exception);
521  else
522  if (fabs(image->gamma-1.0) <= MagickEpsilon)
523  (void) SetImageColorspace(combine_image,RGBColorspace,exception);
524  else
525  (void) SetImageColorspace(combine_image,sRGBColorspace,exception);
526  switch (combine_image->colorspace)
527  {
528  case UndefinedColorspace:
529  case sRGBColorspace:
530  {
531  if (GetImageListLength(image) > 3)
532  combine_image->alpha_trait=BlendPixelTrait;
533  break;
534  }
535  case GRAYColorspace:
536  {
537  if (GetImageListLength(image) > 1)
538  combine_image->alpha_trait=BlendPixelTrait;
539  break;
540  }
541  case CMYKColorspace:
542  {
543  if (GetImageListLength(image) > 4)
544  combine_image->alpha_trait=BlendPixelTrait;
545  break;
546  }
547  default:
548  break;
549  }
550  /*
551  Combine images.
552  */
553  status=MagickTrue;
554  progress=0;
555  combine_view=AcquireAuthenticCacheView(combine_image,exception);
556  for (y=0; y < (ssize_t) combine_image->rows; y++)
557  {
558  CacheView
559  *image_view;
560 
561  const Image
562  *next;
563 
564  Quantum
565  *pixels;
566 
567  register const Quantum
568  *magick_restrict p;
569 
570  register Quantum
571  *magick_restrict q;
572 
573  register ssize_t
574  i;
575 
576  if (status == MagickFalse)
577  continue;
578  pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
579  1,exception);
580  if (pixels == (Quantum *) NULL)
581  {
582  status=MagickFalse;
583  continue;
584  }
585  next=image;
586  for (i=0; i < (ssize_t) GetPixelChannels(combine_image); i++)
587  {
588  register ssize_t
589  x;
590 
591  PixelChannel channel = GetPixelChannelChannel(combine_image,i);
592  PixelTrait traits = GetPixelChannelTraits(combine_image,channel);
593  if (traits == UndefinedPixelTrait)
594  continue;
595  if (next == (Image *) NULL)
596  continue;
597  image_view=AcquireVirtualCacheView(next,exception);
598  p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
599  if (p == (const Quantum *) NULL)
600  continue;
601  q=pixels;
602  for (x=0; x < (ssize_t) combine_image->columns; x++)
603  {
604  if (x < (ssize_t) next->columns)
605  {
606  q[i]=GetPixelGray(next,p);
607  p+=GetPixelChannels(next);
608  }
609  q+=GetPixelChannels(combine_image);
610  }
611  image_view=DestroyCacheView(image_view);
612  next=GetNextImageInList(next);
613  }
614  if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
615  status=MagickFalse;
616  if (image->progress_monitor != (MagickProgressMonitor) NULL)
617  {
619  proceed;
620 
621  proceed=SetImageProgress(image,CombineImageTag,progress++,
622  combine_image->rows);
623  if (proceed == MagickFalse)
624  status=MagickFalse;
625  }
626  }
627  combine_view=DestroyCacheView(combine_view);
628  if (status == MagickFalse)
629  combine_image=DestroyImage(combine_image);
630  return(combine_image);
631 }
632 
633 /*
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 % %
636 % %
637 % %
638 % G e t I m a g e A l p h a C h a n n e l %
639 % %
640 % %
641 % %
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 %
644 % GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
645 % not activated. That is, the image is RGB rather than RGBA or CMYK rather
646 % than CMYKA.
647 %
648 % The format of the GetImageAlphaChannel method is:
649 %
650 % MagickBooleanType GetImageAlphaChannel(const Image *image)
651 %
652 % A description of each parameter follows:
653 %
654 % o image: the image.
655 %
656 */
658 {
659  assert(image != (const Image *) NULL);
660  if (image->debug != MagickFalse)
661  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
662  assert(image->signature == MagickCoreSignature);
664 }
665 
666 /*
667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668 % %
669 % %
670 % %
671 % S e p a r a t e I m a g e %
672 % %
673 % %
674 % %
675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
676 %
677 % SeparateImage() separates a channel from the image and returns it as a
678 % grayscale image.
679 %
680 % The format of the SeparateImage method is:
681 %
682 % Image *SeparateImage(const Image *image,const ChannelType channel,
683 % ExceptionInfo *exception)
684 %
685 % A description of each parameter follows:
686 %
687 % o image: the image.
688 %
689 % o channel: the image channel.
690 %
691 % o exception: return any errors or warnings in this structure.
692 %
693 */
695  const ChannelType channel_type,ExceptionInfo *exception)
696 {
697 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
698 #define SeparateImageTag "Separate/Image"
699 
700  CacheView
701  *image_view,
702  *separate_view;
703 
704  Image
705  *separate_image;
706 
708  status;
709 
711  progress;
712 
713  ssize_t
714  y;
715 
716  /*
717  Initialize separate image attributes.
718  */
719  assert(image != (Image *) NULL);
720  assert(image->signature == MagickCoreSignature);
721  if (image->debug != MagickFalse)
722  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
723  assert(exception != (ExceptionInfo *) NULL);
724  assert(exception->signature == MagickCoreSignature);
725  separate_image=CloneImage(image,image->columns,image->rows,MagickTrue,
726  exception);
727  if (separate_image == (Image *) NULL)
728  return((Image *) NULL);
729  if (SetImageStorageClass(separate_image,DirectClass,exception) == MagickFalse)
730  {
731  separate_image=DestroyImage(separate_image);
732  return((Image *) NULL);
733  }
734  separate_image->alpha_trait=UndefinedPixelTrait;
735  (void) SetImageColorspace(separate_image,GRAYColorspace,exception);
736  separate_image->gamma=image->gamma;
737  /*
738  Separate image.
739  */
740  status=MagickTrue;
741  progress=0;
742  image_view=AcquireVirtualCacheView(image,exception);
743  separate_view=AcquireAuthenticCacheView(separate_image,exception);
744 #if defined(MAGICKCORE_OPENMP_SUPPORT)
745  #pragma omp parallel for schedule(static,4) shared(progress,status) \
746  magick_number_threads(image,image,image->rows,1)
747 #endif
748  for (y=0; y < (ssize_t) image->rows; y++)
749  {
750  register const Quantum
751  *magick_restrict p;
752 
753  register Quantum
754  *magick_restrict q;
755 
756  register ssize_t
757  x;
758 
759  if (status == MagickFalse)
760  continue;
761  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
762  q=QueueCacheViewAuthenticPixels(separate_view,0,y,separate_image->columns,1,
763  exception);
764  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
765  {
766  status=MagickFalse;
767  continue;
768  }
769  for (x=0; x < (ssize_t) image->columns; x++)
770  {
771  register ssize_t
772  i;
773 
774  if (GetPixelWriteMask(image,p) <= (QuantumRange/2))
775  {
776  SetPixelBackgoundColor(separate_image,q);
777  p+=GetPixelChannels(image);
778  q+=GetPixelChannels(separate_image);
779  continue;
780  }
781  SetPixelChannel(separate_image,GrayPixelChannel,0,q);
782  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
783  {
784  PixelChannel channel = GetPixelChannelChannel(image,i);
785  PixelTrait traits = GetPixelChannelTraits(image,channel);
786  if ((traits == UndefinedPixelTrait) ||
787  (GetChannelBit(channel_type,channel) == 0))
788  continue;
789  SetPixelChannel(separate_image,GrayPixelChannel,p[i],q);
790  }
791  p+=GetPixelChannels(image);
792  q+=GetPixelChannels(separate_image);
793  }
794  if (SyncCacheViewAuthenticPixels(separate_view,exception) == MagickFalse)
795  status=MagickFalse;
796  if (image->progress_monitor != (MagickProgressMonitor) NULL)
797  {
799  proceed;
800 
801 #if defined(MAGICKCORE_OPENMP_SUPPORT)
802  #pragma omp critical (MagickCore_SeparateImage)
803 #endif
804  proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
805  if (proceed == MagickFalse)
806  status=MagickFalse;
807  }
808  }
809  separate_view=DestroyCacheView(separate_view);
810  image_view=DestroyCacheView(image_view);
811  (void) SetImageChannelMask(separate_image,DefaultChannels);
812  if (status == MagickFalse)
813  separate_image=DestroyImage(separate_image);
814  return(separate_image);
815 }
816 
817 /*
818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 % %
820 % %
821 % %
822 % S e p a r a t e I m a g e s %
823 % %
824 % %
825 % %
826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 %
828 % SeparateImages() returns a separate grayscale image for each channel
829 % specified.
830 %
831 % The format of the SeparateImages method is:
832 %
833 % Image *SeparateImages(const Image *image,ExceptionInfo *exception)
834 %
835 % A description of each parameter follows:
836 %
837 % o image: the image.
838 %
839 % o exception: return any errors or warnings in this structure.
840 %
841 */
843 {
844  Image
845  *images,
846  *separate_image;
847 
848  register ssize_t
849  i;
850 
851  assert(image != (Image *) NULL);
852  assert(image->signature == MagickCoreSignature);
853  if (image->debug != MagickFalse)
854  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
855  images=NewImageList();
856  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
857  {
858  PixelChannel channel = GetPixelChannelChannel(image,i);
859  PixelTrait traits = GetPixelChannelTraits(image,channel);
860  if ((traits == UndefinedPixelTrait) || ((traits & UpdatePixelTrait) == 0))
861  continue;
862  separate_image=SeparateImage(image,(ChannelType) (1 << channel),exception);
863  if (separate_image != (Image *) NULL)
864  AppendImageToList(&images,separate_image);
865  }
866  if (images == (Image *) NULL)
867  images=SeparateImage(image,UndefinedChannel,exception);
868  return(images);
869 }
870 
871 /*
872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873 % %
874 % %
875 % %
876 % S e t I m a g e A l p h a C h a n n e l %
877 % %
878 % %
879 % %
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 %
882 % SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
883 % channel.
884 %
885 % The format of the SetImageAlphaChannel method is:
886 %
887 % MagickBooleanType SetImageAlphaChannel(Image *image,
888 % const AlphaChannelOption alpha_type,ExceptionInfo *exception)
889 %
890 % A description of each parameter follows:
891 %
892 % o image: the image.
893 %
894 % o alpha_type: The alpha channel type: ActivateAlphaChannel,
895 % AssociateAlphaChannel, CopyAlphaChannel, DeactivateAlphaChannel,
896 % DisassociateAlphaChannel, ExtractAlphaChannel, OffAlphaChannel,
897 % OnAlphaChannel, OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel,
898 % and TransparentAlphaChannel.
899 %
900 % o exception: return any errors or warnings in this structure.
901 %
902 */
903 
904 static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p,
905  const double alpha,const Quantum *q,const double beta,
906  Quantum *composite)
907 {
908  double
909  Da,
910  gamma,
911  Sa;
912 
913  register ssize_t
914  i;
915 
916  /*
917  Compose pixel p over pixel q with the given alpha.
918  */
919  Sa=QuantumScale*alpha;
920  Da=QuantumScale*beta,
921  gamma=Sa*(-Da)+Sa+Da;
922  gamma=PerceptibleReciprocal(gamma);
923  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
924  {
925  PixelChannel channel = GetPixelChannelChannel(image,i);
926  PixelTrait traits = GetPixelChannelTraits(image,channel);
927  if (traits == UndefinedPixelTrait)
928  continue;
929  switch (channel)
930  {
931  case RedPixelChannel:
932  {
933  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
934  (double) p->red,alpha));
935  break;
936  }
937  case GreenPixelChannel:
938  {
939  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
940  (double) p->green,alpha));
941  break;
942  }
943  case BluePixelChannel:
944  {
945  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
946  (double) p->blue,alpha));
947  break;
948  }
949  case BlackPixelChannel:
950  {
951  composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
952  (double) p->black,alpha));
953  break;
954  }
955  case AlphaPixelChannel:
956  {
957  composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
958  break;
959  }
960  default:
961  break;
962  }
963  }
964 }
965 
967  const AlphaChannelOption alpha_type,ExceptionInfo *exception)
968 {
969  CacheView
970  *image_view;
971 
973  status;
974 
975  ssize_t
976  y;
977 
978  assert(image != (Image *) NULL);
979  if (image->debug != MagickFalse)
980  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
981  assert(image->signature == MagickCoreSignature);
982  status=MagickTrue;
983  switch (alpha_type)
984  {
986  {
988  break;
989  }
991  {
992  /*
993  Associate alpha.
994  */
995  status=SetImageStorageClass(image,DirectClass,exception);
996  if (status == MagickFalse)
997  break;
998  image_view=AcquireAuthenticCacheView(image,exception);
999 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1000  #pragma omp parallel for schedule(static,4) shared(status) \
1001  magick_number_threads(image,image,image->rows,1)
1002 #endif
1003  for (y=0; y < (ssize_t) image->rows; y++)
1004  {
1005  register Quantum
1006  *magick_restrict q;
1007 
1008  register ssize_t
1009  x;
1010 
1011  if (status == MagickFalse)
1012  continue;
1013  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1014  exception);
1015  if (q == (Quantum *) NULL)
1016  {
1017  status=MagickFalse;
1018  continue;
1019  }
1020  for (x=0; x < (ssize_t) image->columns; x++)
1021  {
1022  double
1023  gamma;
1024 
1025  register ssize_t
1026  i;
1027 
1028  if (GetPixelWriteMask(image,q) <= (QuantumRange/2))
1029  {
1030  q+=GetPixelChannels(image);
1031  continue;
1032  }
1033  gamma=QuantumScale*GetPixelAlpha(image,q);
1034  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1035  {
1036  PixelChannel channel = GetPixelChannelChannel(image,i);
1037  PixelTrait traits = GetPixelChannelTraits(image,channel);
1038  if (channel == AlphaPixelChannel)
1039  continue;
1040  if ((traits & UpdatePixelTrait) == 0)
1041  continue;
1042  q[i]=ClampToQuantum(gamma*q[i]);
1043  }
1044  q+=GetPixelChannels(image);
1045  }
1046  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1047  status=MagickFalse;
1048  }
1049  image_view=DestroyCacheView(image_view);
1050  image->alpha_trait=CopyPixelTrait;
1051  return(status);
1052  }
1054  {
1055  /*
1056  Set transparent pixels to background color.
1057  */
1058  if (image->alpha_trait == UndefinedPixelTrait)
1059  break;
1060  status=SetImageStorageClass(image,DirectClass,exception);
1061  if (status == MagickFalse)
1062  break;
1063  image_view=AcquireAuthenticCacheView(image,exception);
1064 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1065  #pragma omp parallel for schedule(static,4) shared(status) \
1066  magick_number_threads(image,image,image->rows,1)
1067 #endif
1068  for (y=0; y < (ssize_t) image->rows; y++)
1069  {
1070  register Quantum
1071  *magick_restrict q;
1072 
1073  register ssize_t
1074  x;
1075 
1076  if (status == MagickFalse)
1077  continue;
1078  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1079  exception);
1080  if (q == (Quantum *) NULL)
1081  {
1082  status=MagickFalse;
1083  continue;
1084  }
1085  for (x=0; x < (ssize_t) image->columns; x++)
1086  {
1087  if (GetPixelAlpha(image,q) == TransparentAlpha)
1088  {
1089  SetPixelViaPixelInfo(image,&image->background_color,q);
1091  }
1092  q+=GetPixelChannels(image);
1093  }
1094  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1095  status=MagickFalse;
1096  }
1097  image_view=DestroyCacheView(image_view);
1098  return(status);
1099  }
1100  case CopyAlphaChannel:
1101  {
1103  status=CompositeImage(image,image,IntensityCompositeOp,MagickTrue,0,0,
1104  exception);
1105  break;
1106  }
1108  {
1109  if (image->alpha_trait == UndefinedPixelTrait)
1110  status=SetImageAlpha(image,OpaqueAlpha,exception);
1111  image->alpha_trait=CopyPixelTrait;
1112  break;
1113  }
1115  {
1116  /*
1117  Disassociate alpha.
1118  */
1119  status=SetImageStorageClass(image,DirectClass,exception);
1120  if (status == MagickFalse)
1121  break;
1123  image_view=AcquireAuthenticCacheView(image,exception);
1124 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1125  #pragma omp parallel for schedule(static,4) shared(status) \
1126  magick_number_threads(image,image,image->rows,1)
1127 #endif
1128  for (y=0; y < (ssize_t) image->rows; y++)
1129  {
1130  register Quantum
1131  *magick_restrict q;
1132 
1133  register ssize_t
1134  x;
1135 
1136  if (status == MagickFalse)
1137  continue;
1138  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1139  exception);
1140  if (q == (Quantum *) NULL)
1141  {
1142  status=MagickFalse;
1143  continue;
1144  }
1145  for (x=0; x < (ssize_t) image->columns; x++)
1146  {
1147  double
1148  gamma,
1149  Sa;
1150 
1151  register ssize_t
1152  i;
1153 
1154  if (GetPixelWriteMask(image,q) <= (QuantumRange/2))
1155  {
1156  q+=GetPixelChannels(image);
1157  continue;
1158  }
1159  Sa=QuantumScale*GetPixelAlpha(image,q);
1160  gamma=PerceptibleReciprocal(Sa);
1161  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1162  {
1163  PixelChannel channel = GetPixelChannelChannel(image,i);
1164  PixelTrait traits = GetPixelChannelTraits(image,channel);
1165  if (channel == AlphaPixelChannel)
1166  continue;
1167  if ((traits & UpdatePixelTrait) == 0)
1168  continue;
1169  q[i]=ClampToQuantum(gamma*q[i]);
1170  }
1171  q+=GetPixelChannels(image);
1172  }
1173  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1174  status=MagickFalse;
1175  }
1176  image_view=DestroyCacheView(image_view);
1178  return(status);
1179  }
1180  case DiscreteAlphaChannel:
1181  {
1182  if (image->alpha_trait == UndefinedPixelTrait)
1183  status=SetImageAlpha(image,OpaqueAlpha,exception);
1185  break;
1186  }
1187  case ExtractAlphaChannel:
1188  {
1189  status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0,
1190  exception);
1192  break;
1193  }
1194  case OffAlphaChannel:
1195  {
1197  break;
1198  }
1199  case OnAlphaChannel:
1200  {
1201  if (image->alpha_trait == UndefinedPixelTrait)
1202  status=SetImageAlpha(image,OpaqueAlpha,exception);
1204  break;
1205  }
1206  case OpaqueAlphaChannel:
1207  {
1208  status=SetImageAlpha(image,OpaqueAlpha,exception);
1209  break;
1210  }
1211  case RemoveAlphaChannel:
1212  {
1213  /*
1214  Remove transparency.
1215  */
1216  if (image->alpha_trait == UndefinedPixelTrait)
1217  break;
1218  status=SetImageStorageClass(image,DirectClass,exception);
1219  if (status == MagickFalse)
1220  break;
1221  image_view=AcquireAuthenticCacheView(image,exception);
1222 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1223  #pragma omp parallel for schedule(static,4) shared(status) \
1224  magick_number_threads(image,image,image->rows,1)
1225 #endif
1226  for (y=0; y < (ssize_t) image->rows; y++)
1227  {
1228  register Quantum
1229  *magick_restrict q;
1230 
1231  register ssize_t
1232  x;
1233 
1234  if (status == MagickFalse)
1235  continue;
1236  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1237  exception);
1238  if (q == (Quantum *) NULL)
1239  {
1240  status=MagickFalse;
1241  continue;
1242  }
1243  for (x=0; x < (ssize_t) image->columns; x++)
1244  {
1245  FlattenPixelInfo(image,&image->background_color,
1246  image->background_color.alpha,q,(double)
1247  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  /*
1266  Set alpha channel by shape.
1267  */
1268  status=SetImageStorageClass(image,DirectClass,exception);
1269  if (status == MagickFalse)
1270  break;
1272  (void) SetImageMask(image,WritePixelMask,image,exception);
1273  (void) LevelImageColors(image,&image->background_color,
1274  &image->background_color,MagickTrue,exception);
1275  (void) SetImageMask(image,WritePixelMask,(Image *) NULL,exception);
1276  break;
1277  }
1279  {
1280  status=SetImageAlpha(image,TransparentAlpha,exception);
1281  break;
1282  }
1283  case UndefinedAlphaChannel:
1284  break;
1285  }
1286  if (status == MagickFalse)
1287  return(status);
1288  (void) SetPixelChannelMask(image,image->channel_mask);
1289  return(SyncImagePixelCache(image,exception));
1290 }
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
static MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
#define GetChannelBit(mask, bit)
MagickProgressMonitor progress_monitor
Definition: image.h:303
static void SetPixelBackgoundColor(const Image *magick_restrict image, Quantum *magick_restrict pixel)
static Quantum GetPixelAlpha(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
PixelTrait alpha_trait
Definition: pixel.h:176
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:5252
MagickRealType red
Definition: pixel.h:188
MagickExport MagickBooleanType SetImageAlpha(Image *image, const Quantum alpha, ExceptionInfo *exception)
Definition: image.c:2229
MagickBooleanType read_mask
Definition: image.h:276
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:188
#define MagickEpsilon
Definition: magick-type.h:110
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:539
MagickExport Image * CombineImages(const Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: channel.c:482
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:127
MagickExport ssize_t ParseChannelOption(const char *channels)
Definition: option.c:2833
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:541
MagickExport MagickBooleanType SetImageMask(Image *image, const PixelMask type, const Image *mask, ExceptionInfo *exception)
Definition: image.c:3073
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelOption alpha_type, ExceptionInfo *exception)
Definition: channel.c:966
MagickBooleanType
Definition: magick-type.h:156
MagickExport Image * NewImageList(void)
Definition: list.c:916
static double PerceptibleReciprocal(const double x)
static Quantum GetPixelWriteMask(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static void FlattenPixelInfo(const Image *image, const PixelInfo *p, const double alpha, const Quantum *q, const double beta, Quantum *composite)
Definition: channel.c:904
MagickExport Image * SeparateImage(const Image *image, const ChannelType channel_type, ExceptionInfo *exception)
Definition: channel.c:694
ChannelType channel_mask
Definition: image.h:288
#define MagickPathExtent
PixelTrait alpha_trait
Definition: image.h:280
MagickRealType blue
Definition: pixel.h:188
MagickExport ChannelType SetPixelChannelMask(Image *image, const ChannelType channel_mask)
Definition: pixel.c:6258
MagickExport ChannelType SetImageChannelMask(Image *image, const ChannelType channel_mask)
Definition: image.c:2392
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:1058
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1397
size_t signature
Definition: image.h:354
MagickExport MagickBooleanType LevelImageColors(Image *image, const PixelInfo *black_color, const PixelInfo *white_color, const MagickBooleanType invert, ExceptionInfo *exception)
Definition: enhance.c:2695
#define QuantumScale
Definition: magick-type.h:113
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:718
ChannelType
Definition: pixel.h:33
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2508
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:442
PixelChannel
Definition: pixel.h:66
static size_t GetPixelChannels(const Image *magick_restrict image)
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
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
MagickExport void GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition: token.c:171
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:1081
MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
Definition: channel.c:657
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:752
MagickRealType black
Definition: pixel.h:188
#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:77
#define MagickMin(x, y)
Definition: image-private.h:27
ColorspaceType
Definition: colorspace.h:25
#define ChannelFxImageTag
MagickRealType green
Definition: pixel.h:188
MagickExport ssize_t ParsePixelChannelOption(const char *channels)
Definition: option.c:3059
#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:6340
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
PixelTrait
Definition: pixel.h:132
MagickBooleanType write_mask
Definition: image.h:276
PixelInfo background_color
Definition: image.h:179
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:680
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:842
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1182
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:799
double gamma
Definition: image.h:186
ColorspaceType colorspace
Definition: image.h:157
#define QuantumRange
Definition: magick-type.h:83
MagickBooleanType debug
Definition: image.h:334