2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 RRR 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 %
13 % MagickCore Image Channel Methods %
20 % Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/cache-private.h"
45 #include "MagickCore/colorspace-private.h"
46 #include "MagickCore/composite-private.h"
47 #include "MagickCore/enhance.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/list.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/monitor.h"
52 #include "MagickCore/monitor-private.h"
53 #include "MagickCore/option.h"
54 #include "MagickCore/pixel-accessor.h"
55 #include "MagickCore/pixel-private.h"
56 #include "MagickCore/resource_.h"
57 #include "MagickCore/string-private.h"
58 #include "MagickCore/thread-private.h"
59 #include "MagickCore/token.h"
60 #include "MagickCore/utility.h"
61 #include "MagickCore/version.h"
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 % C h a n n e l F x I m a g e %
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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:
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
85 % For example, to create 3 grayscale images from the red, green, and blue
86 % channels of an image, use:
88 % -channel-fx "red; green; blue"
90 % A channel without an operation symbol implies separate (i.e, semicolon).
92 % The format of the ChannelFxImage method is:
94 % Image *ChannelFxImage(const Image *image,const char *expression,
95 % ExceptionInfo *exception)
97 % A description of each parameter follows:
101 % o expression: A channel expression.
103 % o exception: return any errors or warnings in this structure.
115 static inline size_t MagickMin(const size_t x,const size_t y)
122 static MagickBooleanType ChannelImage(Image *destination_image,
123 const PixelChannel destination_channel,const ChannelFx channel_op,
124 const Image *source_image,const PixelChannel source_channel,
125 const Quantum pixel,ExceptionInfo *exception)
142 source_view=AcquireVirtualCacheView(source_image,exception);
143 destination_view=AcquireAuthenticCacheView(destination_image,exception);
144 height=MagickMin(source_image->rows,destination_image->rows);
145 width=MagickMin(source_image->columns,destination_image->columns);
146 #if defined(MAGICKCORE_OPENMP_SUPPORT)
147 #pragma omp parallel for schedule(static,4) shared(status) \
148 magick_threads(source_image,source_image,height,1)
150 for (y=0; y < (ssize_t) height; y++)
156 register const Quantum
165 if (status == MagickFalse)
167 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
169 q=GetCacheViewAuthenticPixels(destination_view,0,y,
170 destination_image->columns,1,exception);
171 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
176 destination_traits=GetPixelChannelTraits(destination_image,
177 destination_channel);
178 source_traits=GetPixelChannelTraits(source_image,source_channel);
179 if ((destination_traits == UndefinedPixelTrait) ||
180 (source_traits == UndefinedPixelTrait))
182 for (x=0; x < (ssize_t) width; x++)
184 if (channel_op == AssignChannelOp)
185 SetPixelChannel(destination_image,destination_channel,pixel,q);
187 SetPixelChannel(destination_image,destination_channel,
188 GetPixelChannel(source_image,source_channel,p),q);
189 p+=GetPixelChannels(source_image);
190 q+=GetPixelChannels(destination_image);
192 if (SyncCacheViewAuthenticPixels(destination_view,exception) == MagickFalse)
195 destination_view=DestroyCacheView(destination_view);
196 source_view=DestroyCacheView(source_view);
200 MagickExport Image *ChannelFxImage(const Image *image,const char *expression,
201 ExceptionInfo *exception)
203 #define ChannelFxImageTag "ChannelFx/Image"
212 token[MaxTextExtent];
236 assert(image != (Image *) NULL);
237 assert(image->signature == MagickSignature);
238 if (image->debug != MagickFalse)
239 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
240 assert(exception != (ExceptionInfo *) NULL);
241 assert(exception->signature == MagickSignature);
243 destination_image=CloneImage(source_image,0,0,MagickTrue,exception);
244 if (destination_image == (Image *) NULL)
245 return((Image *) NULL);
246 if (expression == (const char *) NULL)
247 return(destination_image);
248 destination_channel=RedPixelChannel;
249 channel_mask=UndefinedChannel;
251 p=(char *) expression;
252 GetMagickToken(p,&p,token);
253 channel_op=ExtractChannelOp;
254 for (channels=0; *token != '\0'; )
263 Interpret channel expression.
265 delete_channel=MagickFalse;
270 delete_channel=MagickTrue;
271 GetMagickToken(p,&p,token);
276 destination_channel=(PixelChannel) ((ssize_t) destination_channel+1);
277 GetMagickToken(p,&p,token);
282 if (GetNextImageInList(source_image) != (Image *) NULL)
283 source_image=GetNextImageInList(source_image);
285 source_image=GetFirstImageInList(source_image);
286 GetMagickToken(p,&p,token);
294 SetPixelChannelMask(destination_image,channel_mask);
295 if ((channel_op == ExtractChannelOp) && (channels == 1))
296 (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
297 status=SetImageStorageClass(destination_image,DirectClass,exception);
298 if (status == MagickFalse)
300 destination_image=DestroyImageList(destination_image);
301 return(destination_image);
303 canvas=CloneImage(source_image,0,0,MagickTrue,exception);
304 if (canvas == (Image *) NULL)
306 destination_image=DestroyImageList(destination_image);
307 return(destination_image);
309 AppendImageToList(&destination_image,canvas);
310 destination_image=GetLastImageInList(destination_image);
311 GetMagickToken(p,&p,token);
313 destination_channel=RedPixelChannel;
314 channel_mask=UndefinedChannel;
320 i=ParsePixelChannelOption(token);
323 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
324 "UnrecognizedChannelType","`%s'",token);
325 destination_image=DestroyImageList(destination_image);
326 return(destination_image);
328 source_channel=(PixelChannel) i;
329 channel_op=ExtractChannelOp;
330 GetMagickToken(p,&p,token);
333 channel_op=ExchangeChannelOp;
334 GetMagickToken(p,&p,token);
338 if (channel_op != ExchangeChannelOp)
339 channel_op=AssignChannelOp;
340 GetMagickToken(p,&p,token);
344 if (channel_op != ExchangeChannelOp)
345 channel_op=TransferChannelOp;
346 GetMagickToken(p,&p,token);
350 case AssignChannelOp:
352 pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0);
353 GetMagickToken(p,&p,token);
356 case ExchangeChannelOp:
361 i=ParsePixelChannelOption(token);
364 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
365 "UnrecognizedChannelType","`%s'",token);
366 destination_image=DestroyImageList(destination_image);
367 return(destination_image);
369 destination_channel=(PixelChannel) i;
370 if ((source_channel >= GetPixelChannels(image)) ||
371 (destination_channel >= GetPixelChannels(image)))
373 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
374 "NoSuchImageChannel","`%s'",token);
375 destination_image=DestroyImageList(destination_image);
376 return(destination_image);
378 channel_map=destination_image->channel_map[destination_channel];
379 destination_image->channel_map[destination_channel]=
380 destination_image->channel_map[source_channel];
381 destination_image->channel_map[source_channel]=channel_map;
384 case TransferChannelOp:
386 i=ParsePixelChannelOption(token);
389 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
390 "UnrecognizedChannelType","`%s'",token);
391 destination_image=DestroyImageList(destination_image);
392 return(destination_image);
394 destination_channel=(PixelChannel) i;
395 switch (destination_channel)
397 case RedPixelChannel:
398 case GreenPixelChannel:
399 case BluePixelChannel:
400 case BlackPixelChannel:
401 case IndexPixelChannel:
403 case AlphaPixelChannel:
405 destination_image->alpha_trait=BlendPixelTrait;
408 case ReadMaskPixelChannel:
410 destination_image->read_mask=MagickTrue;
413 case WriteMaskPixelChannel:
415 destination_image->write_mask=MagickTrue;
418 case MetaPixelChannel:
421 (void) SetPixelMetaChannels(destination_image,(size_t) (i-
422 GetPixelChannels(destination_image)+1),exception);
426 channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token));
427 if (((channels >= 1) || (destination_channel >= 1)) &&
428 (IsGrayColorspace(destination_image->colorspace) != MagickFalse))
429 (void) SetImageColorspace(destination_image,sRGBColorspace,exception);
430 GetMagickToken(p,&p,token);
436 status=ChannelImage(destination_image,destination_channel,channel_op,
437 source_image,source_channel,ClampToQuantum(pixel),exception);
438 if (status == MagickFalse)
440 destination_image=DestroyImageList(destination_image);
444 if (channel_op == ExchangeChannelOp)
446 status=ChannelImage(destination_image,source_channel,channel_op,
447 source_image,destination_channel,ClampToQuantum(pixel),exception);
448 if (status == MagickFalse)
450 destination_image=DestroyImageList(destination_image);
457 case ExtractChannelOp:
459 if (delete_channel == MagickFalse)
460 channel_mask=(ChannelType) (channel_mask |
461 (1 << destination_channel));
463 channel_mask=(ChannelType) (channel_mask &~
464 (1 << destination_channel));
465 destination_channel=(PixelChannel) (destination_channel+1);
471 status=SetImageProgress(source_image,ChannelFxImageTag,p-expression,
473 if (status == MagickFalse)
476 SetPixelChannelMask(destination_image,channel_mask);
477 if ((channel_op == ExtractChannelOp) && (channels == 1))
478 (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
479 status=SetImageStorageClass(destination_image,DirectClass,exception);
480 if (status == MagickFalse)
482 destination_image=GetLastImageInList(destination_image);
483 return((Image *) NULL);
485 return(GetFirstImageInList(destination_image));
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 % C o m b i n e I m a g e s %
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499 % CombineImages() combines one or more images into a single image. The
500 % grayscale value of the pixels of each image in the sequence is assigned in
501 % order to the specified channels of the combined image. The typical
502 % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
504 % The format of the CombineImages method is:
506 % Image *CombineImages(const Image *images,const ColorspaceType colorspace,
507 % ExceptionInfo *exception)
509 % A description of each parameter follows:
511 % o images: the image sequence.
513 % o colorspace: the image colorspace.
515 % o exception: return any errors or warnings in this structure.
518 MagickExport Image *CombineImages(const Image *image,
519 const ColorspaceType colorspace,ExceptionInfo *exception)
521 #define CombineImageTag "Combine/Image"
539 Ensure the image are the same size.
541 assert(image != (const Image *) NULL);
542 assert(image->signature == MagickSignature);
543 if (image->debug != MagickFalse)
544 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
545 assert(exception != (ExceptionInfo *) NULL);
546 assert(exception->signature == MagickSignature);
547 combine_image=CloneImage(image,0,0,MagickTrue,exception);
548 if (combine_image == (Image *) NULL)
549 return((Image *) NULL);
550 if (SetImageStorageClass(combine_image,DirectClass,exception) == MagickFalse)
552 combine_image=DestroyImage(combine_image);
553 return((Image *) NULL);
555 (void) SetImageColorspace(combine_image,colorspace,exception);
556 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
557 combine_image->alpha_trait=BlendPixelTrait;
563 combine_view=AcquireAuthenticCacheView(combine_image,exception);
564 for (y=0; y < (ssize_t) combine_image->rows; y++)
575 register const Quantum
584 if (status == MagickFalse)
586 pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
588 if (pixels == (Quantum *) NULL)
594 for (i=0; i < (ssize_t) GetPixelChannels(combine_image); i++)
599 PixelChannel channel=GetPixelChannelChannel(combine_image,i);
600 PixelTrait traits=GetPixelChannelTraits(combine_image,channel);
601 if (traits == UndefinedPixelTrait)
603 if (next == (Image *) NULL)
605 image_view=AcquireVirtualCacheView(next,exception);
606 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
607 if (p == (const Quantum *) NULL)
610 for (x=0; x < (ssize_t) combine_image->columns; x++)
612 if (x < (ssize_t) next->columns)
614 q[i]=GetPixelGray(next,p);
615 p+=GetPixelChannels(next);
617 q+=GetPixelChannels(combine_image);
619 image_view=DestroyCacheView(image_view);
620 next=GetNextImageInList(next);
622 if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
624 if (image->progress_monitor != (MagickProgressMonitor) NULL)
629 proceed=SetImageProgress(image,CombineImageTag,progress++,
630 combine_image->rows);
631 if (proceed == MagickFalse)
635 combine_view=DestroyCacheView(combine_view);
636 if (status == MagickFalse)
637 combine_image=DestroyImage(combine_image);
638 return(combine_image);
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 % G e t I m a g e A l p h a C h a n n e l %
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 % GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
653 % not activated. That is, the image is RGB rather than RGBA or CMYK rather
656 % The format of the GetImageAlphaChannel method is:
658 % MagickBooleanType GetImageAlphaChannel(const Image *image)
660 % A description of each parameter follows:
662 % o image: the image.
665 MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
667 assert(image != (const Image *) NULL);
668 if (image->debug != MagickFalse)
669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
670 assert(image->signature == MagickSignature);
671 return(image->alpha_trait == BlendPixelTrait ? MagickTrue : MagickFalse);
675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % S e p a r a t e I m a g e %
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685 % SeparateImage() separates a channel from the image and returns it as a
688 % The format of the SeparateImage method is:
690 % Image *SeparateImage(const Image *image,const ChannelType channel,
691 % ExceptionInfo *exception)
693 % A description of each parameter follows:
695 % o image: the image.
697 % o channel: the image channel.
699 % o exception: return any errors or warnings in this structure.
702 MagickExport Image *SeparateImage(const Image *image,
703 const ChannelType channel_type,ExceptionInfo *exception)
705 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
706 #define SeparateImageTag "Separate/Image"
725 Initialize separate image attributes.
727 assert(image != (Image *) NULL);
728 assert(image->signature == MagickSignature);
729 if (image->debug != MagickFalse)
730 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
731 assert(exception != (ExceptionInfo *) NULL);
732 assert(exception->signature == MagickSignature);
733 separate_image=CloneImage(image,image->columns,image->rows,MagickTrue,
735 if (separate_image == (Image *) NULL)
736 return((Image *) NULL);
737 if (SetImageStorageClass(separate_image,DirectClass,exception) == MagickFalse)
739 separate_image=DestroyImage(separate_image);
740 return((Image *) NULL);
742 (void) SetImageColorspace(separate_image,GRAYColorspace,exception);
743 separate_image->alpha_trait=UndefinedPixelTrait;
749 image_view=AcquireVirtualCacheView(image,exception);
750 separate_view=AcquireAuthenticCacheView(separate_image,exception);
751 #if defined(MAGICKCORE_OPENMP_SUPPORT)
752 #pragma omp parallel for schedule(static,4) shared(progress,status) \
753 magick_threads(image,image,image->rows,1)
755 for (y=0; y < (ssize_t) image->rows; y++)
757 register const Quantum
766 if (status == MagickFalse)
768 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
769 q=QueueCacheViewAuthenticPixels(separate_view,0,y,separate_image->columns,1,
771 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
776 for (x=0; x < (ssize_t) image->columns; x++)
781 if (GetPixelReadMask(image,p) == 0)
783 p+=GetPixelChannels(image);
784 q+=GetPixelChannels(separate_image);
787 SetPixelChannel(separate_image,GrayPixelChannel,0,q);
788 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
790 PixelChannel channel=GetPixelChannelChannel(image,i);
791 PixelTrait traits=GetPixelChannelTraits(image,channel);
792 if ((traits == UndefinedPixelTrait) ||
793 (GetChannelBit(channel_type,channel) == 0))
795 SetPixelChannel(separate_image,GrayPixelChannel,p[i],q);
797 p+=GetPixelChannels(image);
798 q+=GetPixelChannels(separate_image);
800 if (SyncCacheViewAuthenticPixels(separate_view,exception) == MagickFalse)
802 if (image->progress_monitor != (MagickProgressMonitor) NULL)
807 #if defined(MAGICKCORE_OPENMP_SUPPORT)
808 #pragma omp critical (MagickCore_SeparateImage)
810 proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
811 if (proceed == MagickFalse)
815 separate_view=DestroyCacheView(separate_view);
816 image_view=DestroyCacheView(image_view);
817 if (status == MagickFalse)
818 separate_image=DestroyImage(separate_image);
819 return(separate_image);
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 % S e p a r a t e I m a g e s %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % SeparateImages() returns a separate grayscale image for each channel
836 % The format of the SeparateImages method is:
838 % Image *SeparateImages(const Image *image,ExceptionInfo *exception)
840 % A description of each parameter follows:
842 % o image: the image.
844 % o exception: return any errors or warnings in this structure.
847 MagickExport Image *SeparateImages(const Image *image,ExceptionInfo *exception)
856 assert(image != (Image *) NULL);
857 assert(image->signature == MagickSignature);
858 if (image->debug != MagickFalse)
859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
860 images=NewImageList();
861 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
863 PixelChannel channel=GetPixelChannelChannel(image,i);
864 PixelTrait traits=GetPixelChannelTraits(image,channel);
865 if ((traits == UndefinedPixelTrait) ||
866 ((traits & UpdatePixelTrait) == 0))
868 separate_image=SeparateImage(image,(ChannelType) (1 << channel),exception);
869 if (separate_image != (Image *) NULL)
870 AppendImageToList(&images,separate_image);
872 if (images == (Image *) NULL)
873 images=SeparateImage(image,UndefinedChannel,exception);
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882 % S e t I m a g e A l p h a C h a n n e l %
886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888 % SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
891 % The format of the SetImageAlphaChannel method is:
893 % MagickBooleanType SetImageAlphaChannel(Image *image,
894 % const AlphaChannelOption alpha_type,ExceptionInfo *exception)
896 % A description of each parameter follows:
898 % o image: the image.
900 % o alpha_type: The alpha channel type: ActivateAlphaChannel,
901 % CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
902 % OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel, and
903 % TransparentAlphaChannel.
905 % o exception: return any errors or warnings in this structure.
909 static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p,
910 const double alpha,const Quantum *q,const double beta,
922 Compose pixel p over pixel q with the given alpha.
924 Sa=QuantumScale*alpha;
925 Da=QuantumScale*beta,
926 gamma=Sa*(-Da)+Sa+Da;
927 gamma=PerceptibleReciprocal(gamma);
928 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
930 PixelChannel channel=GetPixelChannelChannel(image,i);
931 PixelTrait traits=GetPixelChannelTraits(image,channel);
932 if (traits == UndefinedPixelTrait)
936 case RedPixelChannel:
938 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
939 (double) p->red,alpha));
942 case GreenPixelChannel:
944 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
945 (double) p->green,alpha));
948 case BluePixelChannel:
950 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
951 (double) p->blue,alpha));
954 case BlackPixelChannel:
956 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
957 (double) p->black,alpha));
960 case AlphaPixelChannel:
962 composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
971 MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
972 const AlphaChannelOption alpha_type,ExceptionInfo *exception)
977 assert(image != (Image *) NULL);
978 if (image->debug != MagickFalse)
979 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
980 assert(image->signature == MagickSignature);
984 case ActivateAlphaChannel:
986 image->alpha_trait=BlendPixelTrait;
989 case BackgroundAlphaChannel:
998 Set transparent pixels to background color.
1000 if (image->alpha_trait != BlendPixelTrait)
1002 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1004 image_view=AcquireAuthenticCacheView(image,exception);
1005 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1006 #pragma omp parallel for schedule(static,4) shared(status) \
1007 magick_threads(image,image,image->rows,1)
1009 for (y=0; y < (ssize_t) image->rows; y++)
1017 if (status == MagickFalse)
1019 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1021 if (q == (Quantum *) NULL)
1026 for (x=0; x < (ssize_t) image->columns; x++)
1028 if (GetPixelAlpha(image,q) == TransparentAlpha)
1030 SetPixelInfoPixel(image,&image->background_color,q);
1031 SetPixelChannel(image,AlphaPixelChannel,TransparentAlpha,q);
1033 q+=GetPixelChannels(image);
1035 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1038 image_view=DestroyCacheView(image_view);
1041 case CopyAlphaChannel:
1042 case ShapeAlphaChannel:
1045 Copy pixel intensity to the alpha channel.
1047 status=CompositeImage(image,image,IntensityCompositeOp,MagickTrue,0,0,
1049 if (alpha_type == ShapeAlphaChannel)
1050 (void) LevelImageColors(image,&image->background_color,
1051 &image->background_color,MagickTrue,exception);
1054 case DeactivateAlphaChannel:
1056 image->alpha_trait=CopyPixelTrait;
1059 case ExtractAlphaChannel:
1061 status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0,
1063 image->alpha_trait=CopyPixelTrait;
1066 case OpaqueAlphaChannel:
1068 status=SetImageAlpha(image,OpaqueAlpha,exception);
1071 case RemoveAlphaChannel:
1080 Remove transparency.
1082 if (image->alpha_trait != BlendPixelTrait)
1084 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1086 image_view=AcquireAuthenticCacheView(image,exception);
1087 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1088 #pragma omp parallel for schedule(static,4) shared(status) \
1089 magick_threads(image,image,image->rows,1)
1091 for (y=0; y < (ssize_t) image->rows; y++)
1099 if (status == MagickFalse)
1101 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1103 if (q == (Quantum *) NULL)
1108 for (x=0; x < (ssize_t) image->columns; x++)
1110 FlattenPixelInfo(image,&image->background_color,
1111 image->background_color.alpha,q,(double)
1112 GetPixelAlpha(image,q),q);
1113 q+=GetPixelChannels(image);
1115 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1118 image_view=DestroyCacheView(image_view);
1119 image->alpha_trait=image->background_color.alpha_trait;
1122 case SetAlphaChannel:
1124 if (image->alpha_trait != BlendPixelTrait)
1125 status=SetImageAlpha(image,OpaqueAlpha,exception);
1128 case TransparentAlphaChannel:
1130 status=SetImageAlpha(image,TransparentAlpha,exception);
1133 case UndefinedAlphaChannel:
1136 if (status == MagickFalse)
1138 return(SyncImagePixelCache(image,exception));