1d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy/*
2d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
4d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
5d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
6d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%               CCCC  H   H   AAA   N   N  N   N  EEEEE   L                   %
7d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%              C      H   H  A   A  NN  N  NN  N  E       L                   %
8bed32e2740deacf3f3818e376c0f0c6e52827387cristy%              C      HHHHH  AAAAA  N N N  N N N  EEE     L                   %
9d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%              C      H   H  A   A  N  NN  N  NN  E       L                   %
10d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%               CCCC  H   H  A   A  N   N  N   N  EEEEE   LLLLL               %
11d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
12d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
13d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                      MagickCore Image Channel Methods                       %
14d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
15d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
17d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                               December 2003                                 %
18d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
19d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
21d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  dedicated to making software imaging solutions freely available.           %
22d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
23d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  You may not use this file except in compliance with the License.  You may  %
24d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  obtain a copy of the License at                                            %
25d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
26d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%    http://www.imagemagick.org/script/license.php                            %
27d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
28d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  Unless required by applicable law or agreed to in writing, software        %
29d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
30d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  See the License for the specific language governing permissions and        %
32d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  limitations under the License.                                             %
33d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
34d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
36d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
37d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
38d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy*/
3945f56150f9154f7cd94cea2fda548c148861841ddirk
40d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy/*
41d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy  Include declarations.
42d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy*/
43d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy#include "MagickCore/studio.h"
448c8c916b144b0ffb092a820680a591c5899ec0decristy#include "MagickCore/cache-private.h"
45a8816141abbea86b37063416d144b8419be23642cristy#include "MagickCore/channel.h"
46c1119afdec2a8bee6a7e6296aab5921406226fb3cristy#include "MagickCore/colorspace-private.h"
478c8c916b144b0ffb092a820680a591c5899ec0decristy#include "MagickCore/composite-private.h"
488c8c916b144b0ffb092a820680a591c5899ec0decristy#include "MagickCore/enhance.h"
49a15140ffe282798c406b8ce865dd2c02519217e5cristy#include "MagickCore/image.h"
50a15140ffe282798c406b8ce865dd2c02519217e5cristy#include "MagickCore/list.h"
51a15140ffe282798c406b8ce865dd2c02519217e5cristy#include "MagickCore/log.h"
52ab272ac4f115daf25c032de9dbb49a399eebe49bcristy#include "MagickCore/monitor.h"
53ab272ac4f115daf25c032de9dbb49a399eebe49bcristy#include "MagickCore/monitor-private.h"
54a15140ffe282798c406b8ce865dd2c02519217e5cristy#include "MagickCore/option.h"
55ab272ac4f115daf25c032de9dbb49a399eebe49bcristy#include "MagickCore/pixel-accessor.h"
568c8c916b144b0ffb092a820680a591c5899ec0decristy#include "MagickCore/pixel-private.h"
57ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy#include "MagickCore/resource_.h"
588748f56d762a24a791ab3d4c36ef29a4e70e894acristy#include "MagickCore/string-private.h"
5916881e68c6165c6191fc44151a8a4320e3dd1ffdcristy#include "MagickCore/thread-private.h"
60a15140ffe282798c406b8ce865dd2c02519217e5cristy#include "MagickCore/token.h"
61d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy#include "MagickCore/utility.h"
62d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy#include "MagickCore/version.h"
6345f56150f9154f7cd94cea2fda548c148861841ddirk
64d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy/*
65d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
67d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
68d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
695f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%     C h a n n e l F x I m a g e                                             %
70d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
71d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
72d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%                                                                             %
73d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
755f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%  ChannelFxImage() applies a channel expression to the specified image.  The
765f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%  expression consists of one or more channels, either mnemonic or numeric (e.g.
775f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%  red, 1), separated by actions as follows:
78ab272ac4f115daf25c032de9dbb49a399eebe49bcristy%
79ab272ac4f115daf25c032de9dbb49a399eebe49bcristy%    <=>     exchange two channels (e.g. red<=>blue)
807ea920dc300fdc009f158d6db5d217790fdea4a9cristy%    =>      copy one channel to another channel (e.g. red=>green)
817ea920dc300fdc009f158d6db5d217790fdea4a9cristy%    =       assign a constant value to a channel (e.g. red=50%)
827ea920dc300fdc009f158d6db5d217790fdea4a9cristy%    ,       write new image channels in the specified order (e.g. red, green)
833c21361b9ba0dfbbaa484845b40f2dfab3fc8500cristy%    |       add a new output image for the next set of channel operations
843c21361b9ba0dfbbaa484845b40f2dfab3fc8500cristy%    ;       move to the next input image for the source of channel data
85ab272ac4f115daf25c032de9dbb49a399eebe49bcristy%
867ea920dc300fdc009f158d6db5d217790fdea4a9cristy%  For example, to create 3 grayscale images from the red, green, and blue
877ea920dc300fdc009f158d6db5d217790fdea4a9cristy%  channels of an image, use:
88ab272ac4f115daf25c032de9dbb49a399eebe49bcristy%
893c21361b9ba0dfbbaa484845b40f2dfab3fc8500cristy%    -channel-fx "red; green; blue"
907ea920dc300fdc009f158d6db5d217790fdea4a9cristy%
917ea920dc300fdc009f158d6db5d217790fdea4a9cristy%  A channel without an operation symbol implies separate (i.e, semicolon).
92d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
935f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%  The format of the ChannelFxImage method is:
94d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
955f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%      Image *ChannelFxImage(const Image *image,const char *expression,
965f257b2f02bdd982d9bbfe612f5bb1711608590ccristy%        ExceptionInfo *exception)
97d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
98d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%  A description of each parameter follows:
99d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
100ab272ac4f115daf25c032de9dbb49a399eebe49bcristy%    o image: the image.
101d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
102d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%    o expression: A channel expression.
103d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
104d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%    o exception: return any errors or warnings in this structure.
105d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy%
106d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy*/
107a15140ffe282798c406b8ce865dd2c02519217e5cristy
108a15140ffe282798c406b8ce865dd2c02519217e5cristytypedef enum
109a15140ffe282798c406b8ce865dd2c02519217e5cristy{
110a15140ffe282798c406b8ce865dd2c02519217e5cristy  ExtractChannelOp,
1118748f56d762a24a791ab3d4c36ef29a4e70e894acristy  AssignChannelOp,
112a15140ffe282798c406b8ce865dd2c02519217e5cristy  ExchangeChannelOp,
113a15140ffe282798c406b8ce865dd2c02519217e5cristy  TransferChannelOp
1145f257b2f02bdd982d9bbfe612f5bb1711608590ccristy} ChannelFx;
115a15140ffe282798c406b8ce865dd2c02519217e5cristy
116ab272ac4f115daf25c032de9dbb49a399eebe49bcristystatic MagickBooleanType ChannelImage(Image *destination_image,
1178748f56d762a24a791ab3d4c36ef29a4e70e894acristy  const PixelChannel destination_channel,const ChannelFx channel_op,
1183bb378ad21cab4b636aa9a089c9837eba0033ca1cristy  const Image *source_image,const PixelChannel source_channel,
1198748f56d762a24a791ab3d4c36ef29a4e70e894acristy  const Quantum pixel,ExceptionInfo *exception)
120ab272ac4f115daf25c032de9dbb49a399eebe49bcristy{
121ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  CacheView
122ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    *source_view,
123ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    *destination_view;
124ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
125ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  MagickBooleanType
126ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    status;
127ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
128ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  size_t
129ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy    height,
130ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy    width;
131ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
132ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  ssize_t
133ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    y;
134ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
135ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  status=MagickTrue;
13646ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  source_view=AcquireVirtualCacheView(source_image,exception);
13746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  destination_view=AcquireAuthenticCacheView(destination_image,exception);
138ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  height=MagickMin(source_image->rows,destination_image->rows);
139ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  width=MagickMin(source_image->columns,destination_image->columns);
140ab272ac4f115daf25c032de9dbb49a399eebe49bcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
1419a5a52fdbea9190e1c868ba9298a6f64d1c896d1cristy  #pragma omp parallel for schedule(static,4) shared(status) \
1425e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(source_image,source_image,height,1)
143ab272ac4f115daf25c032de9dbb49a399eebe49bcristy#endif
144ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  for (y=0; y < (ssize_t) height; y++)
145ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  {
1464ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    PixelTrait
1474ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      destination_traits,
1484ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      source_traits;
1494ee604053ad78f08a37a8b065dea1cec5c922fb0cristy
150ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    register const Quantum
15105d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
152ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
153ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    register Quantum
15405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
155ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
156ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    register ssize_t
157ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      x;
158ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
159ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    if (status == MagickFalse)
160ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      continue;
161ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    p=GetCacheViewVirtualPixels(source_view,0,y,source_image->columns,1,
162ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      exception);
1634ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    q=GetCacheViewAuthenticPixels(destination_view,0,y,
164ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      destination_image->columns,1,exception);
165ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
166ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      {
167ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        status=MagickFalse;
168ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        continue;
169ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      }
170cf1296eb467f83fd2106e51d2689ac0afc863ef8cristy    destination_traits=GetPixelChannelTraits(destination_image,
1714ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      destination_channel);
172cf1296eb467f83fd2106e51d2689ac0afc863ef8cristy    source_traits=GetPixelChannelTraits(source_image,source_channel);
1734ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    if ((destination_traits == UndefinedPixelTrait) ||
1744ee604053ad78f08a37a8b065dea1cec5c922fb0cristy        (source_traits == UndefinedPixelTrait))
1754ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      continue;
176ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    for (x=0; x < (ssize_t) width; x++)
177ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    {
1788748f56d762a24a791ab3d4c36ef29a4e70e894acristy      if (channel_op == AssignChannelOp)
1798748f56d762a24a791ab3d4c36ef29a4e70e894acristy        SetPixelChannel(destination_image,destination_channel,pixel,q);
1808748f56d762a24a791ab3d4c36ef29a4e70e894acristy      else
1814ee604053ad78f08a37a8b065dea1cec5c922fb0cristy        SetPixelChannel(destination_image,destination_channel,
1824ee604053ad78f08a37a8b065dea1cec5c922fb0cristy          GetPixelChannel(source_image,source_channel,p),q);
1834ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      p+=GetPixelChannels(source_image);
184ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      q+=GetPixelChannels(destination_image);
185ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    }
186ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    if (SyncCacheViewAuthenticPixels(destination_view,exception) == MagickFalse)
187ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      status=MagickFalse;
188ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  }
189ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  destination_view=DestroyCacheView(destination_view);
190ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  source_view=DestroyCacheView(source_view);
191ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  return(status);
192ab272ac4f115daf25c032de9dbb49a399eebe49bcristy}
193ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
1945f257b2f02bdd982d9bbfe612f5bb1711608590ccristyMagickExport Image *ChannelFxImage(const Image *image,const char *expression,
1955f257b2f02bdd982d9bbfe612f5bb1711608590ccristy  ExceptionInfo *exception)
196d04e7bfd3f183453b5c0f8e0a8fbb0a988a1d541cristy{
1975f257b2f02bdd982d9bbfe612f5bb1711608590ccristy#define ChannelFxImageTag  "ChannelFx/Image"
198ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
1995f257b2f02bdd982d9bbfe612f5bb1711608590ccristy  ChannelFx
200a15140ffe282798c406b8ce865dd2c02519217e5cristy    channel_op;
201a15140ffe282798c406b8ce865dd2c02519217e5cristy
202fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy  ChannelType
203fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy    channel_mask;
204fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy
2054ee604053ad78f08a37a8b065dea1cec5c922fb0cristy  char
206151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    token[MagickPathExtent];
2074ee604053ad78f08a37a8b065dea1cec5c922fb0cristy
208a15140ffe282798c406b8ce865dd2c02519217e5cristy  const char
209a15140ffe282798c406b8ce865dd2c02519217e5cristy    *p;
210a15140ffe282798c406b8ce865dd2c02519217e5cristy
211ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  const Image
212ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    *source_image;
213ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
2148748f56d762a24a791ab3d4c36ef29a4e70e894acristy  double
2158748f56d762a24a791ab3d4c36ef29a4e70e894acristy    pixel;
2168748f56d762a24a791ab3d4c36ef29a4e70e894acristy
217a15140ffe282798c406b8ce865dd2c02519217e5cristy  Image
218ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    *destination_image;
219a15140ffe282798c406b8ce865dd2c02519217e5cristy
2204ee604053ad78f08a37a8b065dea1cec5c922fb0cristy  MagickBooleanType
2214ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    status;
2224ee604053ad78f08a37a8b065dea1cec5c922fb0cristy
223a15140ffe282798c406b8ce865dd2c02519217e5cristy  PixelChannel
224ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    source_channel,
225ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    destination_channel;
226ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
227ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  ssize_t
228ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    channels;
229ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
230ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  assert(image != (Image *) NULL);
231e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
232ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  if (image->debug != MagickFalse)
233ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
234ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  assert(exception != (ExceptionInfo *) NULL);
235e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
236ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  source_image=image;
237ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  destination_image=CloneImage(source_image,0,0,MagickTrue,exception);
238ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  if (destination_image == (Image *) NULL)
239ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    return((Image *) NULL);
240ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  if (expression == (const char *) NULL)
241ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    return(destination_image);
242ab272ac4f115daf25c032de9dbb49a399eebe49bcristy  destination_channel=RedPixelChannel;
243fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy  channel_mask=UndefinedChannel;
2448748f56d762a24a791ab3d4c36ef29a4e70e894acristy  pixel=0.0;
245a15140ffe282798c406b8ce865dd2c02519217e5cristy  p=(char *) expression;
2468bedb4edca01599dfd0612cb0daa35b09c67d736Cristy  GetNextToken(p,&p,MagickPathExtent,token);
2474ee604053ad78f08a37a8b065dea1cec5c922fb0cristy  channel_op=ExtractChannelOp;
24809ef5be3fd824b0f67f7c0a8a975b52c89689b56cristy  for (channels=0; *token != '\0'; )
249a15140ffe282798c406b8ce865dd2c02519217e5cristy  {
250a15140ffe282798c406b8ce865dd2c02519217e5cristy    ssize_t
251a15140ffe282798c406b8ce865dd2c02519217e5cristy      i;
252a15140ffe282798c406b8ce865dd2c02519217e5cristy
253a15140ffe282798c406b8ce865dd2c02519217e5cristy    /*
254a15140ffe282798c406b8ce865dd2c02519217e5cristy      Interpret channel expression.
255a15140ffe282798c406b8ce865dd2c02519217e5cristy    */
25668bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy    switch (*token)
25768bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy    {
25868bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy      case ',':
259a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
2608bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
26168bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy        break;
262a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
26368bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy      case '|':
264a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
265ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        if (GetNextImageInList(source_image) != (Image *) NULL)
266ab272ac4f115daf25c032de9dbb49a399eebe49bcristy          source_image=GetNextImageInList(source_image);
267a15140ffe282798c406b8ce865dd2c02519217e5cristy        else
268ab272ac4f115daf25c032de9dbb49a399eebe49bcristy          source_image=GetFirstImageInList(source_image);
2698bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
27068bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy        break;
271a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
27268bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy      case ';':
273a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
274ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        Image
275ab272ac4f115daf25c032de9dbb49a399eebe49bcristy          *canvas;
276ab272ac4f115daf25c032de9dbb49a399eebe49bcristy
277bcd59345f8bbe67289229b663d9bb487cc620e13cristy        (void) SetPixelChannelMask(destination_image,channel_mask);
27868bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy        if ((channel_op == ExtractChannelOp) && (channels == 1))
279fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy          (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
2804ee604053ad78f08a37a8b065dea1cec5c922fb0cristy        status=SetImageStorageClass(destination_image,DirectClass,exception);
2814ee604053ad78f08a37a8b065dea1cec5c922fb0cristy        if (status == MagickFalse)
2824ee604053ad78f08a37a8b065dea1cec5c922fb0cristy          {
283fc68ef52f1f970316ad6dcff28d05c11f92df428cristy            destination_image=DestroyImageList(destination_image);
284fc68ef52f1f970316ad6dcff28d05c11f92df428cristy            return(destination_image);
2854ee604053ad78f08a37a8b065dea1cec5c922fb0cristy          }
286ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        canvas=CloneImage(source_image,0,0,MagickTrue,exception);
287ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        if (canvas == (Image *) NULL)
288ab272ac4f115daf25c032de9dbb49a399eebe49bcristy          {
289fc68ef52f1f970316ad6dcff28d05c11f92df428cristy            destination_image=DestroyImageList(destination_image);
290fc68ef52f1f970316ad6dcff28d05c11f92df428cristy            return(destination_image);
291ab272ac4f115daf25c032de9dbb49a399eebe49bcristy          }
292ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        AppendImageToList(&destination_image,canvas);
293ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        destination_image=GetLastImageInList(destination_image);
2948bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
295ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        channels=0;
296ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        destination_channel=RedPixelChannel;
297fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy        channel_mask=UndefinedChannel;
29868bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy        break;
299a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
30068bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy      default:
30168bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy        break;
30268bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy    }
303a15140ffe282798c406b8ce865dd2c02519217e5cristy    i=ParsePixelChannelOption(token);
304a15140ffe282798c406b8ce865dd2c02519217e5cristy    if (i < 0)
305a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
306a15140ffe282798c406b8ce865dd2c02519217e5cristy        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
307efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy          "UnrecognizedChannelType","`%s'",token);
308ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        destination_image=DestroyImageList(destination_image);
309fc68ef52f1f970316ad6dcff28d05c11f92df428cristy        return(destination_image);
310a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
311ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    source_channel=(PixelChannel) i;
312a15140ffe282798c406b8ce865dd2c02519217e5cristy    channel_op=ExtractChannelOp;
3138bedb4edca01599dfd0612cb0daa35b09c67d736Cristy    GetNextToken(p,&p,MagickPathExtent,token);
314a15140ffe282798c406b8ce865dd2c02519217e5cristy    if (*token == '<')
315a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
316a15140ffe282798c406b8ce865dd2c02519217e5cristy        channel_op=ExchangeChannelOp;
3178bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
318a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
319a15140ffe282798c406b8ce865dd2c02519217e5cristy    if (*token == '=')
3208748f56d762a24a791ab3d4c36ef29a4e70e894acristy      {
3218748f56d762a24a791ab3d4c36ef29a4e70e894acristy        if (channel_op != ExchangeChannelOp)
3228748f56d762a24a791ab3d4c36ef29a4e70e894acristy          channel_op=AssignChannelOp;
3238bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
3248748f56d762a24a791ab3d4c36ef29a4e70e894acristy      }
325a15140ffe282798c406b8ce865dd2c02519217e5cristy    if (*token == '>')
326a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
327a15140ffe282798c406b8ce865dd2c02519217e5cristy        if (channel_op != ExchangeChannelOp)
328a15140ffe282798c406b8ce865dd2c02519217e5cristy          channel_op=TransferChannelOp;
3298bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
330a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
3318748f56d762a24a791ab3d4c36ef29a4e70e894acristy    switch (channel_op)
3328748f56d762a24a791ab3d4c36ef29a4e70e894acristy    {
3338748f56d762a24a791ab3d4c36ef29a4e70e894acristy      case AssignChannelOp:
3348748f56d762a24a791ab3d4c36ef29a4e70e894acristy      {
33541db174aa6c3972ed6f5f34fb06d470adb702982cristy        pixel=StringToDoubleInterval(token,(double) QuantumRange+1.0);
3368bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
3378748f56d762a24a791ab3d4c36ef29a4e70e894acristy        break;
3388748f56d762a24a791ab3d4c36ef29a4e70e894acristy      }
3398748f56d762a24a791ab3d4c36ef29a4e70e894acristy      case ExchangeChannelOp:
3408748f56d762a24a791ab3d4c36ef29a4e70e894acristy      case TransferChannelOp:
341a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
342a15140ffe282798c406b8ce865dd2c02519217e5cristy        i=ParsePixelChannelOption(token);
343a15140ffe282798c406b8ce865dd2c02519217e5cristy        if (i < 0)
344a15140ffe282798c406b8ce865dd2c02519217e5cristy          {
345a15140ffe282798c406b8ce865dd2c02519217e5cristy            (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
346efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy              "UnrecognizedChannelType","`%s'",token);
347ab272ac4f115daf25c032de9dbb49a399eebe49bcristy            destination_image=DestroyImageList(destination_image);
348fc68ef52f1f970316ad6dcff28d05c11f92df428cristy            return(destination_image);
349a15140ffe282798c406b8ce865dd2c02519217e5cristy          }
350ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        destination_channel=(PixelChannel) i;
3510481714f03ee904233a3aa1a5ed8c7690c9d361dcristy        switch (destination_channel)
3520481714f03ee904233a3aa1a5ed8c7690c9d361dcristy        {
353ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          case RedPixelChannel:
354ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          case GreenPixelChannel:
355ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          case BluePixelChannel:
356ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          case BlackPixelChannel:
357ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          case IndexPixelChannel:
358ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy            break;
3590481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          case AlphaPixelChannel:
3600481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          {
3610481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            destination_image->alpha_trait=BlendPixelTrait;
3620481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            break;
3630481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          }
3640481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          case ReadMaskPixelChannel:
3650481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          {
3660481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            destination_image->read_mask=MagickTrue;
3670481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            break;
3680481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          }
3690481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          case WriteMaskPixelChannel:
3700481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          {
3710481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            destination_image->write_mask=MagickTrue;
3720481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            break;
3730481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          }
374ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          case MetaPixelChannel:
3750481714f03ee904233a3aa1a5ed8c7690c9d361dcristy          default:
376ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          {
377ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy            (void) SetPixelMetaChannels(destination_image,(size_t) (i-
378ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy              GetPixelChannels(destination_image)+1),exception);
3790481714f03ee904233a3aa1a5ed8c7690c9d361dcristy            break;
380ed27bb7c277cd19f4ab5aec93adb05bef902404ecristy          }
3810481714f03ee904233a3aa1a5ed8c7690c9d361dcristy        }
382aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy        channel_mask=(ChannelType) (channel_mask | ParseChannelOption(token));
38368bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy        if (((channels >= 1)  || (destination_channel >= 1)) &&
38468bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy            (IsGrayColorspace(destination_image->colorspace) != MagickFalse))
38568bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy          (void) SetImageColorspace(destination_image,sRGBColorspace,exception);
3868bedb4edca01599dfd0612cb0daa35b09c67d736Cristy        GetNextToken(p,&p,MagickPathExtent,token);
3878748f56d762a24a791ab3d4c36ef29a4e70e894acristy        break;
388a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
389fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy      default:
3903c21361b9ba0dfbbaa484845b40f2dfab3fc8500cristy        break;
3917ea920dc300fdc009f158d6db5d217790fdea4a9cristy    }
3923bb378ad21cab4b636aa9a089c9837eba0033ca1cristy    status=ChannelImage(destination_image,destination_channel,channel_op,
3933bb378ad21cab4b636aa9a089c9837eba0033ca1cristy      source_image,source_channel,ClampToQuantum(pixel),exception);
394a15140ffe282798c406b8ce865dd2c02519217e5cristy    if (status == MagickFalse)
395a15140ffe282798c406b8ce865dd2c02519217e5cristy      {
396ab272ac4f115daf25c032de9dbb49a399eebe49bcristy        destination_image=DestroyImageList(destination_image);
397a15140ffe282798c406b8ce865dd2c02519217e5cristy        break;
398a15140ffe282798c406b8ce865dd2c02519217e5cristy      }
3994ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    channels++;
4008748f56d762a24a791ab3d4c36ef29a4e70e894acristy    if (channel_op == ExchangeChannelOp)
4018748f56d762a24a791ab3d4c36ef29a4e70e894acristy      {
4024ee604053ad78f08a37a8b065dea1cec5c922fb0cristy        status=ChannelImage(destination_image,source_channel,channel_op,
4034ee604053ad78f08a37a8b065dea1cec5c922fb0cristy          source_image,destination_channel,ClampToQuantum(pixel),exception);
4048748f56d762a24a791ab3d4c36ef29a4e70e894acristy        if (status == MagickFalse)
4058748f56d762a24a791ab3d4c36ef29a4e70e894acristy          {
4068748f56d762a24a791ab3d4c36ef29a4e70e894acristy            destination_image=DestroyImageList(destination_image);
4078748f56d762a24a791ab3d4c36ef29a4e70e894acristy            break;
4088748f56d762a24a791ab3d4c36ef29a4e70e894acristy          }
4094ee604053ad78f08a37a8b065dea1cec5c922fb0cristy        channels++;
4108748f56d762a24a791ab3d4c36ef29a4e70e894acristy      }
411fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy    switch (channel_op)
412fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy    {
413fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy      case ExtractChannelOp:
414fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy      {
4159dbae2c51938823cab437553a929ea91879f6353cristy        channel_mask=(ChannelType) (channel_mask | (1 << destination_channel));
416aa2c16cb5e695053aa78e40f66bc36fbef4b1ed1cristy        destination_channel=(PixelChannel) (destination_channel+1);
417fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy        break;
418fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy      }
419fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy      default:
420fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy        break;
421fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy    }
4225f257b2f02bdd982d9bbfe612f5bb1711608590ccristy    status=SetImageProgress(source_image,ChannelFxImageTag,p-expression,
423ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      strlen(expression));
424ab272ac4f115daf25c032de9dbb49a399eebe49bcristy    if (status == MagickFalse)
425ab272ac4f115daf25c032de9dbb49a399eebe49bcristy      break;
426a15140ffe282798c406b8ce865dd2c02519217e5cristy  }
427bcd59345f8bbe67289229b663d9bb487cc620e13cristy  (void) SetPixelChannelMask(destination_image,channel_mask);
42868bc25785d7fbe128daeaf9489a5fb120e8e6ed9cristy  if ((channel_op == ExtractChannelOp) && (channels == 1))
429fe88edee6e3a2ce6c87c2d5f2f1a84bccf7bf1c8cristy    (void) SetImageColorspace(destination_image,GRAYColorspace,exception);
4304ee604053ad78f08a37a8b065dea1cec5c922fb0cristy  status=SetImageStorageClass(destination_image,DirectClass,exception);
4314ee604053ad78f08a37a8b065dea1cec5c922fb0cristy  if (status == MagickFalse)
4324ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    {
4334ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      destination_image=GetLastImageInList(destination_image);
4344ee604053ad78f08a37a8b065dea1cec5c922fb0cristy      return((Image *) NULL);
4354ee604053ad78f08a37a8b065dea1cec5c922fb0cristy    }
43609ef5be3fd824b0f67f7c0a8a975b52c89689b56cristy  return(GetFirstImageInList(destination_image));
437fbe800d0796766970fc74b673fd8838ec6bb0520cristy}
43845f56150f9154f7cd94cea2fda548c148861841ddirk
4390c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy/*
4400c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4410c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
4420c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
4430c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
4440c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%     C o m b i n e I m a g e s                                               %
4450c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
4460c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
4470c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
4480c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4490c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
4500c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  CombineImages() combines one or more images into a single image.  The
4510c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  grayscale value of the pixels of each image in the sequence is assigned in
4520c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  order to the specified channels of the combined image.   The typical
4530c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
4540c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
4550c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  The format of the CombineImages method is:
4560c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
45746f354c5b98873dc772eea3fbbf149abbf737690cristy%      Image *CombineImages(const Image *images,const ColorspaceType colorspace,
45846f354c5b98873dc772eea3fbbf149abbf737690cristy%        ExceptionInfo *exception)
4590c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
4600c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  A description of each parameter follows:
4610c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
46246f354c5b98873dc772eea3fbbf149abbf737690cristy%    o images: the image sequence.
46346f354c5b98873dc772eea3fbbf149abbf737690cristy%
46446f354c5b98873dc772eea3fbbf149abbf737690cristy%    o colorspace: the image colorspace.
4650c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
4660c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%    o exception: return any errors or warnings in this structure.
4670c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
4680c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy*/
46946f354c5b98873dc772eea3fbbf149abbf737690cristyMagickExport Image *CombineImages(const Image *image,
47046f354c5b98873dc772eea3fbbf149abbf737690cristy  const ColorspaceType colorspace,ExceptionInfo *exception)
4710c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy{
4720c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#define CombineImageTag  "Combine/Image"
4730c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
4740c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  CacheView
4750c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *combine_view;
4760c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
4770c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  Image
4780c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *combine_image;
4790c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
4800c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  MagickBooleanType
4810c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    status;
4820c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
4830c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  MagickOffsetType
4840c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    progress;
4850c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
4860c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  ssize_t
4870c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    y;
4880c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
4890c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  /*
4900c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    Ensure the image are the same size.
4910c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  */
4920c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  assert(image != (const Image *) NULL);
493e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
4940c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (image->debug != MagickFalse)
4950c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4960c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  assert(exception != (ExceptionInfo *) NULL);
497e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
4980c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  combine_image=CloneImage(image,0,0,MagickTrue,exception);
4990c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (combine_image == (Image *) NULL)
5000c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    return((Image *) NULL);
5010c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (SetImageStorageClass(combine_image,DirectClass,exception) == MagickFalse)
5020c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    {
5030c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      combine_image=DestroyImage(combine_image);
5040c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      return((Image *) NULL);
5050c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    }
5064c61eeaa51ebc6bbbbf75f187ae71dd5005f6e38cristy  if ((colorspace == UndefinedColorspace) || (image->number_channels == 1))
5074c61eeaa51ebc6bbbbf75f187ae71dd5005f6e38cristy    (void) SetImageColorspace(combine_image,sRGBColorspace,exception);
5084c61eeaa51ebc6bbbbf75f187ae71dd5005f6e38cristy  else
5094c61eeaa51ebc6bbbbf75f187ae71dd5005f6e38cristy    (void) SetImageColorspace(combine_image,colorspace,exception);
5100c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
5118a46d827a124555f0c48fb2368ec1bba8e079ab6cristy    combine_image->alpha_trait=BlendPixelTrait;
5120c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  /*
5130c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    Combine images.
5140c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  */
5150c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  status=MagickTrue;
5160c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  progress=0;
51746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  combine_view=AcquireAuthenticCacheView(combine_image,exception);
5180c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  for (y=0; y < (ssize_t) combine_image->rows; y++)
5190c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  {
5200c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    CacheView
5210c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      *image_view;
5220c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5230c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    const Image
5240c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      *next;
5250c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5260c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    Quantum
5270c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      *pixels;
5280c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5290c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    register const Quantum
53005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
5310c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5320c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    register Quantum
53305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
5340c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5350c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    register ssize_t
5360c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      i;
5370c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5380c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if (status == MagickFalse)
5390c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      continue;
5400c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
5410c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      1,exception);
5420c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if (pixels == (Quantum *) NULL)
5430c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      {
5440c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        status=MagickFalse;
5450c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        continue;
5460c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      }
5470c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    next=image;
548c1119afdec2a8bee6a7e6296aab5921406226fb3cristy    for (i=0; i < (ssize_t) GetPixelChannels(combine_image); i++)
5490c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    {
5500c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      register ssize_t
5510c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        x;
5520c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
5535a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy      PixelChannel channel=GetPixelChannelChannel(combine_image,i);
5545a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy      PixelTrait traits=GetPixelChannelTraits(combine_image,channel);
555c1119afdec2a8bee6a7e6296aab5921406226fb3cristy      if (traits == UndefinedPixelTrait)
5560c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        continue;
5575a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy      if (next == (Image *) NULL)
5585a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        continue;
55946ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy      image_view=AcquireVirtualCacheView(next,exception);
5600c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
5610c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      if (p == (const Quantum *) NULL)
5620c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        continue;
5630c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      q=pixels;
5640c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      for (x=0; x < (ssize_t) combine_image->columns; x++)
5650c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      {
566f3381ae4741c83b0dcde33e75060adb9805f788fcristy        if (x < (ssize_t) next->columns)
5670c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          {
568f3381ae4741c83b0dcde33e75060adb9805f788fcristy            q[i]=GetPixelGray(next,p);
569f3381ae4741c83b0dcde33e75060adb9805f788fcristy            p+=GetPixelChannels(next);
5700c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          }
5710c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        q+=GetPixelChannels(combine_image);
5720c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      }
5730c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      image_view=DestroyCacheView(image_view);
5740c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      next=GetNextImageInList(next);
5750c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    }
576f3381ae4741c83b0dcde33e75060adb9805f788fcristy    if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
577f3381ae4741c83b0dcde33e75060adb9805f788fcristy      status=MagickFalse;
578f3381ae4741c83b0dcde33e75060adb9805f788fcristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
579f3381ae4741c83b0dcde33e75060adb9805f788fcristy      {
580f3381ae4741c83b0dcde33e75060adb9805f788fcristy        MagickBooleanType
581f3381ae4741c83b0dcde33e75060adb9805f788fcristy          proceed;
582f3381ae4741c83b0dcde33e75060adb9805f788fcristy
583f3381ae4741c83b0dcde33e75060adb9805f788fcristy        proceed=SetImageProgress(image,CombineImageTag,progress++,
584f3381ae4741c83b0dcde33e75060adb9805f788fcristy          combine_image->rows);
585f3381ae4741c83b0dcde33e75060adb9805f788fcristy        if (proceed == MagickFalse)
586f3381ae4741c83b0dcde33e75060adb9805f788fcristy          status=MagickFalse;
587f3381ae4741c83b0dcde33e75060adb9805f788fcristy      }
5880c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  }
5890c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  combine_view=DestroyCacheView(combine_view);
5900c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (status == MagickFalse)
5910c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    combine_image=DestroyImage(combine_image);
5920c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  return(combine_image);
5930c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy}
59445f56150f9154f7cd94cea2fda548c148861841ddirk
5950c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy/*
5960c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5970c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
5980c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
5990c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
6008c8c916b144b0ffb092a820680a591c5899ec0decristy%   G e t I m a g e A l p h a C h a n n e l                                   %
6018c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
6028c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
6038c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
6048c8c916b144b0ffb092a820680a591c5899ec0decristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6058c8c916b144b0ffb092a820680a591c5899ec0decristy%
6068c8c916b144b0ffb092a820680a591c5899ec0decristy%  GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
6078c8c916b144b0ffb092a820680a591c5899ec0decristy%  not activated.  That is, the image is RGB rather than RGBA or CMYK rather
6088c8c916b144b0ffb092a820680a591c5899ec0decristy%  than CMYKA.
6098c8c916b144b0ffb092a820680a591c5899ec0decristy%
6108c8c916b144b0ffb092a820680a591c5899ec0decristy%  The format of the GetImageAlphaChannel method is:
6118c8c916b144b0ffb092a820680a591c5899ec0decristy%
6128c8c916b144b0ffb092a820680a591c5899ec0decristy%      MagickBooleanType GetImageAlphaChannel(const Image *image)
6138c8c916b144b0ffb092a820680a591c5899ec0decristy%
6148c8c916b144b0ffb092a820680a591c5899ec0decristy%  A description of each parameter follows:
6158c8c916b144b0ffb092a820680a591c5899ec0decristy%
6168c8c916b144b0ffb092a820680a591c5899ec0decristy%    o image: the image.
6178c8c916b144b0ffb092a820680a591c5899ec0decristy%
6188c8c916b144b0ffb092a820680a591c5899ec0decristy*/
6198c8c916b144b0ffb092a820680a591c5899ec0decristyMagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
6208c8c916b144b0ffb092a820680a591c5899ec0decristy{
6218c8c916b144b0ffb092a820680a591c5899ec0decristy  assert(image != (const Image *) NULL);
6228c8c916b144b0ffb092a820680a591c5899ec0decristy  if (image->debug != MagickFalse)
6238c8c916b144b0ffb092a820680a591c5899ec0decristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
624e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
62517f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy  return(image->alpha_trait != UndefinedPixelTrait ? MagickTrue : MagickFalse);
6268c8c916b144b0ffb092a820680a591c5899ec0decristy}
62745f56150f9154f7cd94cea2fda548c148861841ddirk
6288c8c916b144b0ffb092a820680a591c5899ec0decristy/*
6298c8c916b144b0ffb092a820680a591c5899ec0decristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6308c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
6318c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
6328c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
6330c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%     S e p a r a t e I m a g e                                               %
6340c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
6350c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
6360c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
6370c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6380c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6390c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  SeparateImage() separates a channel from the image and returns it as a
6400c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  grayscale image.
6410c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6420c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  The format of the SeparateImage method is:
6430c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6440c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%      Image *SeparateImage(const Image *image,const ChannelType channel,
6450c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%        ExceptionInfo *exception)
6460c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6470c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  A description of each parameter follows:
6480c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6490c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%    o image: the image.
6500c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6510c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%    o channel: the image channel.
6520c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6530c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%    o exception: return any errors or warnings in this structure.
6540c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
6550c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy*/
6560c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristyMagickExport Image *SeparateImage(const Image *image,
6570c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  const ChannelType channel_type,ExceptionInfo *exception)
6580c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy{
6590c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#define GetChannelBit(mask,bit)  (((size_t) (mask) >> (size_t) (bit)) & 0x01)
6600c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#define SeparateImageTag  "Separate/Image"
6610c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
6620c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  CacheView
6630c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *image_view,
6640c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *separate_view;
6650c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
6660c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  Image
6670c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *separate_image;
6680c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
6690c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  MagickBooleanType
6700c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    status;
6710c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
6720c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  MagickOffsetType
6730c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    progress;
6740c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
6750c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  ssize_t
6760c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    y;
6770c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
6780c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  /*
6798fdeeb3501a9069cddc0dde87fe7ec082082e925cristy    Initialize separate image attributes.
6800c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  */
6810c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  assert(image != (Image *) NULL);
682e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
6830c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (image->debug != MagickFalse)
6840c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6850c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  assert(exception != (ExceptionInfo *) NULL);
686e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
6870c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  separate_image=CloneImage(image,image->columns,image->rows,MagickTrue,
6880c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    exception);
6890c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (separate_image == (Image *) NULL)
6900c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    return((Image *) NULL);
6910c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (SetImageStorageClass(separate_image,DirectClass,exception) == MagickFalse)
6920c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    {
6930c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      separate_image=DestroyImage(separate_image);
6940c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      return((Image *) NULL);
6950c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    }
696aa7a225ef86a5a5d01215f9e5993f8e65c3df0d2cristy  (void) SetImageColorspace(separate_image,GRAYColorspace,exception);
6979b8205c051afb54599cbffe8dc49d3dc0c0ae745cristy  separate_image->alpha_trait=UndefinedPixelTrait;
6980c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  /*
6990c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    Separate image.
7000c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  */
7010c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  status=MagickTrue;
7020c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  progress=0;
70346ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireVirtualCacheView(image,exception);
70446ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  separate_view=AcquireAuthenticCacheView(separate_image,exception);
7050c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
7069a5a52fdbea9190e1c868ba9298a6f64d1c896d1cristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
7075e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(image,image,image->rows,1)
7080c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#endif
7090c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  for (y=0; y < (ssize_t) image->rows; y++)
7100c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  {
7110c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    register const Quantum
71205d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
7130c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
7140c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    register Quantum
71505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
7160c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
7170c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    register ssize_t
7180c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      x;
7190c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
7200c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if (status == MagickFalse)
7210c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      continue;
7220c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
7230c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    q=QueueCacheViewAuthenticPixels(separate_view,0,y,separate_image->columns,1,
7240c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      exception);
7250c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
7260c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      {
7270c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        status=MagickFalse;
7280c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        continue;
7290c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      }
7300c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    for (x=0; x < (ssize_t) image->columns; x++)
7310c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    {
7320c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      register ssize_t
7330c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        i;
7340c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
735883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,p) == 0)
7360c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        {
737c3a5802c0bea29c2a308d441dfa233b3059938c1cristy          SetPixelBackgoundColor(separate_image,q);
7380c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          p+=GetPixelChannels(image);
7390c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          q+=GetPixelChannels(separate_image);
7400c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          continue;
7410c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        }
7420c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      SetPixelChannel(separate_image,GrayPixelChannel,0,q);
7430c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
7440c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      {
7455a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
7465a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
7470c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        if ((traits == UndefinedPixelTrait) ||
7480c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy            (GetChannelBit(channel_type,channel) == 0))
7490c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          continue;
7509b8205c051afb54599cbffe8dc49d3dc0c0ae745cristy        SetPixelChannel(separate_image,GrayPixelChannel,p[i],q);
7510c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      }
7520c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      p+=GetPixelChannels(image);
7530c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      q+=GetPixelChannels(separate_image);
7540c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    }
7550c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if (SyncCacheViewAuthenticPixels(separate_view,exception) == MagickFalse)
7560c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      status=MagickFalse;
7570c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
7580c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      {
7590c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        MagickBooleanType
7600c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          proceed;
7610c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
7620c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
763ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy        #pragma omp critical (MagickCore_SeparateImage)
7640c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy#endif
7650c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
7660c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        if (proceed == MagickFalse)
7670c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy          status=MagickFalse;
7680c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      }
7690c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  }
7700c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  separate_view=DestroyCacheView(separate_view);
7710c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  image_view=DestroyCacheView(image_view);
77245f56150f9154f7cd94cea2fda548c148861841ddirk  (void) SetImageChannelMask(separate_image,DefaultChannels);
7731c2f48d0fbbad5757296fca9324fa14033f56632cristy  if (status == MagickFalse)
7741c2f48d0fbbad5757296fca9324fa14033f56632cristy    separate_image=DestroyImage(separate_image);
7750c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  return(separate_image);
7760c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy}
77745f56150f9154f7cd94cea2fda548c148861841ddirk
7780c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy/*
7790c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7800c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
7810c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
7820c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
7830c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%     S e p a r a t e I m a g e s                                             %
7840c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
7850c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
7860c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%                                                                             %
7870c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7880c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
7890c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  SeparateImages() returns a separate grayscale image for each channel
7900c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  specified.
7910c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
7920c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  The format of the SeparateImages method is:
7930c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
794dfdb19ea2c08296b31fef860352c0a6efe8e9cc6cristy%      Image *SeparateImages(const Image *image,ExceptionInfo *exception)
7950c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
7960c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%  A description of each parameter follows:
7970c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
7980c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%    o image: the image.
7990c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
8000c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%    o exception: return any errors or warnings in this structure.
8010c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy%
8020c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy*/
803dfdb19ea2c08296b31fef860352c0a6efe8e9cc6cristyMagickExport Image *SeparateImages(const Image *image,ExceptionInfo *exception)
8040c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy{
8050c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  Image
8060c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *images,
8070c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    *separate_image;
8080c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
8090c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  register ssize_t
8100c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    i;
8110c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy
8120c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  assert(image != (Image *) NULL);
813e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
8140c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  if (image->debug != MagickFalse)
8150c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
8160c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  images=NewImageList();
8170c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
8180c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  {
8195a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy    PixelChannel channel=GetPixelChannelChannel(image,i);
8205a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy    PixelTrait traits=GetPixelChannelTraits(image,channel);
8210c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if ((traits == UndefinedPixelTrait) ||
8220c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy        ((traits & UpdatePixelTrait) == 0))
8230c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      continue;
8240c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    separate_image=SeparateImage(image,(ChannelType) (1 << channel),exception);
8250c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy    if (separate_image != (Image *) NULL)
8260c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy      AppendImageToList(&images,separate_image);
8270c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  }
828e5ef2ce43c1b6a6bea1fdb512c0569bbe0b88780cristy  if (images == (Image *) NULL)
829e5ef2ce43c1b6a6bea1fdb512c0569bbe0b88780cristy    images=SeparateImage(image,UndefinedChannel,exception);
8300c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy  return(images);
8310c6437279e4a1b73d67b4f55738c5ed0a94f5a0ecristy}
83245f56150f9154f7cd94cea2fda548c148861841ddirk
8338c8c916b144b0ffb092a820680a591c5899ec0decristy/*
8348c8c916b144b0ffb092a820680a591c5899ec0decristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8358c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
8368c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
8378c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
8388c8c916b144b0ffb092a820680a591c5899ec0decristy%   S e t I m a g e A l p h a C h a n n e l                                   %
8398c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
8408c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
8418c8c916b144b0ffb092a820680a591c5899ec0decristy%                                                                             %
8428c8c916b144b0ffb092a820680a591c5899ec0decristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8438c8c916b144b0ffb092a820680a591c5899ec0decristy%
8448c8c916b144b0ffb092a820680a591c5899ec0decristy%  SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
8458c8c916b144b0ffb092a820680a591c5899ec0decristy%  channel.
8468c8c916b144b0ffb092a820680a591c5899ec0decristy%
8478c8c916b144b0ffb092a820680a591c5899ec0decristy%  The format of the SetImageAlphaChannel method is:
8488c8c916b144b0ffb092a820680a591c5899ec0decristy%
8498c8c916b144b0ffb092a820680a591c5899ec0decristy%      MagickBooleanType SetImageAlphaChannel(Image *image,
8508c8c916b144b0ffb092a820680a591c5899ec0decristy%        const AlphaChannelOption alpha_type,ExceptionInfo *exception)
8518c8c916b144b0ffb092a820680a591c5899ec0decristy%
8528c8c916b144b0ffb092a820680a591c5899ec0decristy%  A description of each parameter follows:
8538c8c916b144b0ffb092a820680a591c5899ec0decristy%
8548c8c916b144b0ffb092a820680a591c5899ec0decristy%    o image: the image.
8558c8c916b144b0ffb092a820680a591c5899ec0decristy%
8568c8c916b144b0ffb092a820680a591c5899ec0decristy%    o alpha_type:  The alpha channel type: ActivateAlphaChannel,
8577894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy%      AssociateAlphaChannel, CopyAlphaChannel, DeactivateAlphaChannel,
85817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy%      DisassociateAlphaChannel,  ExtractAlphaChannel, OffAlphaChannel,
85917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy%      OnAlphaChannel, OpaqueAlphaChannel, SetAlphaChannel, ShapeAlphaChannel,
86017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy%      and TransparentAlphaChannel.
8618c8c916b144b0ffb092a820680a591c5899ec0decristy%
8628c8c916b144b0ffb092a820680a591c5899ec0decristy%    o exception: return any errors or warnings in this structure.
8638c8c916b144b0ffb092a820680a591c5899ec0decristy%
8648c8c916b144b0ffb092a820680a591c5899ec0decristy*/
8658c8c916b144b0ffb092a820680a591c5899ec0decristy
8668c8c916b144b0ffb092a820680a591c5899ec0decristystatic inline void FlattenPixelInfo(const Image *image,const PixelInfo *p,
8678c8c916b144b0ffb092a820680a591c5899ec0decristy  const double alpha,const Quantum *q,const double beta,
8688c8c916b144b0ffb092a820680a591c5899ec0decristy  Quantum *composite)
8698c8c916b144b0ffb092a820680a591c5899ec0decristy{
8708c8c916b144b0ffb092a820680a591c5899ec0decristy  double
8718c8c916b144b0ffb092a820680a591c5899ec0decristy    Da,
8728c8c916b144b0ffb092a820680a591c5899ec0decristy    gamma,
8738c8c916b144b0ffb092a820680a591c5899ec0decristy    Sa;
8748c8c916b144b0ffb092a820680a591c5899ec0decristy
8758c8c916b144b0ffb092a820680a591c5899ec0decristy  register ssize_t
8768c8c916b144b0ffb092a820680a591c5899ec0decristy    i;
8778c8c916b144b0ffb092a820680a591c5899ec0decristy
8788c8c916b144b0ffb092a820680a591c5899ec0decristy  /*
8798c8c916b144b0ffb092a820680a591c5899ec0decristy    Compose pixel p over pixel q with the given alpha.
8808c8c916b144b0ffb092a820680a591c5899ec0decristy  */
8818c8c916b144b0ffb092a820680a591c5899ec0decristy  Sa=QuantumScale*alpha;
8828c8c916b144b0ffb092a820680a591c5899ec0decristy  Da=QuantumScale*beta,
8838c8c916b144b0ffb092a820680a591c5899ec0decristy  gamma=Sa*(-Da)+Sa+Da;
8848c8c916b144b0ffb092a820680a591c5899ec0decristy  gamma=PerceptibleReciprocal(gamma);
8858c8c916b144b0ffb092a820680a591c5899ec0decristy  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
8868c8c916b144b0ffb092a820680a591c5899ec0decristy  {
8878c8c916b144b0ffb092a820680a591c5899ec0decristy    PixelChannel channel=GetPixelChannelChannel(image,i);
8888c8c916b144b0ffb092a820680a591c5899ec0decristy    PixelTrait traits=GetPixelChannelTraits(image,channel);
8898c8c916b144b0ffb092a820680a591c5899ec0decristy    if (traits == UndefinedPixelTrait)
8908c8c916b144b0ffb092a820680a591c5899ec0decristy      continue;
8918c8c916b144b0ffb092a820680a591c5899ec0decristy    switch (channel)
8928c8c916b144b0ffb092a820680a591c5899ec0decristy    {
8938c8c916b144b0ffb092a820680a591c5899ec0decristy      case RedPixelChannel:
8948c8c916b144b0ffb092a820680a591c5899ec0decristy      {
8958c8c916b144b0ffb092a820680a591c5899ec0decristy        composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
8968c8c916b144b0ffb092a820680a591c5899ec0decristy          (double) p->red,alpha));
8978c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
8988c8c916b144b0ffb092a820680a591c5899ec0decristy      }
8998c8c916b144b0ffb092a820680a591c5899ec0decristy      case GreenPixelChannel:
9008c8c916b144b0ffb092a820680a591c5899ec0decristy      {
9018c8c916b144b0ffb092a820680a591c5899ec0decristy        composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
9028c8c916b144b0ffb092a820680a591c5899ec0decristy          (double) p->green,alpha));
9038c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
9048c8c916b144b0ffb092a820680a591c5899ec0decristy      }
9058c8c916b144b0ffb092a820680a591c5899ec0decristy      case BluePixelChannel:
9068c8c916b144b0ffb092a820680a591c5899ec0decristy      {
9078c8c916b144b0ffb092a820680a591c5899ec0decristy        composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
9088c8c916b144b0ffb092a820680a591c5899ec0decristy          (double) p->blue,alpha));
9098c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
9108c8c916b144b0ffb092a820680a591c5899ec0decristy      }
9118c8c916b144b0ffb092a820680a591c5899ec0decristy      case BlackPixelChannel:
9128c8c916b144b0ffb092a820680a591c5899ec0decristy      {
9138c8c916b144b0ffb092a820680a591c5899ec0decristy        composite[i]=ClampToQuantum(gamma*MagickOver_((double) q[i],beta,
9148c8c916b144b0ffb092a820680a591c5899ec0decristy          (double) p->black,alpha));
9158c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
9168c8c916b144b0ffb092a820680a591c5899ec0decristy      }
9178c8c916b144b0ffb092a820680a591c5899ec0decristy      case AlphaPixelChannel:
9188c8c916b144b0ffb092a820680a591c5899ec0decristy      {
9198c8c916b144b0ffb092a820680a591c5899ec0decristy        composite[i]=ClampToQuantum(QuantumRange*(Sa*(-Da)+Sa+Da));
9208c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
9218c8c916b144b0ffb092a820680a591c5899ec0decristy      }
9228c8c916b144b0ffb092a820680a591c5899ec0decristy      default:
9238c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
9248c8c916b144b0ffb092a820680a591c5899ec0decristy    }
9258c8c916b144b0ffb092a820680a591c5899ec0decristy  }
9268c8c916b144b0ffb092a820680a591c5899ec0decristy}
9278c8c916b144b0ffb092a820680a591c5899ec0decristy
9288c8c916b144b0ffb092a820680a591c5899ec0decristyMagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
9298c8c916b144b0ffb092a820680a591c5899ec0decristy  const AlphaChannelOption alpha_type,ExceptionInfo *exception)
9308c8c916b144b0ffb092a820680a591c5899ec0decristy{
9317894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy  CacheView
9327894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    *image_view;
9337894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
9348c8c916b144b0ffb092a820680a591c5899ec0decristy  MagickBooleanType
9358c8c916b144b0ffb092a820680a591c5899ec0decristy    status;
9368c8c916b144b0ffb092a820680a591c5899ec0decristy
9377894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy  ssize_t
9387894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    y;
9397894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
9408c8c916b144b0ffb092a820680a591c5899ec0decristy  assert(image != (Image *) NULL);
9418c8c916b144b0ffb092a820680a591c5899ec0decristy  if (image->debug != MagickFalse)
9428c8c916b144b0ffb092a820680a591c5899ec0decristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
943e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
9448c8c916b144b0ffb092a820680a591c5899ec0decristy  status=MagickTrue;
9458c8c916b144b0ffb092a820680a591c5899ec0decristy  switch (alpha_type)
9468c8c916b144b0ffb092a820680a591c5899ec0decristy  {
9478c8c916b144b0ffb092a820680a591c5899ec0decristy    case ActivateAlphaChannel:
9488c8c916b144b0ffb092a820680a591c5899ec0decristy    {
9498c8c916b144b0ffb092a820680a591c5899ec0decristy      image->alpha_trait=BlendPixelTrait;
9508c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
9518c8c916b144b0ffb092a820680a591c5899ec0decristy    }
9527894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    case AssociateAlphaChannel:
9538c8c916b144b0ffb092a820680a591c5899ec0decristy    {
9547894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      /*
9557894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        Associate alpha.
9567894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      */
9577894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      status=SetImageStorageClass(image,DirectClass,exception);
9587894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      if (status == MagickFalse)
9597894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        break;
9607894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      image_view=AcquireAuthenticCacheView(image,exception);
9617894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
9627894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      #pragma omp parallel for schedule(static,4) shared(status) \
9637894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        magick_threads(image,image,image->rows,1)
9647894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy#endif
9657894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      for (y=0; y < (ssize_t) image->rows; y++)
9667894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      {
9677894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        register Quantum
96805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
9698c8c916b144b0ffb092a820680a591c5899ec0decristy
9707894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        register ssize_t
9717894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          x;
9728c8c916b144b0ffb092a820680a591c5899ec0decristy
9737894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        if (status == MagickFalse)
9747894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          continue;
9757894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
9767894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          exception);
9777894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        if (q == (Quantum *) NULL)
9787894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          {
9797894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            status=MagickFalse;
9807894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            continue;
9817894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          }
9827894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        for (x=0; x < (ssize_t) image->columns; x++)
9837894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        {
9847894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          double
985a9414e1527720e525cdd677d08080eb134e9ab94dirk            gamma;
9867894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
9877894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          register ssize_t
9887894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            i;
9897894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
9907894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          if (GetPixelReadMask(image,q) == 0)
9917894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            {
9927894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy              q+=GetPixelChannels(image);
9937894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy              continue;
9947894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            }
995a9414e1527720e525cdd677d08080eb134e9ab94dirk          gamma=QuantumScale*GetPixelAlpha(image,q);
9967894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
9977894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          {
9987894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            PixelChannel channel=GetPixelChannelChannel(image,i);
99901c08ca118d98ce2806ab8aa7739225ddb8b8becdirk            PixelTrait traits=GetPixelChannelTraits(image,channel);
1000a9414e1527720e525cdd677d08080eb134e9ab94dirk            if (channel == AlphaPixelChannel)
1001a9414e1527720e525cdd677d08080eb134e9ab94dirk              continue;
10027894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            if ((traits & UpdatePixelTrait) == 0)
10037894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy              continue;
100431e75937db91fd53e7deb9e3544646d0459f2196cristy            q[i]=ClampToQuantum(gamma*q[i]);
10057894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          }
10067894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          q+=GetPixelChannels(image);
10077894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        }
10087894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10097894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          status=MagickFalse;
10107894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      }
10117894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      image_view=DestroyCacheView(image_view);
10127894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      image->alpha_trait=CopyPixelTrait;
10137894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      return(status);
10147894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    }
10157894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    case BackgroundAlphaChannel:
10167894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    {
10178c8c916b144b0ffb092a820680a591c5899ec0decristy      /*
10188c8c916b144b0ffb092a820680a591c5899ec0decristy        Set transparent pixels to background color.
10198c8c916b144b0ffb092a820680a591c5899ec0decristy      */
102017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (image->alpha_trait == UndefinedPixelTrait)
10218c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
10227894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      status=SetImageStorageClass(image,DirectClass,exception);
10237894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      if (status == MagickFalse)
10248c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
10258c8c916b144b0ffb092a820680a591c5899ec0decristy      image_view=AcquireAuthenticCacheView(image,exception);
10268c8c916b144b0ffb092a820680a591c5899ec0decristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
10278c8c916b144b0ffb092a820680a591c5899ec0decristy      #pragma omp parallel for schedule(static,4) shared(status) \
10288c8c916b144b0ffb092a820680a591c5899ec0decristy        magick_threads(image,image,image->rows,1)
10298c8c916b144b0ffb092a820680a591c5899ec0decristy#endif
10308c8c916b144b0ffb092a820680a591c5899ec0decristy      for (y=0; y < (ssize_t) image->rows; y++)
10318c8c916b144b0ffb092a820680a591c5899ec0decristy      {
10328c8c916b144b0ffb092a820680a591c5899ec0decristy        register Quantum
103305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
10348c8c916b144b0ffb092a820680a591c5899ec0decristy
10358c8c916b144b0ffb092a820680a591c5899ec0decristy        register ssize_t
10368c8c916b144b0ffb092a820680a591c5899ec0decristy          x;
10378c8c916b144b0ffb092a820680a591c5899ec0decristy
10388c8c916b144b0ffb092a820680a591c5899ec0decristy        if (status == MagickFalse)
10398c8c916b144b0ffb092a820680a591c5899ec0decristy          continue;
10408c8c916b144b0ffb092a820680a591c5899ec0decristy        q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
10418c8c916b144b0ffb092a820680a591c5899ec0decristy          exception);
10428c8c916b144b0ffb092a820680a591c5899ec0decristy        if (q == (Quantum *) NULL)
10438c8c916b144b0ffb092a820680a591c5899ec0decristy          {
10448c8c916b144b0ffb092a820680a591c5899ec0decristy            status=MagickFalse;
10458c8c916b144b0ffb092a820680a591c5899ec0decristy            continue;
10468c8c916b144b0ffb092a820680a591c5899ec0decristy          }
10478c8c916b144b0ffb092a820680a591c5899ec0decristy        for (x=0; x < (ssize_t) image->columns; x++)
10488c8c916b144b0ffb092a820680a591c5899ec0decristy        {
10498c8c916b144b0ffb092a820680a591c5899ec0decristy          if (GetPixelAlpha(image,q) == TransparentAlpha)
10508c8c916b144b0ffb092a820680a591c5899ec0decristy            {
105111a06d3f2cac0f17af7963e83bc6e9ebd2a377c0cristy              SetPixelViaPixelInfo(image,&image->background_color,q);
10528c8c916b144b0ffb092a820680a591c5899ec0decristy              SetPixelChannel(image,AlphaPixelChannel,TransparentAlpha,q);
10538c8c916b144b0ffb092a820680a591c5899ec0decristy            }
10548c8c916b144b0ffb092a820680a591c5899ec0decristy          q+=GetPixelChannels(image);
10558c8c916b144b0ffb092a820680a591c5899ec0decristy        }
10568c8c916b144b0ffb092a820680a591c5899ec0decristy        if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10578c8c916b144b0ffb092a820680a591c5899ec0decristy          status=MagickFalse;
10588c8c916b144b0ffb092a820680a591c5899ec0decristy      }
10598c8c916b144b0ffb092a820680a591c5899ec0decristy      image_view=DestroyCacheView(image_view);
10608c8c916b144b0ffb092a820680a591c5899ec0decristy      return(status);
10618c8c916b144b0ffb092a820680a591c5899ec0decristy    }
10628c8c916b144b0ffb092a820680a591c5899ec0decristy    case CopyAlphaChannel:
10638c8c916b144b0ffb092a820680a591c5899ec0decristy    case ShapeAlphaChannel:
10648c8c916b144b0ffb092a820680a591c5899ec0decristy    {
10658c8c916b144b0ffb092a820680a591c5899ec0decristy      /*
10668c8c916b144b0ffb092a820680a591c5899ec0decristy        Copy pixel intensity to the alpha channel.
10678c8c916b144b0ffb092a820680a591c5899ec0decristy      */
106894beb9efd871cd08ab2e3e74f2cfd598efbdff58Cristy      image->alpha_trait=UpdatePixelTrait;
10698c8c916b144b0ffb092a820680a591c5899ec0decristy      status=CompositeImage(image,image,IntensityCompositeOp,MagickTrue,0,0,
10708c8c916b144b0ffb092a820680a591c5899ec0decristy        exception);
10718c8c916b144b0ffb092a820680a591c5899ec0decristy      if (alpha_type == ShapeAlphaChannel)
10728c8c916b144b0ffb092a820680a591c5899ec0decristy        (void) LevelImageColors(image,&image->background_color,
10738c8c916b144b0ffb092a820680a591c5899ec0decristy          &image->background_color,MagickTrue,exception);
10748c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
10758c8c916b144b0ffb092a820680a591c5899ec0decristy    }
10768c8c916b144b0ffb092a820680a591c5899ec0decristy    case DeactivateAlphaChannel:
10778c8c916b144b0ffb092a820680a591c5899ec0decristy    {
107817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (image->alpha_trait == UndefinedPixelTrait)
10798f76ccdf9c7bac259c62dd3494a2b4afa1e5e805cristy        status=SetImageAlpha(image,OpaqueAlpha,exception);
10808c8c916b144b0ffb092a820680a591c5899ec0decristy      image->alpha_trait=CopyPixelTrait;
10818c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
10828c8c916b144b0ffb092a820680a591c5899ec0decristy    }
10837894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    case DisassociateAlphaChannel:
10847894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    {
10857894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      /*
10867894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        Disassociate alpha.
10877894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      */
10887894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      status=SetImageStorageClass(image,DirectClass,exception);
10897894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      if (status == MagickFalse)
10907894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        break;
10917894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      image->alpha_trait=BlendPixelTrait;
10927894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      image_view=AcquireAuthenticCacheView(image,exception);
10937894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
10947894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      #pragma omp parallel for schedule(static,4) shared(status) \
10957894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        magick_threads(image,image,image->rows,1)
10967894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy#endif
10977894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      for (y=0; y < (ssize_t) image->rows; y++)
10987894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      {
10997894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        register Quantum
110005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
11017894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
11027894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        register ssize_t
11037894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          x;
11047894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
11057894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        if (status == MagickFalse)
11067894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          continue;
11077894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
11087894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          exception);
11097894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        if (q == (Quantum *) NULL)
11107894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          {
11117894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            status=MagickFalse;
11127894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            continue;
11137894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          }
11147894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        for (x=0; x < (ssize_t) image->columns; x++)
11157894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        {
11167894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          double
11177894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            gamma,
11187894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            Sa;
11197894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
11207894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          register ssize_t
11217894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            i;
11227894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy
11237894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          if (GetPixelReadMask(image,q) == 0)
11247894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            {
11257894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy              q+=GetPixelChannels(image);
11267894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy              continue;
11277894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            }
11287894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          Sa=QuantumScale*GetPixelAlpha(image,q);
11297894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          gamma=PerceptibleReciprocal(Sa);
11307894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
11317894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          {
11327894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            PixelChannel channel=GetPixelChannelChannel(image,i);
113301c08ca118d98ce2806ab8aa7739225ddb8b8becdirk            PixelTrait traits=GetPixelChannelTraits(image,channel);
1134a9414e1527720e525cdd677d08080eb134e9ab94dirk            if (channel == AlphaPixelChannel)
1135a9414e1527720e525cdd677d08080eb134e9ab94dirk              continue;
11367894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            if ((traits & UpdatePixelTrait) == 0)
11377894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy              continue;
11387894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy            q[i]=ClampToQuantum(gamma*q[i]);
11397894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          }
11407894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          q+=GetPixelChannels(image);
11417894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        }
11427894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy        if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
11437894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy          status=MagickFalse;
11447894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      }
11457894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      image_view=DestroyCacheView(image_view);
11462fd3474a54fc07d23bd775f3280d3d37e7afb4c8cristy      image->alpha_trait=UndefinedPixelTrait;
11477894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      return(status);
11487894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy    }
1149dd00eb38ce513a303929f81b87a06aa401045d6dcristy    case DiscreteAlphaChannel:
1150dd00eb38ce513a303929f81b87a06aa401045d6dcristy    {
1151d1af5caa404d6fbe993c9fd30e09624bf0cefe27dirk      if (image->alpha_trait == UndefinedPixelTrait)
1152d1af5caa404d6fbe993c9fd30e09624bf0cefe27dirk        status=SetImageAlpha(image,OpaqueAlpha,exception);
1153dd00eb38ce513a303929f81b87a06aa401045d6dcristy      image->alpha_trait=UpdatePixelTrait;
1154dd00eb38ce513a303929f81b87a06aa401045d6dcristy      break;
1155dd00eb38ce513a303929f81b87a06aa401045d6dcristy    }
11568c8c916b144b0ffb092a820680a591c5899ec0decristy    case ExtractAlphaChannel:
11578c8c916b144b0ffb092a820680a591c5899ec0decristy    {
11588c8c916b144b0ffb092a820680a591c5899ec0decristy      status=CompositeImage(image,image,AlphaCompositeOp,MagickTrue,0,0,
11598c8c916b144b0ffb092a820680a591c5899ec0decristy        exception);
1160b08cbbeb567f759a441fc76165b810156a2de242cristy      image->alpha_trait=UndefinedPixelTrait;
11618c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
11628c8c916b144b0ffb092a820680a591c5899ec0decristy    }
116317f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy    case OffAlphaChannel:
116417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy    {
116517f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      image->alpha_trait=UndefinedPixelTrait;
116617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      break;
116717f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy    }
116817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy    case OnAlphaChannel:
116917f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy    {
1170e36bf51231f20596708785f816a41d0256873d92cristy      if (image->alpha_trait == UndefinedPixelTrait)
1171e36bf51231f20596708785f816a41d0256873d92cristy        status=SetImageAlpha(image,OpaqueAlpha,exception);
117217f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      image->alpha_trait=BlendPixelTrait;
117317f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      break;
117417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy    }
11758c8c916b144b0ffb092a820680a591c5899ec0decristy    case OpaqueAlphaChannel:
11768c8c916b144b0ffb092a820680a591c5899ec0decristy    {
11778c8c916b144b0ffb092a820680a591c5899ec0decristy      status=SetImageAlpha(image,OpaqueAlpha,exception);
11788c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
11798c8c916b144b0ffb092a820680a591c5899ec0decristy    }
11808c8c916b144b0ffb092a820680a591c5899ec0decristy    case RemoveAlphaChannel:
11818c8c916b144b0ffb092a820680a591c5899ec0decristy    {
11828c8c916b144b0ffb092a820680a591c5899ec0decristy      /*
11838c8c916b144b0ffb092a820680a591c5899ec0decristy        Remove transparency.
11848c8c916b144b0ffb092a820680a591c5899ec0decristy      */
118517f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (image->alpha_trait == UndefinedPixelTrait)
11868c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
11877894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      status=SetImageStorageClass(image,DirectClass,exception);
11887894d4a8920a7ee8f292b9c9b4bfc7b722bfcb83cristy      if (status == MagickFalse)
11898c8c916b144b0ffb092a820680a591c5899ec0decristy        break;
11908c8c916b144b0ffb092a820680a591c5899ec0decristy      image_view=AcquireAuthenticCacheView(image,exception);
11918c8c916b144b0ffb092a820680a591c5899ec0decristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
11928c8c916b144b0ffb092a820680a591c5899ec0decristy      #pragma omp parallel for schedule(static,4) shared(status) \
11938c8c916b144b0ffb092a820680a591c5899ec0decristy        magick_threads(image,image,image->rows,1)
11948c8c916b144b0ffb092a820680a591c5899ec0decristy#endif
11958c8c916b144b0ffb092a820680a591c5899ec0decristy      for (y=0; y < (ssize_t) image->rows; y++)
11968c8c916b144b0ffb092a820680a591c5899ec0decristy      {
11978c8c916b144b0ffb092a820680a591c5899ec0decristy        register Quantum
119805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
11998c8c916b144b0ffb092a820680a591c5899ec0decristy
12008c8c916b144b0ffb092a820680a591c5899ec0decristy        register ssize_t
12018c8c916b144b0ffb092a820680a591c5899ec0decristy          x;
12028c8c916b144b0ffb092a820680a591c5899ec0decristy
12038c8c916b144b0ffb092a820680a591c5899ec0decristy        if (status == MagickFalse)
12048c8c916b144b0ffb092a820680a591c5899ec0decristy          continue;
12058c8c916b144b0ffb092a820680a591c5899ec0decristy        q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
12068c8c916b144b0ffb092a820680a591c5899ec0decristy          exception);
12078c8c916b144b0ffb092a820680a591c5899ec0decristy        if (q == (Quantum *) NULL)
12088c8c916b144b0ffb092a820680a591c5899ec0decristy          {
12098c8c916b144b0ffb092a820680a591c5899ec0decristy            status=MagickFalse;
12108c8c916b144b0ffb092a820680a591c5899ec0decristy            continue;
12118c8c916b144b0ffb092a820680a591c5899ec0decristy          }
12128c8c916b144b0ffb092a820680a591c5899ec0decristy        for (x=0; x < (ssize_t) image->columns; x++)
12138c8c916b144b0ffb092a820680a591c5899ec0decristy        {
12148c8c916b144b0ffb092a820680a591c5899ec0decristy          FlattenPixelInfo(image,&image->background_color,
12158c8c916b144b0ffb092a820680a591c5899ec0decristy            image->background_color.alpha,q,(double)
12168c8c916b144b0ffb092a820680a591c5899ec0decristy            GetPixelAlpha(image,q),q);
12178c8c916b144b0ffb092a820680a591c5899ec0decristy          q+=GetPixelChannels(image);
12188c8c916b144b0ffb092a820680a591c5899ec0decristy        }
12198c8c916b144b0ffb092a820680a591c5899ec0decristy        if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
12208c8c916b144b0ffb092a820680a591c5899ec0decristy          status=MagickFalse;
12218c8c916b144b0ffb092a820680a591c5899ec0decristy      }
12228c8c916b144b0ffb092a820680a591c5899ec0decristy      image_view=DestroyCacheView(image_view);
12238c8c916b144b0ffb092a820680a591c5899ec0decristy      image->alpha_trait=image->background_color.alpha_trait;
12240577b2ddf67a4c9f2604116332b97b29e53d2415dirk      break;
12258c8c916b144b0ffb092a820680a591c5899ec0decristy    }
12268c8c916b144b0ffb092a820680a591c5899ec0decristy    case SetAlphaChannel:
12278c8c916b144b0ffb092a820680a591c5899ec0decristy    {
122817f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (image->alpha_trait == UndefinedPixelTrait)
12298c8c916b144b0ffb092a820680a591c5899ec0decristy        status=SetImageAlpha(image,OpaqueAlpha,exception);
12308c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
12318c8c916b144b0ffb092a820680a591c5899ec0decristy    }
12328c8c916b144b0ffb092a820680a591c5899ec0decristy    case TransparentAlphaChannel:
12338c8c916b144b0ffb092a820680a591c5899ec0decristy    {
12348c8c916b144b0ffb092a820680a591c5899ec0decristy      status=SetImageAlpha(image,TransparentAlpha,exception);
12358c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
12368c8c916b144b0ffb092a820680a591c5899ec0decristy    }
12378c8c916b144b0ffb092a820680a591c5899ec0decristy    case UndefinedAlphaChannel:
12388c8c916b144b0ffb092a820680a591c5899ec0decristy      break;
12398c8c916b144b0ffb092a820680a591c5899ec0decristy  }
12408c8c916b144b0ffb092a820680a591c5899ec0decristy  if (status == MagickFalse)
12418c8c916b144b0ffb092a820680a591c5899ec0decristy    return(status);
124294beb9efd871cd08ab2e3e74f2cfd598efbdff58Cristy  (void) SetPixelChannelMask(image,image->channel_mask);
12438c8c916b144b0ffb092a820680a591c5899ec0decristy  return(SyncImagePixelCache(image,exception));
12448c8c916b144b0ffb092a820680a591c5899ec0decristy}
1245