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-2014 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/channel.h"
46 #include "MagickCore/colorspace-private.h"
47 #include "MagickCore/composite-private.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"
53 #include "MagickCore/monitor-private.h"
54 #include "MagickCore/option.h"
55 #include "MagickCore/pixel-accessor.h"
56 #include "MagickCore/pixel-private.h"
57 #include "MagickCore/resource_.h"
58 #include "MagickCore/string-private.h"
59 #include "MagickCore/thread-private.h"
60 #include "MagickCore/token.h"
61 #include "MagickCore/utility.h"
62 #include "MagickCore/version.h"
65 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 % C h a n n e l F x I m a g e %
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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:
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
86 % For example, to create 3 grayscale images from the red, green, and blue
87 % channels of an image, use:
89 % -channel-fx "red; green; blue"
91 % A channel without an operation symbol implies separate (i.e, semicolon).
93 % The format of the ChannelFxImage method is:
95 % Image *ChannelFxImage(const Image *image,const char *expression,
96 % ExceptionInfo *exception)
98 % A description of each parameter follows:
100 % o image: the image.
102 % o expression: A channel expression.
104 % o exception: return any errors or warnings in this structure.
116 static inline size_t MagickMin(const size_t x,const size_t y)
123 static MagickBooleanType ChannelImage(Image *destination_image,
124 const PixelChannel destination_channel,const ChannelFx channel_op,
125 const Image *source_image,const PixelChannel source_channel,
126 const Quantum pixel,ExceptionInfo *exception)
143 source_view=AcquireVirtualCacheView(source_image,exception);
144 destination_view=AcquireAuthenticCacheView(destination_image,exception);
145 height=MagickMin(source_image->rows,destination_image->rows);
146 width=MagickMin(source_image->columns,destination_image->columns);
147 #if defined(MAGICKCORE_OPENMP_SUPPORT)
148 #pragma omp parallel for schedule(static,4) shared(status) \
149 magick_threads(source_image,source_image,height,1)
151 for (y=0; y < (ssize_t) height; y++)
157 register const Quantum
166 if (status == MagickFalse)
168 p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
170 q=GetCacheViewAuthenticPixels(destination_view,0,y,
171 destination_image->columns,1,exception);
172 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
177 destination_traits=GetPixelChannelTraits(destination_image,
178 destination_channel);
179 source_traits=GetPixelChannelTraits(source_image,source_channel);
180 if ((destination_traits == UndefinedPixelTrait) ||
181 (source_traits == UndefinedPixelTrait))
183 for (x=0; x < (ssize_t) width; x++)
185 if (channel_op == AssignChannelOp)
186 SetPixelChannel(destination_image,destination_channel,pixel,q);
188 SetPixelChannel(destination_image,destination_channel,
189 GetPixelChannel(source_image,source_channel,p),q);
190 p+=GetPixelChannels(source_image);
191 q+=GetPixelChannels(destination_image);
193 if (SyncCacheViewAuthenticPixels(destination_view,exception) == MagickFalse)
196 destination_view=DestroyCacheView(destination_view);
197 source_view=DestroyCacheView(source_view);
201 MagickExport Image *ChannelFxImage(const Image *image,const char *expression,
202 ExceptionInfo *exception)
204 #define ChannelFxImageTag "ChannelFx/Image"
213 token[MaxTextExtent];
237 assert(image != (Image *) NULL);
238 assert(image->signature == MagickSignature);
239 if (image->debug != MagickFalse)
240 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
241 assert(exception != (ExceptionInfo *) NULL);
242 assert(exception->signature == MagickSignature);
244 destination_image=CloneImage(source_image,0,0,MagickTrue,exception);
245 if (destination_image == (Image *) NULL)
246 return((Image *) NULL);
247 if (expression == (const char *) NULL)
248 return(destination_image);
249 destination_channel=RedPixelChannel;
250 channel_mask=UndefinedChannel;
252 p=(char *) expression;
253 GetMagickToken(p,&p,token);
254 channel_op=ExtractChannelOp;
255 for (channels=0; *token != '\0'; )
261 Interpret channel expression.
267 GetMagickToken(p,&p,token);
272 if (GetNextImageInList(source_image) != (Image *) NULL)
273 source_image=GetNextImageInList(source_image);
275 source_image=GetFirstImageInList(source_image);
276 GetMagickToken(p,&p,token);
284 SetPixelChannelMask(destination_image,channel_mask);
285 if ((channel_op == ExtractChannelOp) && (channels == 1))
286 (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
287 status=SetImageStorageClass(destination_image,DirectClass,exception);
288 if (status == MagickFalse)
290 destination_image=DestroyImageList(destination_image);
291 return(destination_image);
293 canvas=CloneImage(source_image,0,0,MagickTrue,exception);
294 if (canvas == (Image *) NULL)
296 destination_image=DestroyImageList(destination_image);
297 return(destination_image);
299 AppendImageToList(&destination_image,canvas);
300 destination_image=GetLastImageInList(destination_image);
301 GetMagickToken(p,&p,token);
303 destination_channel=RedPixelChannel;
304 channel_mask=UndefinedChannel;
310 i=ParsePixelChannelOption(token);
313 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
314 "UnrecognizedChannelType","`%s'",token);
315 destination_image=DestroyImageList(destination_image);
316 return(destination_image);
318 source_channel=(PixelChannel) i;
319 channel_op=ExtractChannelOp;
320 GetMagickToken(p,&p,token);
323 channel_op=ExchangeChannelOp;
324 GetMagickToken(p,&p,token);
328 if (channel_op != ExchangeChannelOp)
329 channel_op=AssignChannelOp;
330 GetMagickToken(p,&p,token);
334 if (channel_op != ExchangeChannelOp)
335 channel_op=TransferChannelOp;
336 GetMagickToken(p,&p,token);
340 case AssignChannelOp:
342 pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0);
343 GetMagickToken(p,&p,token);
346 case ExchangeChannelOp:
347 case TransferChannelOp:
349 i=ParsePixelChannelOption(token);
352 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
353 "UnrecognizedChannelType","`%s'",token);
354 destination_image=DestroyImageList(destination_image);
355 return(destination_image);
357 destination_channel=(PixelChannel) i;
358 switch (destination_channel)
360 case RedPixelChannel:
361 case GreenPixelChannel:
362 case BluePixelChannel:
363 case BlackPixelChannel:
364 case IndexPixelChannel:
366 case AlphaPixelChannel:
368 destination_image->alpha_trait=BlendPixelTrait;
371 case ReadMaskPixelChannel:
373 destination_image->read_mask=MagickTrue;
376 case WriteMaskPixelChannel:
378 destination_image->write_mask=MagickTrue;
381 case MetaPixelChannel:
384 (void) SetPixelMetaChannels(destination_image,(size_t) (i-
385 GetPixelChannels(destination_image)+1),exception);
389 channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token));
390 if (((channels >= 1) || (destination_channel >= 1)) &&
391 (IsGrayColorspace(destination_image->colorspace) != MagickFalse))
392 (void) SetImageColorspace(destination_image,sRGBColorspace,exception);
393 GetMagickToken(p,&p,token);
399 status=ChannelImage(destination_image,destination_channel,channel_op,
400 source_image,source_channel,ClampToQuantum(pixel),exception);
401 if (status == MagickFalse)
403 destination_image=DestroyImageList(destination_image);
407 if (channel_op == ExchangeChannelOp)
409 status=ChannelImage(destination_image,source_channel,channel_op,
410 source_image,destination_channel,ClampToQuantum(pixel),exception);
411 if (status == MagickFalse)
413 destination_image=DestroyImageList(destination_image);
420 case ExtractChannelOp:
422 channel_mask=(ChannelType) (channel_mask | (1 << destination_channel));
423 destination_channel=(PixelChannel) (destination_channel+1);
429 status=SetImageProgress(source_image,ChannelFxImageTag,p-expression,
431 if (status == MagickFalse)
434 SetPixelChannelMask(destination_image,channel_mask);
435 if ((channel_op == ExtractChannelOp) && (channels == 1))
436 (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
437 status=SetImageStorageClass(destination_image,DirectClass,exception);
438 if (status == MagickFalse)
440 destination_image=GetLastImageInList(destination_image);
441 return((Image *) NULL);
443 return(GetFirstImageInList(destination_image));
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 % C o m b i n e I m a g e s %
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % CombineImages() combines one or more images into a single image. The
458 % grayscale value of the pixels of each image in the sequence is assigned in
459 % order to the specified channels of the combined image. The typical
460 % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
462 % The format of the CombineImages method is:
464 % Image *CombineImages(const Image *images,const ColorspaceType colorspace,
465 % ExceptionInfo *exception)
467 % A description of each parameter follows:
469 % o images: the image sequence.
471 % o colorspace: the image colorspace.
473 % o exception: return any errors or warnings in this structure.
476 MagickExport Image *CombineImages(const Image *image,
477 const ColorspaceType colorspace,ExceptionInfo *exception)
479 #define CombineImageTag "Combine/Image"
497 Ensure the image are the same size.
499 assert(image != (const Image *) NULL);
500 assert(image->signature == MagickSignature);
501 if (image->debug != MagickFalse)
502 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
503 assert(exception != (ExceptionInfo *) NULL);
504 assert(exception->signature == MagickSignature);
505 combine_image=CloneImage(image,0,0,MagickTrue,exception);
506 if (combine_image == (Image *) NULL)
507 return((Image *) NULL);
508 if (SetImageStorageClass(combine_image,DirectClass,exception) == MagickFalse)
510 combine_image=DestroyImage(combine_image);
511 return((Image *) NULL);
513 (void) SetImageColorspace(combine_image,colorspace,exception);
514 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
515 combine_image->alpha_trait=BlendPixelTrait;
521 combine_view=AcquireAuthenticCacheView(combine_image,exception);
522 for (y=0; y < (ssize_t) combine_image->rows; y++)
533 register const Quantum
542 if (status == MagickFalse)
544 pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
546 if (pixels == (Quantum *) NULL)
552 for (i=0; i < (ssize_t) GetPixelChannels(combine_image); i++)
557 PixelChannel channel=GetPixelChannelChannel(combine_image,i);
558 PixelTrait traits=GetPixelChannelTraits(combine_image,channel);
559 if (traits == UndefinedPixelTrait)
561 if (next == (Image *) NULL)
563 image_view=AcquireVirtualCacheView(next,exception);
564 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
565 if (p == (const Quantum *) NULL)
568 for (x=0; x < (ssize_t) combine_image->columns; x++)
570 if (x < (ssize_t) next->columns)
572 q[i]=GetPixelGray(next,p);
573 p+=GetPixelChannels(next);
575 q+=GetPixelChannels(combine_image);
577 image_view=DestroyCacheView(image_view);
578 next=GetNextImageInList(next);
580 if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
582 if (image->progress_monitor != (MagickProgressMonitor) NULL)
587 proceed=SetImageProgress(image,CombineImageTag,progress++,
588 combine_image->rows);
589 if (proceed == MagickFalse)
593 combine_view=DestroyCacheView(combine_view);
594 if (status == MagickFalse)
595 combine_image=DestroyImage(combine_image);
596 return(combine_image);
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 % G e t I m a g e A l p h a C h a n n e l %
608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 % GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
611 % not activated. That is, the image is RGB rather than RGBA or CMYK rather
614 % The format of the GetImageAlphaChannel method is:
616 % MagickBooleanType GetImageAlphaChannel(const Image *image)
618 % A description of each parameter follows:
620 % o image: the image.
623 MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
625 assert(image != (const Image *) NULL);
626 if (image->debug != MagickFalse)
627 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
628 assert(image->signature == MagickSignature);
629 return(image->alpha_trait == BlendPixelTrait ? MagickTrue : MagickFalse);
633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637 % S e p a r a t e I m a g e %
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 % SeparateImage() separates a channel from the image and returns it as a
646 % The format of the SeparateImage method is:
648 % Image *SeparateImage(const Image *image,const ChannelType channel,
649 % ExceptionInfo *exception)
651 % A description of each parameter follows:
653 % o image: the image.
655 % o channel: the image channel.
657 % o exception: return any errors or warnings in this structure.
660 MagickExport Image *SeparateImage(const Image *image,
661 const ChannelType channel_type,ExceptionInfo *exception)
663 #define GetChannelBit(mask,bit) (((size_t) (mask) >> (size_t) (bit)) & 0x01)
664 #define SeparateImageTag "Separate/Image"
683 Initialize separate image attributes.
685 assert(image != (Image *) NULL);
686 assert(image->signature == MagickSignature);
687 if (image->debug != MagickFalse)
688 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
689 assert(exception != (ExceptionInfo *) NULL);
690 assert(exception->signature == MagickSignature);
691 separate_image=CloneImage(image,image->columns,image->rows,MagickTrue,
693 if (separate_image == (Image *) NULL)
694 return((Image *) NULL);
695 if (SetImageStorageClass(separate_image,DirectClass,exception) == MagickFalse)
697 separate_image=DestroyImage(separate_image);
698 return((Image *) NULL);
700 (void) SetImageColorspace(separate_image,GRAYColorspace,exception);
701 separate_image->alpha_trait=UndefinedPixelTrait;
707 image_view=AcquireVirtualCacheView(image,exception);
708 separate_view=AcquireAuthenticCacheView(separate_image,exception);
709 #if defined(MAGICKCORE_OPENMP_SUPPORT)
710 #pragma omp parallel for schedule(static,4) shared(progress,status) \
711 magick_threads(image,image,image->rows,1)
713 for (y=0; y < (ssize_t) image->rows; y++)
715 register const Quantum
724 if (status == MagickFalse)
726 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
727 q=QueueCacheViewAuthenticPixels(separate_view,0,y,separate_image->columns,1,
729 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
734 for (x=0; x < (ssize_t) image->columns; x++)
739 if (GetPixelReadMask(image,p) == 0)
741 SetPixelBackgoundColor(separate_image,q);
742 p+=GetPixelChannels(image);
743 q+=GetPixelChannels(separate_image);
746 SetPixelChannel(separate_image,GrayPixelChannel,0,q);
747 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
749 PixelChannel channel=GetPixelChannelChannel(image,i);
750 PixelTrait traits=GetPixelChannelTraits(image,channel);
751 if ((traits == UndefinedPixelTrait) ||
752 (GetChannelBit(channel_type,channel) == 0))
754 SetPixelChannel(separate_image,GrayPixelChannel,p[i],q);
756 p+=GetPixelChannels(image);
757 q+=GetPixelChannels(separate_image);
759 if (SyncCacheViewAuthenticPixels(separate_view,exception) == MagickFalse)
761 if (image->progress_monitor != (MagickProgressMonitor) NULL)
766 #if defined(MAGICKCORE_OPENMP_SUPPORT)
767 #pragma omp critical (MagickCore_SeparateImage)
769 proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
770 if (proceed == MagickFalse)
774 separate_view=DestroyCacheView(separate_view);
775 image_view=DestroyCacheView(image_view);
776 if (status == MagickFalse)
777 separate_image=DestroyImage(separate_image);
778 return(separate_image);
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786 % S e p a r a t e I m a g e s %
790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792 % SeparateImages() returns a separate grayscale image for each channel
795 % The format of the SeparateImages method is:
797 % Image *SeparateImages(const Image *image,ExceptionInfo *exception)
799 % A description of each parameter follows:
801 % o image: the image.
803 % o exception: return any errors or warnings in this structure.
806 MagickExport Image *SeparateImages(const Image *image,ExceptionInfo *exception)
815 assert(image != (Image *) NULL);
816 assert(image->signature == MagickSignature);
817 if (image->debug != MagickFalse)
818 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
819 images=NewImageList();
820 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
822 PixelChannel channel=GetPixelChannelChannel(image,i);
823 PixelTrait traits=GetPixelChannelTraits(image,channel);
824 if ((traits == UndefinedPixelTrait) ||
825 ((traits & UpdatePixelTrait) == 0))
827 separate_image=SeparateImage(image,(ChannelType) (1 << channel),exception);
828 if (separate_image != (Image *) NULL)
829 AppendImageToList(&images,separate_image);
831 if (images == (Image *) NULL)
832 images=SeparateImage(image,UndefinedChannel,exception);
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 % S e t I m a g e A l p h a C h a n n e l %
845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847 % SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
850 % The format of the SetImageAlphaChannel method is:
852 % MagickBooleanType SetImageAlphaChannel(Image *image,
853 % const AlphaChannelOption alpha_type,ExceptionInfo *exception)
855 % A description of each parameter follows:
857 % o image: the image.
859 % o alpha_type: The alpha channel type: ActivateAlphaChannel,
860 % CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
861 % OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel, and
862 % TransparentAlphaChannel.
864 % o exception: return any errors or warnings in this structure.
868 static inline void FlattenPixelInfo(const Image *image,const PixelInfo *p,
869 const double alpha,const Quantum *q,const double beta,
881 Compose pixel p over pixel q with the given alpha.
883 Sa=QuantumScale*alpha;
884 Da=QuantumScale*beta,
885 gamma=Sa*(-Da)+Sa+Da;
886 gamma=PerceptibleReciprocal(gamma);
887 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
889 PixelChannel channel=GetPixelChannelChannel(image,i);
890 PixelTrait traits=GetPixelChannelTraits(image,channel);
891 if (traits == UndefinedPixelTrait)
895 case RedPixelChannel:
897 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
898 (double) p->red,alpha));
901 case GreenPixelChannel:
903 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
904 (double) p->green,alpha));
907 case BluePixelChannel:
909 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
910 (double) p->blue,alpha));
913 case BlackPixelChannel:
915 composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
916 (double) p->black,alpha));
919 case AlphaPixelChannel:
921 composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
930 MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
931 const AlphaChannelOption alpha_type,ExceptionInfo *exception)
936 assert(image != (Image *) NULL);
937 if (image->debug != MagickFalse)
938 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
939 assert(image->signature == MagickSignature);
943 case ActivateAlphaChannel:
945 image->alpha_trait=BlendPixelTrait;
948 case BackgroundAlphaChannel:
957 Set transparent pixels to background color.
959 if (image->alpha_trait != BlendPixelTrait)
961 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
963 image_view=AcquireAuthenticCacheView(image,exception);
964 #if defined(MAGICKCORE_OPENMP_SUPPORT)
965 #pragma omp parallel for schedule(static,4) shared(status) \
966 magick_threads(image,image,image->rows,1)
968 for (y=0; y < (ssize_t) image->rows; y++)
976 if (status == MagickFalse)
978 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
980 if (q == (Quantum *) NULL)
985 for (x=0; x < (ssize_t) image->columns; x++)
987 if (GetPixelAlpha(image,q) == TransparentAlpha)
989 SetPixelInfoPixel(image,&image->background_color,q);
990 SetPixelChannel(image,AlphaPixelChannel,TransparentAlpha,q);
992 q+=GetPixelChannels(image);
994 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
997 image_view=DestroyCacheView(image_view);
1000 case CopyAlphaChannel:
1001 case ShapeAlphaChannel:
1004 Copy pixel intensity to the alpha channel.
1006 status=CompositeImage(image,image,IntensityCompositeOp,MagickTrue,0,0,
1008 if (alpha_type == ShapeAlphaChannel)
1009 (void) LevelImageColors(image,&image->background_color,
1010 &image->background_color,MagickTrue,exception);
1013 case DeactivateAlphaChannel:
1015 image->alpha_trait=CopyPixelTrait;
1018 case ExtractAlphaChannel:
1020 status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0,
1022 image->alpha_trait=CopyPixelTrait;
1025 case OpaqueAlphaChannel:
1027 status=SetImageAlpha(image,OpaqueAlpha,exception);
1030 case RemoveAlphaChannel:
1039 Remove transparency.
1041 if (image->alpha_trait != BlendPixelTrait)
1043 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1045 image_view=AcquireAuthenticCacheView(image,exception);
1046 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1047 #pragma omp parallel for schedule(static,4) shared(status) \
1048 magick_threads(image,image,image->rows,1)
1050 for (y=0; y < (ssize_t) image->rows; y++)
1058 if (status == MagickFalse)
1060 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1062 if (q == (Quantum *) NULL)
1067 for (x=0; x < (ssize_t) image->columns; x++)
1069 FlattenPixelInfo(image,&image->background_color,
1070 image->background_color.alpha,q,(double)
1071 GetPixelAlpha(image,q),q);
1072 q+=GetPixelChannels(image);
1074 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1077 image_view=DestroyCacheView(image_view);
1078 image->alpha_trait=image->background_color.alpha_trait;
1081 case SetAlphaChannel:
1083 if (image->alpha_trait != BlendPixelTrait)
1084 status=SetImageAlpha(image,OpaqueAlpha,exception);
1087 case TransparentAlphaChannel:
1089 status=SetImageAlpha(image,TransparentAlpha,exception);
1092 case UndefinedAlphaChannel:
1095 if (status == MagickFalse)
1097 return(SyncImagePixelCache(image,exception));