13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        SSSSS  TTTTT   AAA   TTTTT  IIIII  SSSSS  TTTTT  IIIII   CCCC        %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        SS       T    A   A    T      I    SS       T      I    C            %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%         SSS     T    AAAAA    T      I     SSS     T      I    C            %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           SS    T    A   A    T      I       SS    T      I    C            %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        SSSSS    T    A   A    T    IIIII  SSSSS    T    IIIII   CCCC        %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133e2860cb0796fe77659325ec3d540d8766d54f49cristy%                     MagickCore Image Statistical Methods                    %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
45eeec14f738e8dbcfa064c1158a6e503b30a5dc3edirk#include "MagickCore/accelerate-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/animate.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache-private.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache-view.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace-private.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite-private.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/compress.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/display.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/enhance.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
678ea81224e9ff022e56eb2cddb12860a8b2e90411cristy#include "MagickCore/gem-private.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magic.h"
724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
734c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
744c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
754c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
764c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
774c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/option.h"
784c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/paint.h"
794c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
804c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/profile.h"
814c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantize.h"
824c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
834c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/random_.h"
844c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/random-private.h"
8557340e008c81f05c0adb4d8874dda11104d8bb7ecristy#include "MagickCore/resource_.h"
864c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/segment.h"
874c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/semaphore.h"
884c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/signature-private.h"
894c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/statistic.h"
904c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
914c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/thread-private.h"
924c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/timer.h"
934c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
944c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/version.h"
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
101d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%     E v a l u a t e I m a g e                                               %
102316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
103316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
104316d51773c093e74e15de805e8bf620d6b56bc8bcristy%                                                                             %
105316d51773c093e74e15de805e8bf620d6b56bc8bcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
107d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%  EvaluateImage() applies a value to the image with an arithmetic, relational,
108d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%  or logical operator to an image. Use these operations to lighten or darken
109d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%  an image, to increase or decrease contrast in an image, or to produce the
110d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%  "negative" of an image.
111316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
112d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  The format of the EvaluateImage method is:
113316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
114d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%      MagickBooleanType EvaluateImage(Image *image,
115d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%        const MagickEvaluateOperator op,const double value,
116d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%        ExceptionInfo *exception)
117d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%      MagickBooleanType EvaluateImages(Image *images,
118d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%        const MagickEvaluateOperator op,const double value,
119d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%        ExceptionInfo *exception)
120316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
121316d51773c093e74e15de805e8bf620d6b56bc8bcristy%  A description of each parameter follows:
122316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
123d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%    o image: the image.
124d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%
125d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%    o op: A channel op.
126d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%
127d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy%    o value: A value value.
128316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
129316d51773c093e74e15de805e8bf620d6b56bc8bcristy%    o exception: return any errors or warnings in this structure.
130316d51773c093e74e15de805e8bf620d6b56bc8bcristy%
131316d51773c093e74e15de805e8bf620d6b56bc8bcristy*/
132316d51773c093e74e15de805e8bf620d6b56bc8bcristy
13395a072b9674d607b5318a3283fd3952e82107828cristytypedef struct _PixelChannels
134ba18a7a20da567238922ea992832fd3c8f70e7bbcristy{
135a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
1365f95f4f77efc46ff53593d750491c8f60698c983cristy    channel[CompositePixelChannel];
13795a072b9674d607b5318a3283fd3952e82107828cristy} PixelChannels;
138ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
13995a072b9674d607b5318a3283fd3952e82107828cristystatic PixelChannels **DestroyPixelThreadSet(PixelChannels **pixels)
140316d51773c093e74e15de805e8bf620d6b56bc8bcristy{
141bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
142316d51773c093e74e15de805e8bf620d6b56bc8bcristy    i;
143316d51773c093e74e15de805e8bf620d6b56bc8bcristy
14495a072b9674d607b5318a3283fd3952e82107828cristy  assert(pixels != (PixelChannels **) NULL);
145ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
14695a072b9674d607b5318a3283fd3952e82107828cristy    if (pixels[i] != (PixelChannels *) NULL)
14795a072b9674d607b5318a3283fd3952e82107828cristy      pixels[i]=(PixelChannels *) RelinquishMagickMemory(pixels[i]);
14895a072b9674d607b5318a3283fd3952e82107828cristy  pixels=(PixelChannels **) RelinquishMagickMemory(pixels);
149316d51773c093e74e15de805e8bf620d6b56bc8bcristy  return(pixels);
150316d51773c093e74e15de805e8bf620d6b56bc8bcristy}
151316d51773c093e74e15de805e8bf620d6b56bc8bcristy
152751a6671c9b7480f3672a7ef6aa6e392f064b46ddirkstatic PixelChannels **AcquirePixelThreadSet(const Image *image)
153316d51773c093e74e15de805e8bf620d6b56bc8bcristy{
15495a072b9674d607b5318a3283fd3952e82107828cristy  PixelChannels
155316d51773c093e74e15de805e8bf620d6b56bc8bcristy    **pixels;
156316d51773c093e74e15de805e8bf620d6b56bc8bcristy
157af1feeee51c32b77405b02abb3e0d655458e2621Cristy  register ssize_t
158af1feeee51c32b77405b02abb3e0d655458e2621Cristy    i;
159af1feeee51c32b77405b02abb3e0d655458e2621Cristy
160bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
161316d51773c093e74e15de805e8bf620d6b56bc8bcristy    number_threads;
162316d51773c093e74e15de805e8bf620d6b56bc8bcristy
1639357bdd9a30c3d65ef8812e45220f7552dc4376bcristy  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
164e2a912b6c9086c98ec838baa0824cd8deca55538cristy  pixels=(PixelChannels **) AcquireQuantumMemory(number_threads,
165e2a912b6c9086c98ec838baa0824cd8deca55538cristy    sizeof(*pixels));
16695a072b9674d607b5318a3283fd3952e82107828cristy  if (pixels == (PixelChannels **) NULL)
16795a072b9674d607b5318a3283fd3952e82107828cristy    return((PixelChannels **) NULL);
168316d51773c093e74e15de805e8bf620d6b56bc8bcristy  (void) ResetMagickMemory(pixels,0,number_threads*sizeof(*pixels));
169bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) number_threads; i++)
170316d51773c093e74e15de805e8bf620d6b56bc8bcristy  {
171ba18a7a20da567238922ea992832fd3c8f70e7bbcristy    register ssize_t
172ba18a7a20da567238922ea992832fd3c8f70e7bbcristy      j;
173ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
174b21069ba490260839c06334bdce983c4022781b0Cristy    pixels[i]=(PixelChannels *) AcquireQuantumMemory(image->columns,
175b21069ba490260839c06334bdce983c4022781b0Cristy      sizeof(**pixels));
17695a072b9674d607b5318a3283fd3952e82107828cristy    if (pixels[i] == (PixelChannels *) NULL)
177316d51773c093e74e15de805e8bf620d6b56bc8bcristy      return(DestroyPixelThreadSet(pixels));
178b21069ba490260839c06334bdce983c4022781b0Cristy    for (j=0; j < (ssize_t) image->columns; j++)
179ba18a7a20da567238922ea992832fd3c8f70e7bbcristy    {
180ba18a7a20da567238922ea992832fd3c8f70e7bbcristy      register ssize_t
181ba18a7a20da567238922ea992832fd3c8f70e7bbcristy        k;
182ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
183ba18a7a20da567238922ea992832fd3c8f70e7bbcristy      for (k=0; k < MaxPixelChannels; k++)
184ba18a7a20da567238922ea992832fd3c8f70e7bbcristy        pixels[i][j].channel[k]=0.0;
185ba18a7a20da567238922ea992832fd3c8f70e7bbcristy    }
186316d51773c093e74e15de805e8bf620d6b56bc8bcristy  }
187316d51773c093e74e15de805e8bf620d6b56bc8bcristy  return(pixels);
188316d51773c093e74e15de805e8bf620d6b56bc8bcristy}
189316d51773c093e74e15de805e8bf620d6b56bc8bcristy
190a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristystatic inline double EvaluateMax(const double x,const double y)
191a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy{
192a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy  if (x > y)
193a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy    return(x);
194a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy  return(y);
195a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy}
196a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy
19708a3d70530ab973a425c8cdce82396825b6a7834cristy#if defined(__cplusplus) || defined(c_plusplus)
19808a3d70530ab973a425c8cdce82396825b6a7834cristyextern "C" {
19908a3d70530ab973a425c8cdce82396825b6a7834cristy#endif
20008a3d70530ab973a425c8cdce82396825b6a7834cristy
20108a3d70530ab973a425c8cdce82396825b6a7834cristystatic int IntensityCompare(const void *x,const void *y)
20208a3d70530ab973a425c8cdce82396825b6a7834cristy{
20395a072b9674d607b5318a3283fd3952e82107828cristy  const PixelChannels
20408a3d70530ab973a425c8cdce82396825b6a7834cristy    *color_1,
20508a3d70530ab973a425c8cdce82396825b6a7834cristy    *color_2;
20608a3d70530ab973a425c8cdce82396825b6a7834cristy
207a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
208ba18a7a20da567238922ea992832fd3c8f70e7bbcristy    distance;
209ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
210ba18a7a20da567238922ea992832fd3c8f70e7bbcristy  register ssize_t
211ba18a7a20da567238922ea992832fd3c8f70e7bbcristy    i;
21208a3d70530ab973a425c8cdce82396825b6a7834cristy
21395a072b9674d607b5318a3283fd3952e82107828cristy  color_1=(const PixelChannels *) x;
21495a072b9674d607b5318a3283fd3952e82107828cristy  color_2=(const PixelChannels *) y;
215ba18a7a20da567238922ea992832fd3c8f70e7bbcristy  distance=0.0;
216ba18a7a20da567238922ea992832fd3c8f70e7bbcristy  for (i=0; i < MaxPixelChannels; i++)
217a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    distance+=color_1->channel[i]-(double) color_2->channel[i];
218ba18a7a20da567238922ea992832fd3c8f70e7bbcristy  return(distance < 0 ? -1 : distance > 0 ? 1 : 0);
21908a3d70530ab973a425c8cdce82396825b6a7834cristy}
22008a3d70530ab973a425c8cdce82396825b6a7834cristy
22108a3d70530ab973a425c8cdce82396825b6a7834cristy#if defined(__cplusplus) || defined(c_plusplus)
22208a3d70530ab973a425c8cdce82396825b6a7834cristy}
22308a3d70530ab973a425c8cdce82396825b6a7834cristy#endif
22408a3d70530ab973a425c8cdce82396825b6a7834cristy
22584ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristystatic double ApplyEvaluateOperator(RandomInfo *random_info,const Quantum pixel,
22684ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy  const MagickEvaluateOperator op,const double value)
227351842fbf91597bd44b6200df92c8d45c98fe5adcristy{
228a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
229351842fbf91597bd44b6200df92c8d45c98fe5adcristy    result;
230351842fbf91597bd44b6200df92c8d45c98fe5adcristy
231351842fbf91597bd44b6200df92c8d45c98fe5adcristy  result=0.0;
232351842fbf91597bd44b6200df92c8d45c98fe5adcristy  switch (op)
233351842fbf91597bd44b6200df92c8d45c98fe5adcristy  {
234351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case UndefinedEvaluateOperator:
235351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
23633aaed249b7e64a7e43ef086334235f1de342bbccristy    case AbsEvaluateOperator:
23733aaed249b7e64a7e43ef086334235f1de342bbccristy    {
238a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) fabs((double) (pixel+value));
23933aaed249b7e64a7e43ef086334235f1de342bbccristy      break;
24033aaed249b7e64a7e43ef086334235f1de342bbccristy    }
241351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case AddEvaluateOperator:
242351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
243a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (pixel+value);
244351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
245351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
246351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case AddModulusEvaluateOperator:
247351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
248351842fbf91597bd44b6200df92c8d45c98fe5adcristy      /*
249e2a912b6c9086c98ec838baa0824cd8deca55538cristy        This returns a 'floored modulus' of the addition which is a positive
250e2a912b6c9086c98ec838baa0824cd8deca55538cristy        result.  It differs from % or fmod() that returns a 'truncated modulus'
251e2a912b6c9086c98ec838baa0824cd8deca55538cristy        result, where floor() is replaced by trunc() and could return a
252e2a912b6c9086c98ec838baa0824cd8deca55538cristy        negative result (which is clipped).
253351842fbf91597bd44b6200df92c8d45c98fe5adcristy      */
254351842fbf91597bd44b6200df92c8d45c98fe5adcristy      result=pixel+value;
255364a8e2b0fc2f71afc727196466c0a5f54fce738cristy      result-=(QuantumRange+1.0)*floor((double) result/(QuantumRange+1.0));
256351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
257351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
258351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case AndEvaluateOperator:
259351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
260a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) ((size_t) pixel & (size_t) (value+0.5));
261351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
262351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
263351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case CosineEvaluateOperator:
264351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
265a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (QuantumRange*(0.5*cos((double) (2.0*MagickPI*
266351842fbf91597bd44b6200df92c8d45c98fe5adcristy        QuantumScale*pixel*value))+0.5));
267351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
268351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
269351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case DivideEvaluateOperator:
270351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
271351842fbf91597bd44b6200df92c8d45c98fe5adcristy      result=pixel/(value == 0.0 ? 1.0 : value);
272351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
273351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
2749fe8cd76fbf1dc52cef01a2b137ca1b659b244c8cristy    case ExponentialEvaluateOperator:
2759fe8cd76fbf1dc52cef01a2b137ca1b659b244c8cristy    {
27684ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) (QuantumRange*exp((double) (value*QuantumScale*pixel)));
2779fe8cd76fbf1dc52cef01a2b137ca1b659b244c8cristy      break;
2789fe8cd76fbf1dc52cef01a2b137ca1b659b244c8cristy    }
279351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case GaussianNoiseEvaluateOperator:
280351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
281a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) GenerateDifferentialNoise(random_info,pixel,
282351842fbf91597bd44b6200df92c8d45c98fe5adcristy        GaussianNoise,value);
283351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
284351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
285351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case ImpulseNoiseEvaluateOperator:
286351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
28784ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) GenerateDifferentialNoise(random_info,pixel,ImpulseNoise,
28884ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy        value);
289351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
290351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
291351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case LaplacianNoiseEvaluateOperator:
292351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
293a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) GenerateDifferentialNoise(random_info,pixel,
294351842fbf91597bd44b6200df92c8d45c98fe5adcristy        LaplacianNoise,value);
295351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
296351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
297351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case LeftShiftEvaluateOperator:
298351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
299a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) ((size_t) pixel << (size_t) (value+0.5));
300351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
301351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
302351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case LogEvaluateOperator:
303351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
304a9b9d2efa02426f73a9ecad1bf1e4401d5a6d852cristy      if ((QuantumScale*pixel) >= MagickEpsilon)
30584ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy        result=(double) (QuantumRange*log((double) (QuantumScale*value*pixel+
30684ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy          1.0))/log((double) (value+1.0)));
307351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
308351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
309351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case MaxEvaluateOperator:
310351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
311a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy      result=(double) EvaluateMax((double) pixel,value);
312351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
313351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
314351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case MeanEvaluateOperator:
315351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
316a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (pixel+value);
317351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
318351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
31908a3d70530ab973a425c8cdce82396825b6a7834cristy    case MedianEvaluateOperator:
32008a3d70530ab973a425c8cdce82396825b6a7834cristy    {
321a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (pixel+value);
32208a3d70530ab973a425c8cdce82396825b6a7834cristy      break;
32308a3d70530ab973a425c8cdce82396825b6a7834cristy    }
324351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case MinEvaluateOperator:
325351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
326a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy      result=(double) MagickMin((double) pixel,value);
327351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
328351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
329351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case MultiplicativeNoiseEvaluateOperator:
330351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
331a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) GenerateDifferentialNoise(random_info,pixel,
332351842fbf91597bd44b6200df92c8d45c98fe5adcristy        MultiplicativeGaussianNoise,value);
333351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
334351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
335351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case MultiplyEvaluateOperator:
336351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
337a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (value*pixel);
338351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
339351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
340351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case OrEvaluateOperator:
341351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
342a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) ((size_t) pixel | (size_t) (value+0.5));
343351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
344351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
345351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case PoissonNoiseEvaluateOperator:
346351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
34784ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) GenerateDifferentialNoise(random_info,pixel,PoissonNoise,
34884ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy        value);
349351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
350351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
351351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case PowEvaluateOperator:
352351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
35384ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) (QuantumRange*pow((double) (QuantumScale*pixel),(double)
35484ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy        value));
355351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
356351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
357351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case RightShiftEvaluateOperator:
358351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
359a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) ((size_t) pixel >> (size_t) (value+0.5));
360351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
361351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
3627c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy    case RootMeanSquareEvaluateOperator:
3637c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy    {
3647c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy      result=(double) (pixel*pixel+value);
3657c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy      break;
3667c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy    }
367351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case SetEvaluateOperator:
368351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
369351842fbf91597bd44b6200df92c8d45c98fe5adcristy      result=value;
370351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
371351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
372351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case SineEvaluateOperator:
373351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
374a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (QuantumRange*(0.5*sin((double) (2.0*MagickPI*
375351842fbf91597bd44b6200df92c8d45c98fe5adcristy        QuantumScale*pixel*value))+0.5));
376351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
377351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
378351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case SubtractEvaluateOperator:
379351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
380a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (pixel-value);
381351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
382351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
38312a3f8e5d02c1f840a79232564641eee7e0aea6dcristy    case SumEvaluateOperator:
38412a3f8e5d02c1f840a79232564641eee7e0aea6dcristy    {
385a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (pixel+value);
38612a3f8e5d02c1f840a79232564641eee7e0aea6dcristy      break;
38712a3f8e5d02c1f840a79232564641eee7e0aea6dcristy    }
388351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case ThresholdEvaluateOperator:
389351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
39084ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) (((double) pixel <= value) ? 0 : QuantumRange);
391351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
392351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
393351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case ThresholdBlackEvaluateOperator:
394351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
395a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (((double) pixel <= value) ? 0 : pixel);
396351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
397351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
398351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case ThresholdWhiteEvaluateOperator:
399351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
40084ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) (((double) pixel > value) ? QuantumRange : pixel);
401351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
402351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
403351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case UniformNoiseEvaluateOperator:
404351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
40584ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy      result=(double) GenerateDifferentialNoise(random_info,pixel,UniformNoise,
40684ff57f38f4ae2f2f52fbbf22a6511635f29c35bcristy        value);
407351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
408351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
409351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case XorEvaluateOperator:
410351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
411a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) ((size_t) pixel ^ (size_t) (value+0.5));
412351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
413351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
414351842fbf91597bd44b6200df92c8d45c98fe5adcristy  }
415d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  return(result);
416351842fbf91597bd44b6200df92c8d45c98fe5adcristy}
417351842fbf91597bd44b6200df92c8d45c98fe5adcristy
418d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristyMagickExport Image *EvaluateImages(const Image *images,
419d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  const MagickEvaluateOperator op,ExceptionInfo *exception)
420d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy{
421d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy#define EvaluateImageTag  "Evaluate/Image"
422d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
423d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  CacheView
424d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    *evaluate_view;
425d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
426d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  Image
4274ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy    *image;
428d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
429d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  MagickBooleanType
430d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    status;
431d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
4325f959473f334e196c6bf39b740c12cb4963fceebcristy  MagickOffsetType
4335f959473f334e196c6bf39b740c12cb4963fceebcristy    progress;
4345f959473f334e196c6bf39b740c12cb4963fceebcristy
43595a072b9674d607b5318a3283fd3952e82107828cristy  PixelChannels
43605d2ff7ebf21f659f5b11e45afb294e152f4330cdirk    **magick_restrict evaluate_pixels;
437d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
438d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  RandomInfo
43905d2ff7ebf21f659f5b11e45afb294e152f4330cdirk    **magick_restrict random_info;
440d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
441bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
442d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    number_images;
443d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
4445f959473f334e196c6bf39b740c12cb4963fceebcristy  ssize_t
4455f959473f334e196c6bf39b740c12cb4963fceebcristy    y;
4465f959473f334e196c6bf39b740c12cb4963fceebcristy
447b36143ff2559783289b92a25d4b4579a6a8b5618glennrp#if defined(MAGICKCORE_OPENMP_SUPPORT)
44857340e008c81f05c0adb4d8874dda11104d8bb7ecristy  unsigned long
44957340e008c81f05c0adb4d8874dda11104d8bb7ecristy    key;
450b36143ff2559783289b92a25d4b4579a6a8b5618glennrp#endif
45157340e008c81f05c0adb4d8874dda11104d8bb7ecristy
452d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  assert(images != (Image *) NULL);
453e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(images->signature == MagickCoreSignature);
454d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  if (images->debug != MagickFalse)
455d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
456d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  assert(exception != (ExceptionInfo *) NULL);
457e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
4584ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy  image=CloneImage(images,images->columns,images->rows,MagickTrue,
459d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    exception);
4604ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy  if (image == (Image *) NULL)
461d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    return((Image *) NULL);
4624ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
463d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    {
4644ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy      image=DestroyImage(image);
465d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy      return((Image *) NULL);
466d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    }
46708a3d70530ab973a425c8cdce82396825b6a7834cristy  number_images=GetImageListLength(images);
468751a6671c9b7480f3672a7ef6aa6e392f064b46ddirk  evaluate_pixels=AcquirePixelThreadSet(images);
46995a072b9674d607b5318a3283fd3952e82107828cristy  if (evaluate_pixels == (PixelChannels **) NULL)
470d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    {
4714ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy      image=DestroyImage(image);
472d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy      (void) ThrowMagickException(exception,GetMagickModule(),
473efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy        ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
474d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy      return((Image *) NULL);
475d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    }
476d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  /*
477d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy    Evaluate image pixels.
478d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  */
479d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  status=MagickTrue;
480d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  progress=0;
481d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  random_info=AcquireRandomInfoThreadSet();
48246ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  evaluate_view=AcquireAuthenticCacheView(image,exception);
48308a3d70530ab973a425c8cdce82396825b6a7834cristy  if (op == MedianEvaluateOperator)
48408a3d70530ab973a425c8cdce82396825b6a7834cristy    {
485e2a912b6c9086c98ec838baa0824cd8deca55538cristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
486ecd6dd161dfefd2b14a11c3d907bdeb648f5e201cristy      key=GetRandomSecretKey(random_info[0]);
4879a5a52fdbea9190e1c868ba9298a6f64d1c896d1cristy      #pragma omp parallel for schedule(static,4) shared(progress,status) \
4885e6b259130f9dbe0da4666f734937017babe573acristy        magick_threads(image,images,image->rows,key == ~0UL)
489a30fec6bcaca00206491523e7b7b59e707f15339cristy#endif
4904ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy      for (y=0; y < (ssize_t) image->rows; y++)
491a30fec6bcaca00206491523e7b7b59e707f15339cristy      {
492a30fec6bcaca00206491523e7b7b59e707f15339cristy        CacheView
493a30fec6bcaca00206491523e7b7b59e707f15339cristy          *image_view;
494d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
495a30fec6bcaca00206491523e7b7b59e707f15339cristy        const Image
496a30fec6bcaca00206491523e7b7b59e707f15339cristy          *next;
497d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
498a30fec6bcaca00206491523e7b7b59e707f15339cristy        const int
499a30fec6bcaca00206491523e7b7b59e707f15339cristy          id = GetOpenMPThreadId();
5006ebe97c3470475a87f649cfab09fa0cf1f249da3cristy
501a30fec6bcaca00206491523e7b7b59e707f15339cristy        register PixelChannels
502a30fec6bcaca00206491523e7b7b59e707f15339cristy          *evaluate_pixel;
503d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
504a30fec6bcaca00206491523e7b7b59e707f15339cristy        register Quantum
50505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
506d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
507a30fec6bcaca00206491523e7b7b59e707f15339cristy        register ssize_t
508a30fec6bcaca00206491523e7b7b59e707f15339cristy          x;
509d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
510a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (status == MagickFalse)
51108a3d70530ab973a425c8cdce82396825b6a7834cristy          continue;
51214a436ee80433ecd346653ee3ca478d3dbe7edf2cristy        q=QueueCacheViewAuthenticPixels(evaluate_view,0,y,image->columns,1,
51314a436ee80433ecd346653ee3ca478d3dbe7edf2cristy          exception);
514a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (q == (Quantum *) NULL)
515a30fec6bcaca00206491523e7b7b59e707f15339cristy          {
516a30fec6bcaca00206491523e7b7b59e707f15339cristy            status=MagickFalse;
517a30fec6bcaca00206491523e7b7b59e707f15339cristy            continue;
518a30fec6bcaca00206491523e7b7b59e707f15339cristy          }
519a30fec6bcaca00206491523e7b7b59e707f15339cristy        evaluate_pixel=evaluate_pixels[id];
5204ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy        for (x=0; x < (ssize_t) image->columns; x++)
521a30fec6bcaca00206491523e7b7b59e707f15339cristy        {
522a30fec6bcaca00206491523e7b7b59e707f15339cristy          register ssize_t
523a30fec6bcaca00206491523e7b7b59e707f15339cristy            j,
524a30fec6bcaca00206491523e7b7b59e707f15339cristy            k;
525a30fec6bcaca00206491523e7b7b59e707f15339cristy
526a30fec6bcaca00206491523e7b7b59e707f15339cristy          for (j=0; j < (ssize_t) number_images; j++)
527a30fec6bcaca00206491523e7b7b59e707f15339cristy            for (k=0; k < MaxPixelChannels; k++)
528a30fec6bcaca00206491523e7b7b59e707f15339cristy              evaluate_pixel[j].channel[k]=0.0;
529a30fec6bcaca00206491523e7b7b59e707f15339cristy          next=images;
530a30fec6bcaca00206491523e7b7b59e707f15339cristy          for (j=0; j < (ssize_t) number_images; j++)
531a30fec6bcaca00206491523e7b7b59e707f15339cristy          {
532a30fec6bcaca00206491523e7b7b59e707f15339cristy            register const Quantum
533a30fec6bcaca00206491523e7b7b59e707f15339cristy              *p;
534a30fec6bcaca00206491523e7b7b59e707f15339cristy
535a30fec6bcaca00206491523e7b7b59e707f15339cristy            register ssize_t
536a30fec6bcaca00206491523e7b7b59e707f15339cristy              i;
537a30fec6bcaca00206491523e7b7b59e707f15339cristy
53846ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy            image_view=AcquireVirtualCacheView(next,exception);
539a30fec6bcaca00206491523e7b7b59e707f15339cristy            p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
540a30fec6bcaca00206491523e7b7b59e707f15339cristy            if (p == (const Quantum *) NULL)
541a30fec6bcaca00206491523e7b7b59e707f15339cristy              {
542a30fec6bcaca00206491523e7b7b59e707f15339cristy                image_view=DestroyCacheView(image_view);
543a30fec6bcaca00206491523e7b7b59e707f15339cristy                break;
544a30fec6bcaca00206491523e7b7b59e707f15339cristy              }
5454ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy            for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
546a30fec6bcaca00206491523e7b7b59e707f15339cristy            {
5475a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              PixelChannel channel=GetPixelChannelChannel(image,i);
5485a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              PixelTrait evaluate_traits=GetPixelChannelTraits(image,channel);
5495a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              PixelTrait traits=GetPixelChannelTraits(next,channel);
550a30fec6bcaca00206491523e7b7b59e707f15339cristy              if ((traits == UndefinedPixelTrait) ||
551a30fec6bcaca00206491523e7b7b59e707f15339cristy                  (evaluate_traits == UndefinedPixelTrait))
552a30fec6bcaca00206491523e7b7b59e707f15339cristy                continue;
553a30fec6bcaca00206491523e7b7b59e707f15339cristy              if ((evaluate_traits & UpdatePixelTrait) == 0)
554a30fec6bcaca00206491523e7b7b59e707f15339cristy                continue;
555a30fec6bcaca00206491523e7b7b59e707f15339cristy              evaluate_pixel[j].channel[i]=ApplyEvaluateOperator(
5564ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy                random_info[id],GetPixelChannel(image,channel,p),op,
557a30fec6bcaca00206491523e7b7b59e707f15339cristy                evaluate_pixel[j].channel[i]);
558a30fec6bcaca00206491523e7b7b59e707f15339cristy            }
559a30fec6bcaca00206491523e7b7b59e707f15339cristy            image_view=DestroyCacheView(image_view);
560a30fec6bcaca00206491523e7b7b59e707f15339cristy            next=GetNextImageInList(next);
561a30fec6bcaca00206491523e7b7b59e707f15339cristy          }
562a30fec6bcaca00206491523e7b7b59e707f15339cristy          qsort((void *) evaluate_pixel,number_images,sizeof(*evaluate_pixel),
563a30fec6bcaca00206491523e7b7b59e707f15339cristy            IntensityCompare);
5644ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy          for (k=0; k < (ssize_t) GetPixelChannels(image); k++)
565a30fec6bcaca00206491523e7b7b59e707f15339cristy            q[k]=ClampToQuantum(evaluate_pixel[j/2].channel[k]);
5664ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy          q+=GetPixelChannels(image);
567d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy        }
568a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (SyncCacheViewAuthenticPixels(evaluate_view,exception) == MagickFalse)
569a30fec6bcaca00206491523e7b7b59e707f15339cristy          status=MagickFalse;
570a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (images->progress_monitor != (MagickProgressMonitor) NULL)
571a30fec6bcaca00206491523e7b7b59e707f15339cristy          {
572a30fec6bcaca00206491523e7b7b59e707f15339cristy            MagickBooleanType
573a30fec6bcaca00206491523e7b7b59e707f15339cristy              proceed;
574a30fec6bcaca00206491523e7b7b59e707f15339cristy
575a30fec6bcaca00206491523e7b7b59e707f15339cristy#if   defined(MAGICKCORE_OPENMP_SUPPORT)
576a30fec6bcaca00206491523e7b7b59e707f15339cristy            #pragma omp critical (MagickCore_EvaluateImages)
577a30fec6bcaca00206491523e7b7b59e707f15339cristy#endif
578a30fec6bcaca00206491523e7b7b59e707f15339cristy            proceed=SetImageProgress(images,EvaluateImageTag,progress++,
5794ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy              image->rows);
580a30fec6bcaca00206491523e7b7b59e707f15339cristy            if (proceed == MagickFalse)
581a30fec6bcaca00206491523e7b7b59e707f15339cristy              status=MagickFalse;
582a30fec6bcaca00206491523e7b7b59e707f15339cristy          }
583a30fec6bcaca00206491523e7b7b59e707f15339cristy      }
584a30fec6bcaca00206491523e7b7b59e707f15339cristy    }
585a30fec6bcaca00206491523e7b7b59e707f15339cristy  else
586a30fec6bcaca00206491523e7b7b59e707f15339cristy    {
587a30fec6bcaca00206491523e7b7b59e707f15339cristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
588ecd6dd161dfefd2b14a11c3d907bdeb648f5e201cristy      key=GetRandomSecretKey(random_info[0]);
5899a5a52fdbea9190e1c868ba9298a6f64d1c896d1cristy      #pragma omp parallel for schedule(static,4) shared(progress,status) \
5905e6b259130f9dbe0da4666f734937017babe573acristy        magick_threads(image,images,image->rows,key == ~0UL)
591a30fec6bcaca00206491523e7b7b59e707f15339cristy#endif
5924ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy      for (y=0; y < (ssize_t) image->rows; y++)
593d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy      {
594a30fec6bcaca00206491523e7b7b59e707f15339cristy        CacheView
595a30fec6bcaca00206491523e7b7b59e707f15339cristy          *image_view;
596a30fec6bcaca00206491523e7b7b59e707f15339cristy
597a30fec6bcaca00206491523e7b7b59e707f15339cristy        const Image
598a30fec6bcaca00206491523e7b7b59e707f15339cristy          *next;
599a30fec6bcaca00206491523e7b7b59e707f15339cristy
600a30fec6bcaca00206491523e7b7b59e707f15339cristy        const int
601a30fec6bcaca00206491523e7b7b59e707f15339cristy          id = GetOpenMPThreadId();
602a30fec6bcaca00206491523e7b7b59e707f15339cristy
60308a3d70530ab973a425c8cdce82396825b6a7834cristy        register ssize_t
604a30fec6bcaca00206491523e7b7b59e707f15339cristy          i,
605a30fec6bcaca00206491523e7b7b59e707f15339cristy          x;
60608a3d70530ab973a425c8cdce82396825b6a7834cristy
607a30fec6bcaca00206491523e7b7b59e707f15339cristy        register PixelChannels
608a30fec6bcaca00206491523e7b7b59e707f15339cristy          *evaluate_pixel;
609a30fec6bcaca00206491523e7b7b59e707f15339cristy
610a30fec6bcaca00206491523e7b7b59e707f15339cristy        register Quantum
61105d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict q;
612a30fec6bcaca00206491523e7b7b59e707f15339cristy
613a30fec6bcaca00206491523e7b7b59e707f15339cristy        ssize_t
614a30fec6bcaca00206491523e7b7b59e707f15339cristy          j;
615a30fec6bcaca00206491523e7b7b59e707f15339cristy
616a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (status == MagickFalse)
617a30fec6bcaca00206491523e7b7b59e707f15339cristy          continue;
618edb3f510ac6109703f134e42f9a2a0cc21866d78cristy        q=QueueCacheViewAuthenticPixels(evaluate_view,0,y,image->columns,1,
619edb3f510ac6109703f134e42f9a2a0cc21866d78cristy          exception);
620a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (q == (Quantum *) NULL)
621a30fec6bcaca00206491523e7b7b59e707f15339cristy          {
622a30fec6bcaca00206491523e7b7b59e707f15339cristy            status=MagickFalse;
623a30fec6bcaca00206491523e7b7b59e707f15339cristy            continue;
624a30fec6bcaca00206491523e7b7b59e707f15339cristy          }
625a30fec6bcaca00206491523e7b7b59e707f15339cristy        evaluate_pixel=evaluate_pixels[id];
6264ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy        for (j=0; j < (ssize_t) image->columns; j++)
627a30fec6bcaca00206491523e7b7b59e707f15339cristy          for (i=0; i < MaxPixelChannels; i++)
628a30fec6bcaca00206491523e7b7b59e707f15339cristy            evaluate_pixel[j].channel[i]=0.0;
62908a3d70530ab973a425c8cdce82396825b6a7834cristy        next=images;
630ba18a7a20da567238922ea992832fd3c8f70e7bbcristy        for (j=0; j < (ssize_t) number_images; j++)
63108a3d70530ab973a425c8cdce82396825b6a7834cristy        {
6324c08aed51c5899665ade97263692328eea4af106cristy          register const Quantum
63308a3d70530ab973a425c8cdce82396825b6a7834cristy            *p;
63408a3d70530ab973a425c8cdce82396825b6a7834cristy
63546ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy          image_view=AcquireVirtualCacheView(next,exception);
636b21069ba490260839c06334bdce983c4022781b0Cristy          p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,
637b21069ba490260839c06334bdce983c4022781b0Cristy            exception);
6384c08aed51c5899665ade97263692328eea4af106cristy          if (p == (const Quantum *) NULL)
63908a3d70530ab973a425c8cdce82396825b6a7834cristy            {
64008a3d70530ab973a425c8cdce82396825b6a7834cristy              image_view=DestroyCacheView(image_view);
64108a3d70530ab973a425c8cdce82396825b6a7834cristy              break;
64208a3d70530ab973a425c8cdce82396825b6a7834cristy            }
643b21069ba490260839c06334bdce983c4022781b0Cristy          for (x=0; x < (ssize_t) image->columns; x++)
644ba18a7a20da567238922ea992832fd3c8f70e7bbcristy          {
645a30fec6bcaca00206491523e7b7b59e707f15339cristy            register ssize_t
646a30fec6bcaca00206491523e7b7b59e707f15339cristy              i;
647ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
648883fde11debec15cedb05dc5d7228d8588066bc0cristy            if (GetPixelReadMask(next,p) == 0)
64910a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              {
650c94ba6f2e80cce201ffaf24ce7534019b6353dfecristy                p+=GetPixelChannels(next);
65110a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy                continue;
65210a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              }
65310a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            for (i=0; i < (ssize_t) GetPixelChannels(next); i++)
654a30fec6bcaca00206491523e7b7b59e707f15339cristy            {
6555a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy              PixelChannel channel=GetPixelChannelChannel(image,i);
656b21069ba490260839c06334bdce983c4022781b0Cristy              PixelTrait traits=GetPixelChannelTraits(next,channel);
657b21069ba490260839c06334bdce983c4022781b0Cristy              PixelTrait evaluate_traits=GetPixelChannelTraits(image,channel);
658a30fec6bcaca00206491523e7b7b59e707f15339cristy              if ((traits == UndefinedPixelTrait) ||
659a30fec6bcaca00206491523e7b7b59e707f15339cristy                  (evaluate_traits == UndefinedPixelTrait))
660a30fec6bcaca00206491523e7b7b59e707f15339cristy                continue;
661a30fec6bcaca00206491523e7b7b59e707f15339cristy              if ((traits & UpdatePixelTrait) == 0)
662a30fec6bcaca00206491523e7b7b59e707f15339cristy                continue;
663a30fec6bcaca00206491523e7b7b59e707f15339cristy              evaluate_pixel[x].channel[i]=ApplyEvaluateOperator(
664e7704276d758791b63a64832735480860086f104cristy                random_info[id],GetPixelChannel(image,channel,p),j == 0 ?
665e7704276d758791b63a64832735480860086f104cristy                AddEvaluateOperator : op,evaluate_pixel[x].channel[i]);
666a30fec6bcaca00206491523e7b7b59e707f15339cristy            }
667a30fec6bcaca00206491523e7b7b59e707f15339cristy            p+=GetPixelChannels(next);
668ba18a7a20da567238922ea992832fd3c8f70e7bbcristy          }
66908a3d70530ab973a425c8cdce82396825b6a7834cristy          image_view=DestroyCacheView(image_view);
67008a3d70530ab973a425c8cdce82396825b6a7834cristy          next=GetNextImageInList(next);
67108a3d70530ab973a425c8cdce82396825b6a7834cristy        }
6724ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy        for (x=0; x < (ssize_t) image->columns; x++)
67308a3d70530ab973a425c8cdce82396825b6a7834cristy        {
674a30fec6bcaca00206491523e7b7b59e707f15339cristy          register ssize_t
675a30fec6bcaca00206491523e7b7b59e707f15339cristy             i;
67608a3d70530ab973a425c8cdce82396825b6a7834cristy
677a30fec6bcaca00206491523e7b7b59e707f15339cristy          switch (op)
67808a3d70530ab973a425c8cdce82396825b6a7834cristy          {
679a30fec6bcaca00206491523e7b7b59e707f15339cristy            case MeanEvaluateOperator:
680a30fec6bcaca00206491523e7b7b59e707f15339cristy            {
6814ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy              for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
682a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy                evaluate_pixel[x].channel[i]/=(double) number_images;
683a30fec6bcaca00206491523e7b7b59e707f15339cristy              break;
684a30fec6bcaca00206491523e7b7b59e707f15339cristy            }
685a30fec6bcaca00206491523e7b7b59e707f15339cristy            case MultiplyEvaluateOperator:
686a30fec6bcaca00206491523e7b7b59e707f15339cristy            {
6874ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy              for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
688a30fec6bcaca00206491523e7b7b59e707f15339cristy              {
689a30fec6bcaca00206491523e7b7b59e707f15339cristy                register ssize_t
690a30fec6bcaca00206491523e7b7b59e707f15339cristy                  j;
691a30fec6bcaca00206491523e7b7b59e707f15339cristy
692a30fec6bcaca00206491523e7b7b59e707f15339cristy                for (j=0; j < (ssize_t) (number_images-1); j++)
693a30fec6bcaca00206491523e7b7b59e707f15339cristy                  evaluate_pixel[x].channel[i]*=QuantumScale;
694a30fec6bcaca00206491523e7b7b59e707f15339cristy              }
695a30fec6bcaca00206491523e7b7b59e707f15339cristy              break;
696a30fec6bcaca00206491523e7b7b59e707f15339cristy            }
6977c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy            case RootMeanSquareEvaluateOperator:
6987c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy            {
6997c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy              for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
7007c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy                evaluate_pixel[x].channel[i]=sqrt(evaluate_pixel[x].channel[i]/
7017c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy                  number_images);
7027c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy              break;
7037c4c78fe1a6a4884ad06dcf886cd1f6a40cc037ccristy            }
704a30fec6bcaca00206491523e7b7b59e707f15339cristy            default:
705a30fec6bcaca00206491523e7b7b59e707f15339cristy              break;
70608a3d70530ab973a425c8cdce82396825b6a7834cristy          }
707a30fec6bcaca00206491523e7b7b59e707f15339cristy        }
7084ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy        for (x=0; x < (ssize_t) image->columns; x++)
70908a3d70530ab973a425c8cdce82396825b6a7834cristy        {
710ba18a7a20da567238922ea992832fd3c8f70e7bbcristy          register ssize_t
711ba18a7a20da567238922ea992832fd3c8f70e7bbcristy            i;
712ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
713883fde11debec15cedb05dc5d7228d8588066bc0cristy          if (GetPixelReadMask(image,q) == 0)
71410a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            {
7154ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy              q+=GetPixelChannels(image);
71610a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy              continue;
71710a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy            }
7184ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
719ba18a7a20da567238922ea992832fd3c8f70e7bbcristy          {
7205a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelChannel channel=GetPixelChannelChannel(image,i);
7215a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy            PixelTrait traits=GetPixelChannelTraits(image,channel);
722a30fec6bcaca00206491523e7b7b59e707f15339cristy            if (traits == UndefinedPixelTrait)
723ba18a7a20da567238922ea992832fd3c8f70e7bbcristy              continue;
724ba18a7a20da567238922ea992832fd3c8f70e7bbcristy            if ((traits & UpdatePixelTrait) == 0)
725ba18a7a20da567238922ea992832fd3c8f70e7bbcristy              continue;
726a30fec6bcaca00206491523e7b7b59e707f15339cristy            q[i]=ClampToQuantum(evaluate_pixel[x].channel[i]);
727ba18a7a20da567238922ea992832fd3c8f70e7bbcristy          }
7284ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy          q+=GetPixelChannels(image);
72908a3d70530ab973a425c8cdce82396825b6a7834cristy        }
730a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (SyncCacheViewAuthenticPixels(evaluate_view,exception) == MagickFalse)
731a30fec6bcaca00206491523e7b7b59e707f15339cristy          status=MagickFalse;
732a30fec6bcaca00206491523e7b7b59e707f15339cristy        if (images->progress_monitor != (MagickProgressMonitor) NULL)
7339ee911ca8bd048eb050184ee491f631f947a6a8dcristy          {
734a30fec6bcaca00206491523e7b7b59e707f15339cristy            MagickBooleanType
735a30fec6bcaca00206491523e7b7b59e707f15339cristy              proceed;
736ba18a7a20da567238922ea992832fd3c8f70e7bbcristy
737a30fec6bcaca00206491523e7b7b59e707f15339cristy#if   defined(MAGICKCORE_OPENMP_SUPPORT)
738a30fec6bcaca00206491523e7b7b59e707f15339cristy            #pragma omp critical (MagickCore_EvaluateImages)
739a30fec6bcaca00206491523e7b7b59e707f15339cristy#endif
740a30fec6bcaca00206491523e7b7b59e707f15339cristy            proceed=SetImageProgress(images,EvaluateImageTag,progress++,
7414ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy              image->rows);
742a30fec6bcaca00206491523e7b7b59e707f15339cristy            if (proceed == MagickFalse)
743a30fec6bcaca00206491523e7b7b59e707f15339cristy              status=MagickFalse;
7449ee911ca8bd048eb050184ee491f631f947a6a8dcristy          }
7459ee911ca8bd048eb050184ee491f631f947a6a8dcristy      }
74608a3d70530ab973a425c8cdce82396825b6a7834cristy    }
747d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  evaluate_view=DestroyCacheView(evaluate_view);
748d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  evaluate_pixels=DestroyPixelThreadSet(evaluate_pixels);
749d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  random_info=DestroyRandomInfoThreadSet(random_info);
750d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy  if (status == MagickFalse)
7514ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy    image=DestroyImage(image);
7524ee2b0c11849aca22cbc22f1fb48e3ee9c8eaba5cristy  return(image);
753d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy}
754d18ae7ce9b6ff934472abb8e3fa73d0c1aed7d20cristy
755d42d995b9cb2a16e13221e665554417a5b7ec7fbcristyMagickExport MagickBooleanType EvaluateImage(Image *image,
756d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy  const MagickEvaluateOperator op,const double value,ExceptionInfo *exception)
757351842fbf91597bd44b6200df92c8d45c98fe5adcristy{
758351842fbf91597bd44b6200df92c8d45c98fe5adcristy  CacheView
759351842fbf91597bd44b6200df92c8d45c98fe5adcristy    *image_view;
760351842fbf91597bd44b6200df92c8d45c98fe5adcristy
761351842fbf91597bd44b6200df92c8d45c98fe5adcristy  MagickBooleanType
762351842fbf91597bd44b6200df92c8d45c98fe5adcristy    status;
763351842fbf91597bd44b6200df92c8d45c98fe5adcristy
7645f959473f334e196c6bf39b740c12cb4963fceebcristy  MagickOffsetType
7655f959473f334e196c6bf39b740c12cb4963fceebcristy    progress;
7665f959473f334e196c6bf39b740c12cb4963fceebcristy
767351842fbf91597bd44b6200df92c8d45c98fe5adcristy  RandomInfo
76805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk    **magick_restrict random_info;
769351842fbf91597bd44b6200df92c8d45c98fe5adcristy
7705f959473f334e196c6bf39b740c12cb4963fceebcristy  ssize_t
7715f959473f334e196c6bf39b740c12cb4963fceebcristy    y;
7725f959473f334e196c6bf39b740c12cb4963fceebcristy
773b36143ff2559783289b92a25d4b4579a6a8b5618glennrp#if defined(MAGICKCORE_OPENMP_SUPPORT)
77457340e008c81f05c0adb4d8874dda11104d8bb7ecristy  unsigned long
77557340e008c81f05c0adb4d8874dda11104d8bb7ecristy    key;
776b36143ff2559783289b92a25d4b4579a6a8b5618glennrp#endif
77757340e008c81f05c0adb4d8874dda11104d8bb7ecristy
778351842fbf91597bd44b6200df92c8d45c98fe5adcristy  assert(image != (Image *) NULL);
779e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
780351842fbf91597bd44b6200df92c8d45c98fe5adcristy  if (image->debug != MagickFalse)
781351842fbf91597bd44b6200df92c8d45c98fe5adcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
782351842fbf91597bd44b6200df92c8d45c98fe5adcristy  assert(exception != (ExceptionInfo *) NULL);
783e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
784574cc26500992189f637cd1cdf93d0654e7df7aecristy  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
785574cc26500992189f637cd1cdf93d0654e7df7aecristy    return(MagickFalse);
786351842fbf91597bd44b6200df92c8d45c98fe5adcristy  status=MagickTrue;
787351842fbf91597bd44b6200df92c8d45c98fe5adcristy  progress=0;
788351842fbf91597bd44b6200df92c8d45c98fe5adcristy  random_info=AcquireRandomInfoThreadSet();
78946ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireAuthenticCacheView(image,exception);
790351842fbf91597bd44b6200df92c8d45c98fe5adcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
791ecd6dd161dfefd2b14a11c3d907bdeb648f5e201cristy  key=GetRandomSecretKey(random_info[0]);
79257340e008c81f05c0adb4d8874dda11104d8bb7ecristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
7935e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(image,image,image->rows,key == ~0UL)
794351842fbf91597bd44b6200df92c8d45c98fe5adcristy#endif
795bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
796351842fbf91597bd44b6200df92c8d45c98fe5adcristy  {
7975c9e6f2ec2e7738ede83902931da0f80db60f565cristy    const int
7985c9e6f2ec2e7738ede83902931da0f80db60f565cristy      id = GetOpenMPThreadId();
7996ebe97c3470475a87f649cfab09fa0cf1f249da3cristy
8004c08aed51c5899665ade97263692328eea4af106cristy    register Quantum
80105d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
802351842fbf91597bd44b6200df92c8d45c98fe5adcristy
8035c9e6f2ec2e7738ede83902931da0f80db60f565cristy    register ssize_t
8045c9e6f2ec2e7738ede83902931da0f80db60f565cristy      x;
8055c9e6f2ec2e7738ede83902931da0f80db60f565cristy
806351842fbf91597bd44b6200df92c8d45c98fe5adcristy    if (status == MagickFalse)
807351842fbf91597bd44b6200df92c8d45c98fe5adcristy      continue;
808351842fbf91597bd44b6200df92c8d45c98fe5adcristy    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
809acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
810351842fbf91597bd44b6200df92c8d45c98fe5adcristy      {
811351842fbf91597bd44b6200df92c8d45c98fe5adcristy        status=MagickFalse;
812351842fbf91597bd44b6200df92c8d45c98fe5adcristy        continue;
813351842fbf91597bd44b6200df92c8d45c98fe5adcristy      }
814bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
815351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
8162f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy      double
8172f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy        result;
8182f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy
81949dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      register ssize_t
82049dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy        i;
82149dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy
82249dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
82349dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      {
8245a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
8255a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
82649dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy        if (traits == UndefinedPixelTrait)
82749dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy          continue;
8281eced097f7f4f51d5aa14d46079292fa1dcf0e77cristy        if (((traits & CopyPixelTrait) != 0) ||
829883fde11debec15cedb05dc5d7228d8588066bc0cristy            (GetPixelReadMask(image,q) == 0))
830177e41c20ccba692bc4c7797aeb817b2f80c7e8ccristy          continue;
8312f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy        result=ApplyEvaluateOperator(random_info[id],q[i],op,value);
8322f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy        if (op == MeanEvaluateOperator)
8332f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy          result/=2.0;
8342f5eaba185a3514cb1d704ea48c72cfa929da3fdcristy        q[i]=ClampToQuantum(result);
83549dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      }
836ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
837351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
838351842fbf91597bd44b6200df92c8d45c98fe5adcristy    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
839351842fbf91597bd44b6200df92c8d45c98fe5adcristy      status=MagickFalse;
840351842fbf91597bd44b6200df92c8d45c98fe5adcristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
841351842fbf91597bd44b6200df92c8d45c98fe5adcristy      {
842351842fbf91597bd44b6200df92c8d45c98fe5adcristy        MagickBooleanType
843351842fbf91597bd44b6200df92c8d45c98fe5adcristy          proceed;
844351842fbf91597bd44b6200df92c8d45c98fe5adcristy
845351842fbf91597bd44b6200df92c8d45c98fe5adcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
846ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy        #pragma omp critical (MagickCore_EvaluateImage)
847351842fbf91597bd44b6200df92c8d45c98fe5adcristy#endif
848351842fbf91597bd44b6200df92c8d45c98fe5adcristy        proceed=SetImageProgress(image,EvaluateImageTag,progress++,image->rows);
849351842fbf91597bd44b6200df92c8d45c98fe5adcristy        if (proceed == MagickFalse)
850351842fbf91597bd44b6200df92c8d45c98fe5adcristy          status=MagickFalse;
851351842fbf91597bd44b6200df92c8d45c98fe5adcristy      }
852351842fbf91597bd44b6200df92c8d45c98fe5adcristy  }
853351842fbf91597bd44b6200df92c8d45c98fe5adcristy  image_view=DestroyCacheView(image_view);
854351842fbf91597bd44b6200df92c8d45c98fe5adcristy  random_info=DestroyRandomInfoThreadSet(random_info);
855351842fbf91597bd44b6200df92c8d45c98fe5adcristy  return(status);
856351842fbf91597bd44b6200df92c8d45c98fe5adcristy}
857351842fbf91597bd44b6200df92c8d45c98fe5adcristy
858351842fbf91597bd44b6200df92c8d45c98fe5adcristy/*
859351842fbf91597bd44b6200df92c8d45c98fe5adcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
861351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
862351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
863351842fbf91597bd44b6200df92c8d45c98fe5adcristy%     F u n c t i o n I m a g e                                               %
864351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
865351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
866351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
867351842fbf91597bd44b6200df92c8d45c98fe5adcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
869351842fbf91597bd44b6200df92c8d45c98fe5adcristy%  FunctionImage() applies a value to the image with an arithmetic, relational,
870351842fbf91597bd44b6200df92c8d45c98fe5adcristy%  or logical operator to an image. Use these operations to lighten or darken
871351842fbf91597bd44b6200df92c8d45c98fe5adcristy%  an image, to increase or decrease contrast in an image, or to produce the
872351842fbf91597bd44b6200df92c8d45c98fe5adcristy%  "negative" of an image.
873351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
874d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  The format of the FunctionImage method is:
875351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
876351842fbf91597bd44b6200df92c8d45c98fe5adcristy%      MagickBooleanType FunctionImage(Image *image,
877bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%        const MagickFunction function,const ssize_t number_parameters,
878351842fbf91597bd44b6200df92c8d45c98fe5adcristy%        const double *parameters,ExceptionInfo *exception)
879351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
880351842fbf91597bd44b6200df92c8d45c98fe5adcristy%  A description of each parameter follows:
881351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
882351842fbf91597bd44b6200df92c8d45c98fe5adcristy%    o image: the image.
883351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
884351842fbf91597bd44b6200df92c8d45c98fe5adcristy%    o function: A channel function.
885351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
886351842fbf91597bd44b6200df92c8d45c98fe5adcristy%    o parameters: one or more parameters.
887351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
888351842fbf91597bd44b6200df92c8d45c98fe5adcristy%    o exception: return any errors or warnings in this structure.
889351842fbf91597bd44b6200df92c8d45c98fe5adcristy%
890351842fbf91597bd44b6200df92c8d45c98fe5adcristy*/
891351842fbf91597bd44b6200df92c8d45c98fe5adcristy
892351842fbf91597bd44b6200df92c8d45c98fe5adcristystatic Quantum ApplyFunction(Quantum pixel,const MagickFunction function,
893bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  const size_t number_parameters,const double *parameters,
894351842fbf91597bd44b6200df92c8d45c98fe5adcristy  ExceptionInfo *exception)
895351842fbf91597bd44b6200df92c8d45c98fe5adcristy{
896a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
897351842fbf91597bd44b6200df92c8d45c98fe5adcristy    result;
898351842fbf91597bd44b6200df92c8d45c98fe5adcristy
899bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
900351842fbf91597bd44b6200df92c8d45c98fe5adcristy    i;
901351842fbf91597bd44b6200df92c8d45c98fe5adcristy
902351842fbf91597bd44b6200df92c8d45c98fe5adcristy  (void) exception;
903351842fbf91597bd44b6200df92c8d45c98fe5adcristy  result=0.0;
904351842fbf91597bd44b6200df92c8d45c98fe5adcristy  switch (function)
905351842fbf91597bd44b6200df92c8d45c98fe5adcristy  {
906351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case PolynomialFunction:
907351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
908351842fbf91597bd44b6200df92c8d45c98fe5adcristy      /*
909e2a912b6c9086c98ec838baa0824cd8deca55538cristy        Polynomial: polynomial constants, highest to lowest order (e.g. c0*x^3+
910e2a912b6c9086c98ec838baa0824cd8deca55538cristy        c1*x^2+c2*x+c3).
91194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      */
912351842fbf91597bd44b6200df92c8d45c98fe5adcristy      result=0.0;
913bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (i=0; i < (ssize_t) number_parameters; i++)
91494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        result=result*QuantumScale*pixel+parameters[i];
91594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      result*=QuantumRange;
916351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
917351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
918351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case SinusoidFunction:
919351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
920a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      double
92194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        amplitude,
92294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        bias,
92394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        frequency,
92494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        phase;
92594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
92694a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      /*
92794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        Sinusoid: frequency, phase, amplitude, bias.
92894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      */
92994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      frequency=(number_parameters >= 1) ? parameters[0] : 1.0;
93094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      phase=(number_parameters >= 2) ? parameters[1] : 0.0;
93194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      amplitude=(number_parameters >= 3) ? parameters[2] : 0.5;
93294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      bias=(number_parameters >= 4) ? parameters[3] : 0.5;
933a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (QuantumRange*(amplitude*sin((double) (2.0*
93494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        MagickPI*(frequency*QuantumScale*pixel+phase/360.0)))+bias));
935351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
936351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
937351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case ArcsinFunction:
938351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
939a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      double
94094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        bias,
94194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        center,
94294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        range,
94394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        width;
94494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
94594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      /*
946e2a912b6c9086c98ec838baa0824cd8deca55538cristy        Arcsin (peged at range limits for invalid results): width, center,
947e2a912b6c9086c98ec838baa0824cd8deca55538cristy        range, and bias.
94894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      */
94994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      width=(number_parameters >= 1) ? parameters[0] : 1.0;
95094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      center=(number_parameters >= 2) ? parameters[1] : 0.5;
95194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      range=(number_parameters >= 3) ? parameters[2] : 1.0;
95294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      bias=(number_parameters >= 4) ? parameters[3] : 0.5;
95394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      result=2.0/width*(QuantumScale*pixel-center);
954351842fbf91597bd44b6200df92c8d45c98fe5adcristy      if ( result <= -1.0 )
95594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        result=bias-range/2.0;
956351842fbf91597bd44b6200df92c8d45c98fe5adcristy      else
95794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        if (result >= 1.0)
95894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy          result=bias+range/2.0;
95994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        else
960a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy          result=(double) (range/MagickPI*asin((double) result)+bias);
96194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      result*=QuantumRange;
962351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
963351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
964351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case ArctanFunction:
965351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
966a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      double
96794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        center,
96894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        bias,
96994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        range,
97094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        slope;
97194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
97294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      /*
97394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        Arctan: slope, center, range, and bias.
97494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      */
97594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      slope=(number_parameters >= 1) ? parameters[0] : 1.0;
97694a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      center=(number_parameters >= 2) ? parameters[1] : 0.5;
97794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      range=(number_parameters >= 3) ? parameters[2] : 1.0;
97894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      bias=(number_parameters >= 4) ? parameters[3] : 0.5;
979a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (MagickPI*slope*(QuantumScale*pixel-center));
980a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      result=(double) (QuantumRange*(range/MagickPI*atan((double)
98194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        result)+bias));
982351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
983351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
984351842fbf91597bd44b6200df92c8d45c98fe5adcristy    case UndefinedFunction:
985351842fbf91597bd44b6200df92c8d45c98fe5adcristy      break;
986351842fbf91597bd44b6200df92c8d45c98fe5adcristy  }
987351842fbf91597bd44b6200df92c8d45c98fe5adcristy  return(ClampToQuantum(result));
988351842fbf91597bd44b6200df92c8d45c98fe5adcristy}
989351842fbf91597bd44b6200df92c8d45c98fe5adcristy
990351842fbf91597bd44b6200df92c8d45c98fe5adcristyMagickExport MagickBooleanType FunctionImage(Image *image,
991bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  const MagickFunction function,const size_t number_parameters,
992351842fbf91597bd44b6200df92c8d45c98fe5adcristy  const double *parameters,ExceptionInfo *exception)
993351842fbf91597bd44b6200df92c8d45c98fe5adcristy{
994351842fbf91597bd44b6200df92c8d45c98fe5adcristy#define FunctionImageTag  "Function/Image "
995351842fbf91597bd44b6200df92c8d45c98fe5adcristy
996351842fbf91597bd44b6200df92c8d45c98fe5adcristy  CacheView
997351842fbf91597bd44b6200df92c8d45c98fe5adcristy    *image_view;
998351842fbf91597bd44b6200df92c8d45c98fe5adcristy
999351842fbf91597bd44b6200df92c8d45c98fe5adcristy  MagickBooleanType
1000351842fbf91597bd44b6200df92c8d45c98fe5adcristy    status;
1001351842fbf91597bd44b6200df92c8d45c98fe5adcristy
10025f959473f334e196c6bf39b740c12cb4963fceebcristy  MagickOffsetType
10035f959473f334e196c6bf39b740c12cb4963fceebcristy    progress;
10045f959473f334e196c6bf39b740c12cb4963fceebcristy
10055f959473f334e196c6bf39b740c12cb4963fceebcristy  ssize_t
10065f959473f334e196c6bf39b740c12cb4963fceebcristy    y;
10075f959473f334e196c6bf39b740c12cb4963fceebcristy
1008351842fbf91597bd44b6200df92c8d45c98fe5adcristy  assert(image != (Image *) NULL);
1009e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
1010351842fbf91597bd44b6200df92c8d45c98fe5adcristy  if (image->debug != MagickFalse)
1011351842fbf91597bd44b6200df92c8d45c98fe5adcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1012351842fbf91597bd44b6200df92c8d45c98fe5adcristy  assert(exception != (ExceptionInfo *) NULL);
1013e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
101421dc0310cdaa5cc6034a1e100746706f5ec089ebdirk#if defined(MAGICKCORE_OPENCL_SUPPORT)
101506c4f034881895074da3f4e4f206ba06429f042bdirk  if (AccelerateFunctionImage(image,function,number_parameters,parameters,
101606c4f034881895074da3f4e4f206ba06429f042bdirk        exception) != MagickFalse)
101794190b79d7abf8261e3a1af37aa7a7f86757b2d6Dusan Veljko    return(MagickTrue);
101821dc0310cdaa5cc6034a1e100746706f5ec089ebdirk#endif
1019574cc26500992189f637cd1cdf93d0654e7df7aecristy  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1020574cc26500992189f637cd1cdf93d0654e7df7aecristy    return(MagickFalse);
1021351842fbf91597bd44b6200df92c8d45c98fe5adcristy  status=MagickTrue;
1022351842fbf91597bd44b6200df92c8d45c98fe5adcristy  progress=0;
102346ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireAuthenticCacheView(image,exception);
1024351842fbf91597bd44b6200df92c8d45c98fe5adcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
1025ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
10265e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(image,image,image->rows,1)
1027351842fbf91597bd44b6200df92c8d45c98fe5adcristy#endif
1028bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
1029351842fbf91597bd44b6200df92c8d45c98fe5adcristy  {
10304c08aed51c5899665ade97263692328eea4af106cristy    register Quantum
103105d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
1032351842fbf91597bd44b6200df92c8d45c98fe5adcristy
103394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    register ssize_t
103494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      x;
103594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
1036351842fbf91597bd44b6200df92c8d45c98fe5adcristy    if (status == MagickFalse)
1037351842fbf91597bd44b6200df92c8d45c98fe5adcristy      continue;
1038351842fbf91597bd44b6200df92c8d45c98fe5adcristy    q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1039acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
1040351842fbf91597bd44b6200df92c8d45c98fe5adcristy      {
1041351842fbf91597bd44b6200df92c8d45c98fe5adcristy        status=MagickFalse;
1042351842fbf91597bd44b6200df92c8d45c98fe5adcristy        continue;
1043351842fbf91597bd44b6200df92c8d45c98fe5adcristy      }
1044bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
1045351842fbf91597bd44b6200df92c8d45c98fe5adcristy    {
104694a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      register ssize_t
104794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        i;
104894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
1049883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,q) == 0)
105010a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        {
105110a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          q+=GetPixelChannels(image);
105210a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          continue;
105310a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        }
105494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
105594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      {
10565a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
10575a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
105894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        if (traits == UndefinedPixelTrait)
105994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy          continue;
106094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        if ((traits & UpdatePixelTrait) == 0)
106194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy          continue;
106294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        q[i]=ApplyFunction(q[i],function,number_parameters,parameters,
106394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy          exception);
106494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      }
1065ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
1066351842fbf91597bd44b6200df92c8d45c98fe5adcristy    }
1067351842fbf91597bd44b6200df92c8d45c98fe5adcristy    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1068351842fbf91597bd44b6200df92c8d45c98fe5adcristy      status=MagickFalse;
1069351842fbf91597bd44b6200df92c8d45c98fe5adcristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
1070351842fbf91597bd44b6200df92c8d45c98fe5adcristy      {
1071351842fbf91597bd44b6200df92c8d45c98fe5adcristy        MagickBooleanType
1072351842fbf91597bd44b6200df92c8d45c98fe5adcristy          proceed;
1073351842fbf91597bd44b6200df92c8d45c98fe5adcristy
1074351842fbf91597bd44b6200df92c8d45c98fe5adcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
1075ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy        #pragma omp critical (MagickCore_FunctionImage)
1076351842fbf91597bd44b6200df92c8d45c98fe5adcristy#endif
1077351842fbf91597bd44b6200df92c8d45c98fe5adcristy        proceed=SetImageProgress(image,FunctionImageTag,progress++,image->rows);
1078351842fbf91597bd44b6200df92c8d45c98fe5adcristy        if (proceed == MagickFalse)
1079351842fbf91597bd44b6200df92c8d45c98fe5adcristy          status=MagickFalse;
1080351842fbf91597bd44b6200df92c8d45c98fe5adcristy      }
1081351842fbf91597bd44b6200df92c8d45c98fe5adcristy  }
1082351842fbf91597bd44b6200df92c8d45c98fe5adcristy  image_view=DestroyCacheView(image_view);
1083351842fbf91597bd44b6200df92c8d45c98fe5adcristy  return(status);
1084351842fbf91597bd44b6200df92c8d45c98fe5adcristy}
1085351842fbf91597bd44b6200df92c8d45c98fe5adcristy
1086351842fbf91597bd44b6200df92c8d45c98fe5adcristy/*
1087351842fbf91597bd44b6200df92c8d45c98fe5adcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1088351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
1089351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
1090351842fbf91597bd44b6200df92c8d45c98fe5adcristy%                                                                             %
109150908ac2139298d3f39d279d75c5868caea64316cristy%   G e t I m a g e E n t r o p y                                             %
109250908ac2139298d3f39d279d75c5868caea64316cristy%                                                                             %
109350908ac2139298d3f39d279d75c5868caea64316cristy%                                                                             %
109450908ac2139298d3f39d279d75c5868caea64316cristy%                                                                             %
109550908ac2139298d3f39d279d75c5868caea64316cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109650908ac2139298d3f39d279d75c5868caea64316cristy%
109750908ac2139298d3f39d279d75c5868caea64316cristy%  GetImageEntropy() returns the entropy of one or more image channels.
109850908ac2139298d3f39d279d75c5868caea64316cristy%
109950908ac2139298d3f39d279d75c5868caea64316cristy%  The format of the GetImageEntropy method is:
110050908ac2139298d3f39d279d75c5868caea64316cristy%
110150908ac2139298d3f39d279d75c5868caea64316cristy%      MagickBooleanType GetImageEntropy(const Image *image,double *entropy,
110250908ac2139298d3f39d279d75c5868caea64316cristy%        ExceptionInfo *exception)
110350908ac2139298d3f39d279d75c5868caea64316cristy%
110450908ac2139298d3f39d279d75c5868caea64316cristy%  A description of each parameter follows:
110550908ac2139298d3f39d279d75c5868caea64316cristy%
110650908ac2139298d3f39d279d75c5868caea64316cristy%    o image: the image.
110750908ac2139298d3f39d279d75c5868caea64316cristy%
110850908ac2139298d3f39d279d75c5868caea64316cristy%    o entropy: the average entropy of the selected channels.
110950908ac2139298d3f39d279d75c5868caea64316cristy%
111050908ac2139298d3f39d279d75c5868caea64316cristy%    o exception: return any errors or warnings in this structure.
111150908ac2139298d3f39d279d75c5868caea64316cristy%
111250908ac2139298d3f39d279d75c5868caea64316cristy*/
111350908ac2139298d3f39d279d75c5868caea64316cristyMagickExport MagickBooleanType GetImageEntropy(const Image *image,
111450908ac2139298d3f39d279d75c5868caea64316cristy  double *entropy,ExceptionInfo *exception)
111550908ac2139298d3f39d279d75c5868caea64316cristy{
111650908ac2139298d3f39d279d75c5868caea64316cristy  double
111750908ac2139298d3f39d279d75c5868caea64316cristy    area;
111850908ac2139298d3f39d279d75c5868caea64316cristy
111950908ac2139298d3f39d279d75c5868caea64316cristy  ChannelStatistics
112050908ac2139298d3f39d279d75c5868caea64316cristy    *channel_statistics;
112150908ac2139298d3f39d279d75c5868caea64316cristy
112250908ac2139298d3f39d279d75c5868caea64316cristy  register ssize_t
112350908ac2139298d3f39d279d75c5868caea64316cristy    i;
112450908ac2139298d3f39d279d75c5868caea64316cristy
112550908ac2139298d3f39d279d75c5868caea64316cristy  assert(image != (Image *) NULL);
1126e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
112750908ac2139298d3f39d279d75c5868caea64316cristy  if (image->debug != MagickFalse)
112850908ac2139298d3f39d279d75c5868caea64316cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
112950908ac2139298d3f39d279d75c5868caea64316cristy  channel_statistics=GetImageStatistics(image,exception);
113050908ac2139298d3f39d279d75c5868caea64316cristy  if (channel_statistics == (ChannelStatistics *) NULL)
113150908ac2139298d3f39d279d75c5868caea64316cristy    return(MagickFalse);
113250908ac2139298d3f39d279d75c5868caea64316cristy  area=0.0;
113350908ac2139298d3f39d279d75c5868caea64316cristy  channel_statistics[CompositePixelChannel].entropy=0.0;
113450908ac2139298d3f39d279d75c5868caea64316cristy  channel_statistics[CompositePixelChannel].standard_deviation=0.0;
113550908ac2139298d3f39d279d75c5868caea64316cristy  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
113650908ac2139298d3f39d279d75c5868caea64316cristy  {
113750908ac2139298d3f39d279d75c5868caea64316cristy    PixelChannel channel=GetPixelChannelChannel(image,i);
113850908ac2139298d3f39d279d75c5868caea64316cristy    PixelTrait traits=GetPixelChannelTraits(image,channel);
113950908ac2139298d3f39d279d75c5868caea64316cristy    if (traits == UndefinedPixelTrait)
114050908ac2139298d3f39d279d75c5868caea64316cristy      continue;
114150908ac2139298d3f39d279d75c5868caea64316cristy    if ((traits & UpdatePixelTrait) == 0)
114250908ac2139298d3f39d279d75c5868caea64316cristy      continue;
114350908ac2139298d3f39d279d75c5868caea64316cristy    channel_statistics[CompositePixelChannel].entropy+=
114450908ac2139298d3f39d279d75c5868caea64316cristy      channel_statistics[i].entropy;
114550908ac2139298d3f39d279d75c5868caea64316cristy    area++;
114650908ac2139298d3f39d279d75c5868caea64316cristy  }
114744706661c10e56ccd366f5d48b28f3103ff21e5ecristy  if (area > MagickEpsilon)
114844706661c10e56ccd366f5d48b28f3103ff21e5ecristy    {
114944706661c10e56ccd366f5d48b28f3103ff21e5ecristy      channel_statistics[CompositePixelChannel].entropy/=area;
115044706661c10e56ccd366f5d48b28f3103ff21e5ecristy      channel_statistics[CompositePixelChannel].standard_deviation=
115144706661c10e56ccd366f5d48b28f3103ff21e5ecristy        sqrt(channel_statistics[CompositePixelChannel].standard_deviation/area);
115244706661c10e56ccd366f5d48b28f3103ff21e5ecristy    }
115350908ac2139298d3f39d279d75c5868caea64316cristy  *entropy=channel_statistics[CompositePixelChannel].entropy;
115450908ac2139298d3f39d279d75c5868caea64316cristy  channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
115550908ac2139298d3f39d279d75c5868caea64316cristy    channel_statistics);
115650908ac2139298d3f39d279d75c5868caea64316cristy  return(MagickTrue);
115750908ac2139298d3f39d279d75c5868caea64316cristy}
115850908ac2139298d3f39d279d75c5868caea64316cristy
115950908ac2139298d3f39d279d75c5868caea64316cristy/*
116050908ac2139298d3f39d279d75c5868caea64316cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116150908ac2139298d3f39d279d75c5868caea64316cristy%                                                                             %
116250908ac2139298d3f39d279d75c5868caea64316cristy%                                                                             %
116350908ac2139298d3f39d279d75c5868caea64316cristy%                                                                             %
1164d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%   G e t I m a g e E x t r e m a                                             %
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1170d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  GetImageExtrema() returns the extrema of one or more image channels.
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1172d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  The format of the GetImageExtrema method is:
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1174d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%      MagickBooleanType GetImageExtrema(const Image *image,size_t *minima,
1175d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%        size_t *maxima,ExceptionInfo *exception)
11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o minima: the minimum value in the channel.
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o maxima: the maximum value in the channel.
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType GetImageExtrema(const Image *image,
1189bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t *minima,size_t *maxima,ExceptionInfo *exception)
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double
11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max,
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    min;
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
1199e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1202d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy  status=GetImageRange(image,&min,&max,exception);
1203bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  *minima=(size_t) ceil(min-0.5);
1204bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  *maxima=(size_t) floor(max+0.5);
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1213bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%   G e t I m a g e K u r t o s i s                                           %
1214bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%                                                                             %
1215bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%                                                                             %
1216bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%                                                                             %
1217bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1218bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1219bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%  GetImageKurtosis() returns the kurtosis and skewness of one or more image
1220bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%  channels.
1221bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1222bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%  The format of the GetImageKurtosis method is:
1223bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1224bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%      MagickBooleanType GetImageKurtosis(const Image *image,double *kurtosis,
1225bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%        double *skewness,ExceptionInfo *exception)
1226bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1227bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%  A description of each parameter follows:
1228bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1229bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%    o image: the image.
1230bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1231bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%    o kurtosis: the kurtosis of the channel.
1232bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1233bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%    o skewness: the skewness of the channel.
1234bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1235bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%    o exception: return any errors or warnings in this structure.
1236bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%
1237bd4a3c228c0e785517b8ab630b2cc6095373f710cristy*/
1238bd4a3c228c0e785517b8ab630b2cc6095373f710cristyMagickExport MagickBooleanType GetImageKurtosis(const Image *image,
1239bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  double *kurtosis,double *skewness,ExceptionInfo *exception)
1240bd4a3c228c0e785517b8ab630b2cc6095373f710cristy{
1241bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  CacheView
1242bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    *image_view;
1243bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1244bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  double
1245bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    area,
1246bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    mean,
1247bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    standard_deviation,
1248bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    sum_squares,
1249bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    sum_cubes,
1250bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    sum_fourth_power;
1251bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1252bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  MagickBooleanType
1253bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    status;
1254bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1255bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  ssize_t
1256bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    y;
1257bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1258bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  assert(image != (Image *) NULL);
1259e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
1260bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  if (image->debug != MagickFalse)
1261bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1262bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  status=MagickTrue;
1263bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  *kurtosis=0.0;
1264bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  *skewness=0.0;
1265bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  area=0.0;
1266bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  mean=0.0;
1267bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  standard_deviation=0.0;
1268bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  sum_squares=0.0;
1269bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  sum_cubes=0.0;
1270bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  sum_fourth_power=0.0;
1271bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  image_view=AcquireVirtualCacheView(image,exception);
1272bd4a3c228c0e785517b8ab630b2cc6095373f710cristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
1273bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  #pragma omp parallel for schedule(static,4) shared(status) \
1274bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    magick_threads(image,image,image->rows,1)
1275bd4a3c228c0e785517b8ab630b2cc6095373f710cristy#endif
1276bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  for (y=0; y < (ssize_t) image->rows; y++)
1277bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  {
1278bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    register const Quantum
127905d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
1280bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1281bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    register ssize_t
1282bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      x;
1283bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1284bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    if (status == MagickFalse)
1285bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      continue;
1286bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1287bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    if (p == (const Quantum *) NULL)
1288bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      {
1289bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        status=MagickFalse;
1290bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        continue;
1291bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      }
1292bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    for (x=0; x < (ssize_t) image->columns; x++)
1293bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    {
1294bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      register ssize_t
1295bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        i;
1296bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1297bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      if (GetPixelReadMask(image,p) == 0)
1298bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        {
1299bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          p+=GetPixelChannels(image);
1300bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          continue;
1301bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        }
1302bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1303bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      {
1304bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        PixelChannel channel=GetPixelChannelChannel(image,i);
1305bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
1306bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        if (traits == UndefinedPixelTrait)
1307bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          continue;
1308bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        if ((traits & UpdatePixelTrait) == 0)
1309bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          continue;
1310bd4a3c228c0e785517b8ab630b2cc6095373f710cristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
1311bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        #pragma omp critical (MagickCore_GetImageKurtosis)
1312bd4a3c228c0e785517b8ab630b2cc6095373f710cristy#endif
1313bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        {
1314bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          mean+=p[i];
1315bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          sum_squares+=(double) p[i]*p[i];
1316bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          sum_cubes+=(double) p[i]*p[i]*p[i];
1317bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          sum_fourth_power+=(double) p[i]*p[i]*p[i]*p[i];
1318bd4a3c228c0e785517b8ab630b2cc6095373f710cristy          area++;
1319bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        }
1320bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      }
1321bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      p+=GetPixelChannels(image);
1322bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    }
1323bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  }
1324bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  image_view=DestroyCacheView(image_view);
1325bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  if (area != 0.0)
1326bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    {
1327bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      mean/=area;
1328bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      sum_squares/=area;
1329bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      sum_cubes/=area;
1330bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      sum_fourth_power/=area;
1331bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    }
1332bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  standard_deviation=sqrt(sum_squares-(mean*mean));
1333bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  if (standard_deviation != 0.0)
1334bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    {
1335bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      *kurtosis=sum_fourth_power-4.0*mean*sum_cubes+6.0*mean*mean*sum_squares-
1336bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        3.0*mean*mean*mean*mean;
1337bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      *kurtosis/=standard_deviation*standard_deviation*standard_deviation*
1338bd4a3c228c0e785517b8ab630b2cc6095373f710cristy        standard_deviation;
1339bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      *kurtosis-=3.0;
1340bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      *skewness=sum_cubes-3.0*mean*sum_squares+2.0*mean*mean*mean;
1341bd4a3c228c0e785517b8ab630b2cc6095373f710cristy      *skewness/=standard_deviation*standard_deviation*standard_deviation;
1342bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    }
1343bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  return(status);
1344bd4a3c228c0e785517b8ab630b2cc6095373f710cristy}
1345bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
1346bd4a3c228c0e785517b8ab630b2cc6095373f710cristy/*
1347bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1348bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%                                                                             %
1349bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%                                                                             %
1350bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%                                                                             %
1351d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%   G e t I m a g e M e a n                                                   %
13523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13575048d30ffd6670a4b4c9986bbcb46b228afdd884cristy%  GetImageMean() returns the mean and standard deviation of one or more image
13585048d30ffd6670a4b4c9986bbcb46b228afdd884cristy%  channels.
13593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1360d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  The format of the GetImageMean method is:
13613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1362d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%      MagickBooleanType GetImageMean(const Image *image,double *mean,
1363d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%        double *standard_deviation,ExceptionInfo *exception)
13643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
13663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
13683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o mean: the average value in the channel.
13703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o standard_deviation: the standard deviation of the channel.
13723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
13743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
13753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
13763ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType GetImageMean(const Image *image,double *mean,
13773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  double *standard_deviation,ExceptionInfo *exception)
13783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
13795048d30ffd6670a4b4c9986bbcb46b228afdd884cristy  double
13805048d30ffd6670a4b4c9986bbcb46b228afdd884cristy    area;
13815048d30ffd6670a4b4c9986bbcb46b228afdd884cristy
1382fd9dcd4a312944c590a433c5d519146364fa6932cristy  ChannelStatistics
1383fd9dcd4a312944c590a433c5d519146364fa6932cristy    *channel_statistics;
13843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
138594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy  register ssize_t
138694a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    i;
138794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
13883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
1389e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
13903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
13913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1392d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy  channel_statistics=GetImageStatistics(image,exception);
1393fd9dcd4a312944c590a433c5d519146364fa6932cristy  if (channel_statistics == (ChannelStatistics *) NULL)
1394fd9dcd4a312944c590a433c5d519146364fa6932cristy    return(MagickFalse);
13955048d30ffd6670a4b4c9986bbcb46b228afdd884cristy  area=0.0;
13965f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].mean=0.0;
13975f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].standard_deviation=0.0;
139894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
139994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy  {
14005a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy    PixelChannel channel=GetPixelChannelChannel(image,i);
14015a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy    PixelTrait traits=GetPixelChannelTraits(image,channel);
140294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    if (traits == UndefinedPixelTrait)
140394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      continue;
140494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    if ((traits & UpdatePixelTrait) == 0)
140594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      continue;
14065f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].mean+=channel_statistics[i].mean;
14075f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].standard_deviation+=
140894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      channel_statistics[i].variance-channel_statistics[i].mean*
140994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      channel_statistics[i].mean;
141094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    area++;
141194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy  }
141244706661c10e56ccd366f5d48b28f3103ff21e5ecristy  if (area > MagickEpsilon)
141344706661c10e56ccd366f5d48b28f3103ff21e5ecristy    {
141444706661c10e56ccd366f5d48b28f3103ff21e5ecristy      channel_statistics[CompositePixelChannel].mean/=area;
141544706661c10e56ccd366f5d48b28f3103ff21e5ecristy      channel_statistics[CompositePixelChannel].standard_deviation=
141644706661c10e56ccd366f5d48b28f3103ff21e5ecristy        sqrt(channel_statistics[CompositePixelChannel].standard_deviation/area);
141744706661c10e56ccd366f5d48b28f3103ff21e5ecristy    }
14185f95f4f77efc46ff53593d750491c8f60698c983cristy  *mean=channel_statistics[CompositePixelChannel].mean;
1419e2a912b6c9086c98ec838baa0824cd8deca55538cristy  *standard_deviation=
1420e2a912b6c9086c98ec838baa0824cd8deca55538cristy    channel_statistics[CompositePixelChannel].standard_deviation;
1421fd9dcd4a312944c590a433c5d519146364fa6932cristy  channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
1422fd9dcd4a312944c590a433c5d519146364fa6932cristy    channel_statistics);
1423fd9dcd4a312944c590a433c5d519146364fa6932cristy  return(MagickTrue);
14243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
14253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
14273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1431bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%   G e t I m a g e M o m e n t s                                             %
14323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
14353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14376b3de2b7931481269d953d26f5de67471a8bf6f3cristy%  GetImageMoments() returns the normalized moments of one or more image
14386b3de2b7931481269d953d26f5de67471a8bf6f3cristy%  channels.
14393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1440bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%  The format of the GetImageMoments method is:
14413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1442bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%      ChannelMoments *GetImageMoments(const Image *image,
1443bd4a3c228c0e785517b8ab630b2cc6095373f710cristy%        ExceptionInfo *exception)
14443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
14463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
14483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1452e22513c47799a2fc63e145f93c6ee03269767ba0cristy
1453e22513c47799a2fc63e145f93c6ee03269767ba0cristystatic size_t GetImageChannels(const Image *image)
1454e22513c47799a2fc63e145f93c6ee03269767ba0cristy{
1455e22513c47799a2fc63e145f93c6ee03269767ba0cristy  register ssize_t
1456e22513c47799a2fc63e145f93c6ee03269767ba0cristy    i;
1457e22513c47799a2fc63e145f93c6ee03269767ba0cristy
1458e22513c47799a2fc63e145f93c6ee03269767ba0cristy  size_t
1459e22513c47799a2fc63e145f93c6ee03269767ba0cristy    channels;
1460e22513c47799a2fc63e145f93c6ee03269767ba0cristy
1461e22513c47799a2fc63e145f93c6ee03269767ba0cristy  channels=0;
1462e22513c47799a2fc63e145f93c6ee03269767ba0cristy  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1463e22513c47799a2fc63e145f93c6ee03269767ba0cristy  {
1464e22513c47799a2fc63e145f93c6ee03269767ba0cristy    PixelChannel channel=GetPixelChannelChannel(image,i);
1465e22513c47799a2fc63e145f93c6ee03269767ba0cristy    PixelTrait traits=GetPixelChannelTraits(image,channel);
1466e22513c47799a2fc63e145f93c6ee03269767ba0cristy    if ((traits & UpdatePixelTrait) != 0)
1467e22513c47799a2fc63e145f93c6ee03269767ba0cristy      channels++;
1468e22513c47799a2fc63e145f93c6ee03269767ba0cristy  }
146981c3360b2dfd109013aa2116eeb3a3caa29dd362cristy  return((size_t) (channels == 0 ? 1 : channels));
1470e22513c47799a2fc63e145f93c6ee03269767ba0cristy}
1471e22513c47799a2fc63e145f93c6ee03269767ba0cristy
1472bd4a3c228c0e785517b8ab630b2cc6095373f710cristyMagickExport ChannelMoments *GetImageMoments(const Image *image,
1473bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  ExceptionInfo *exception)
14743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1475bd4a3c228c0e785517b8ab630b2cc6095373f710cristy#define MaxNumberImageMoments  8
1476bd4a3c228c0e785517b8ab630b2cc6095373f710cristy
147794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy  CacheView
147894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    *image_view;
147994a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
1480bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  ChannelMoments
1481bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    *channel_moments;
14823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
14832a22aaab1509397c26047182cc73275f1f251075cristy  double
14842a22aaab1509397c26047182cc73275f1f251075cristy    M00[MaxPixelChannels+1],
14852a22aaab1509397c26047182cc73275f1f251075cristy    M01[MaxPixelChannels+1],
14862a22aaab1509397c26047182cc73275f1f251075cristy    M02[MaxPixelChannels+1],
14872a22aaab1509397c26047182cc73275f1f251075cristy    M03[MaxPixelChannels+1],
14882a22aaab1509397c26047182cc73275f1f251075cristy    M10[MaxPixelChannels+1],
14892a22aaab1509397c26047182cc73275f1f251075cristy    M11[MaxPixelChannels+1],
14902a22aaab1509397c26047182cc73275f1f251075cristy    M12[MaxPixelChannels+1],
14912a22aaab1509397c26047182cc73275f1f251075cristy    M20[MaxPixelChannels+1],
14922a22aaab1509397c26047182cc73275f1f251075cristy    M21[MaxPixelChannels+1],
14932a22aaab1509397c26047182cc73275f1f251075cristy    M22[MaxPixelChannels+1],
1494cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy    M30[MaxPixelChannels+1];
14952a22aaab1509397c26047182cc73275f1f251075cristy
14962a22aaab1509397c26047182cc73275f1f251075cristy  PointInfo
14972a22aaab1509397c26047182cc73275f1f251075cristy    centroid[MaxPixelChannels+1];
1498a9ec2bb46f44af91aac5091a183a3a874d9d480edirk
1499bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  ssize_t
15002a22aaab1509397c26047182cc73275f1f251075cristy    channel,
15013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    y;
15023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
1504e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
15053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
15063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
15072a22aaab1509397c26047182cc73275f1f251075cristy  channel_moments=(ChannelMoments *) AcquireQuantumMemory(MaxPixelChannels+1,
1508bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    sizeof(*channel_moments));
1509bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  if (channel_moments == (ChannelMoments *) NULL)
1510bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    return(channel_moments);
15112a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(channel_moments,0,(MaxPixelChannels+1)*
15122a22aaab1509397c26047182cc73275f1f251075cristy    sizeof(*channel_moments));
15132a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(centroid,0,sizeof(centroid));
15142a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M00,0,sizeof(M00));
15152a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M01,0,sizeof(M01));
15162a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M02,0,sizeof(M02));
15172a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M03,0,sizeof(M03));
15182a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M10,0,sizeof(M10));
15192a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M11,0,sizeof(M11));
15202a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M12,0,sizeof(M12));
15212a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M20,0,sizeof(M20));
15222a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M21,0,sizeof(M21));
15232a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M22,0,sizeof(M22));
15242a22aaab1509397c26047182cc73275f1f251075cristy  (void) ResetMagickMemory(M30,0,sizeof(M30));
152546ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireVirtualCacheView(image,exception);
1526bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
15273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
15284c08aed51c5899665ade97263692328eea4af106cristy    register const Quantum
152905d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
15303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1531bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    register ssize_t
15323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      x;
15333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15342a22aaab1509397c26047182cc73275f1f251075cristy    /*
15352a22aaab1509397c26047182cc73275f1f251075cristy      Compute center of mass (centroid).
15362a22aaab1509397c26047182cc73275f1f251075cristy    */
153794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
15384c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
15392a22aaab1509397c26047182cc73275f1f251075cristy      break;
1540bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
15413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
154294a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      register ssize_t
154394a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        i;
154494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy
1545883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,p) == 0)
15466d94a308cc4b42b09f5020acce05d779e24faa47cristy        {
15476d94a308cc4b42b09f5020acce05d779e24faa47cristy          p+=GetPixelChannels(image);
15486d94a308cc4b42b09f5020acce05d779e24faa47cristy          continue;
15496d94a308cc4b42b09f5020acce05d779e24faa47cristy        }
155094a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
155194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      {
15525a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
15535a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
155494a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy        if (traits == UndefinedPixelTrait)
155594a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy          continue;
15566d94a308cc4b42b09f5020acce05d779e24faa47cristy        if ((traits & UpdatePixelTrait) == 0)
155794a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy          continue;
1558cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy        M00[channel]+=QuantumScale*p[i];
1559b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M00[MaxPixelChannels]+=QuantumScale*p[i];
1560cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy        M10[channel]+=x*QuantumScale*p[i];
1561cb28e4323ca26dd27838e97fb6fe1ee678ce33d9cristy        M10[MaxPixelChannels]+=x*QuantumScale*p[i];
1562cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy        M01[channel]+=y*QuantumScale*p[i];
1563cb28e4323ca26dd27838e97fb6fe1ee678ce33d9cristy        M01[MaxPixelChannels]+=y*QuantumScale*p[i];
15642a22aaab1509397c26047182cc73275f1f251075cristy      }
15652a22aaab1509397c26047182cc73275f1f251075cristy      p+=GetPixelChannels(image);
15662a22aaab1509397c26047182cc73275f1f251075cristy    }
15672a22aaab1509397c26047182cc73275f1f251075cristy  }
15682a22aaab1509397c26047182cc73275f1f251075cristy  for (channel=0; channel <= MaxPixelChannels; channel++)
15692a22aaab1509397c26047182cc73275f1f251075cristy  {
15702a22aaab1509397c26047182cc73275f1f251075cristy    /*
15712a22aaab1509397c26047182cc73275f1f251075cristy       Compute center of mass (centroid).
15722a22aaab1509397c26047182cc73275f1f251075cristy    */
15730633a1f35940363594ecb272bb113e045fd65f93cristy    if (M00[channel] < MagickEpsilon)
15740633a1f35940363594ecb272bb113e045fd65f93cristy      {
15750633a1f35940363594ecb272bb113e045fd65f93cristy        M00[channel]+=MagickEpsilon;
157681c3360b2dfd109013aa2116eeb3a3caa29dd362cristy        centroid[channel].x=(double) image->columns/2.0;
157781c3360b2dfd109013aa2116eeb3a3caa29dd362cristy        centroid[channel].y=(double) image->rows/2.0;
15780633a1f35940363594ecb272bb113e045fd65f93cristy        continue;
15790633a1f35940363594ecb272bb113e045fd65f93cristy      }
158012cdaaec0ce96a51b80c1c5ceea1a4ea7c4574f7cristy    M00[channel]+=MagickEpsilon;
15812a22aaab1509397c26047182cc73275f1f251075cristy    centroid[channel].x=M10[channel]/M00[channel];
15822a22aaab1509397c26047182cc73275f1f251075cristy    centroid[channel].y=M01[channel]/M00[channel];
15832a22aaab1509397c26047182cc73275f1f251075cristy  }
15842a22aaab1509397c26047182cc73275f1f251075cristy  for (y=0; y < (ssize_t) image->rows; y++)
15852a22aaab1509397c26047182cc73275f1f251075cristy  {
15862a22aaab1509397c26047182cc73275f1f251075cristy    register const Quantum
158705d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
15882a22aaab1509397c26047182cc73275f1f251075cristy
15892a22aaab1509397c26047182cc73275f1f251075cristy    register ssize_t
15902a22aaab1509397c26047182cc73275f1f251075cristy      x;
15912a22aaab1509397c26047182cc73275f1f251075cristy
15922a22aaab1509397c26047182cc73275f1f251075cristy    /*
15932a22aaab1509397c26047182cc73275f1f251075cristy      Compute the image moments.
15942a22aaab1509397c26047182cc73275f1f251075cristy    */
15952a22aaab1509397c26047182cc73275f1f251075cristy    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
15962a22aaab1509397c26047182cc73275f1f251075cristy    if (p == (const Quantum *) NULL)
15972a22aaab1509397c26047182cc73275f1f251075cristy      break;
15982a22aaab1509397c26047182cc73275f1f251075cristy    for (x=0; x < (ssize_t) image->columns; x++)
15992a22aaab1509397c26047182cc73275f1f251075cristy    {
16002a22aaab1509397c26047182cc73275f1f251075cristy      register ssize_t
16012a22aaab1509397c26047182cc73275f1f251075cristy        i;
16022a22aaab1509397c26047182cc73275f1f251075cristy
16032a22aaab1509397c26047182cc73275f1f251075cristy      if (GetPixelReadMask(image,p) == 0)
16043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
16052a22aaab1509397c26047182cc73275f1f251075cristy          p+=GetPixelChannels(image);
16062a22aaab1509397c26047182cc73275f1f251075cristy          continue;
16073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
16082a22aaab1509397c26047182cc73275f1f251075cristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
16092a22aaab1509397c26047182cc73275f1f251075cristy      {
16102a22aaab1509397c26047182cc73275f1f251075cristy        PixelChannel channel=GetPixelChannelChannel(image,i);
16112a22aaab1509397c26047182cc73275f1f251075cristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
16122a22aaab1509397c26047182cc73275f1f251075cristy        if (traits == UndefinedPixelTrait)
16132a22aaab1509397c26047182cc73275f1f251075cristy          continue;
16142a22aaab1509397c26047182cc73275f1f251075cristy        if ((traits & UpdatePixelTrait) == 0)
16152a22aaab1509397c26047182cc73275f1f251075cristy          continue;
161620b0c74e0979efb79370e5e9bd6047996ffa7b43cristy        M11[channel]+=(x-centroid[channel].x)*(y-centroid[channel].y)*
1617cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          QuantumScale*p[i];
1618b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M11[MaxPixelChannels]+=(x-centroid[channel].x)*(y-centroid[channel].y)*
1619b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          QuantumScale*p[i];
162020b0c74e0979efb79370e5e9bd6047996ffa7b43cristy        M20[channel]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1621cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          QuantumScale*p[i];
1622b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M20[MaxPixelChannels]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1623b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          QuantumScale*p[i];
162420b0c74e0979efb79370e5e9bd6047996ffa7b43cristy        M02[channel]+=(y-centroid[channel].y)*(y-centroid[channel].y)*
1625cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          QuantumScale*p[i];
1626b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M02[MaxPixelChannels]+=(y-centroid[channel].y)*(y-centroid[channel].y)*
1627b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          QuantumScale*p[i];
16282a22aaab1509397c26047182cc73275f1f251075cristy        M21[channel]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1629cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          (y-centroid[channel].y)*QuantumScale*p[i];
1630b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M21[MaxPixelChannels]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1631b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          (y-centroid[channel].y)*QuantumScale*p[i];
16322a22aaab1509397c26047182cc73275f1f251075cristy        M12[channel]+=(x-centroid[channel].x)*(y-centroid[channel].y)*
1633cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          (y-centroid[channel].y)*QuantumScale*p[i];
1634b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M12[MaxPixelChannels]+=(x-centroid[channel].x)*(y-centroid[channel].y)*
1635b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          (y-centroid[channel].y)*QuantumScale*p[i];
16362a22aaab1509397c26047182cc73275f1f251075cristy        M22[channel]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1637cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          (y-centroid[channel].y)*(y-centroid[channel].y)*QuantumScale*p[i];
1638b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M22[MaxPixelChannels]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1639b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          (y-centroid[channel].y)*(y-centroid[channel].y)*QuantumScale*p[i];
16402a22aaab1509397c26047182cc73275f1f251075cristy        M30[channel]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1641cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          (x-centroid[channel].x)*QuantumScale*p[i];
1642b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M30[MaxPixelChannels]+=(x-centroid[channel].x)*(x-centroid[channel].x)*
1643b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          (x-centroid[channel].x)*QuantumScale*p[i];
16442a22aaab1509397c26047182cc73275f1f251075cristy        M03[channel]+=(y-centroid[channel].y)*(y-centroid[channel].y)*
1645cb9af4ac6134e7e15e7d344489e9e0f634e1b4c1cristy          (y-centroid[channel].y)*QuantumScale*p[i];
1646b5a738f267f28d95bf0103934aa48a50f2d502b9cristy        M03[MaxPixelChannels]+=(y-centroid[channel].y)*(y-centroid[channel].y)*
1647b5a738f267f28d95bf0103934aa48a50f2d502b9cristy          (y-centroid[channel].y)*QuantumScale*p[i];
164894a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy      }
1649ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
16503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
16513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1652e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M00[MaxPixelChannels]/=GetImageChannels(image);
1653e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M01[MaxPixelChannels]/=GetImageChannels(image);
1654e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M02[MaxPixelChannels]/=GetImageChannels(image);
1655e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M03[MaxPixelChannels]/=GetImageChannels(image);
1656e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M10[MaxPixelChannels]/=GetImageChannels(image);
1657e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M11[MaxPixelChannels]/=GetImageChannels(image);
1658e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M12[MaxPixelChannels]/=GetImageChannels(image);
1659e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M20[MaxPixelChannels]/=GetImageChannels(image);
1660e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M21[MaxPixelChannels]/=GetImageChannels(image);
1661e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M22[MaxPixelChannels]/=GetImageChannels(image);
1662e22513c47799a2fc63e145f93c6ee03269767ba0cristy  M30[MaxPixelChannels]/=GetImageChannels(image);
16632a22aaab1509397c26047182cc73275f1f251075cristy  for (channel=0; channel <= MaxPixelChannels; channel++)
16642a22aaab1509397c26047182cc73275f1f251075cristy  {
16652a22aaab1509397c26047182cc73275f1f251075cristy    /*
1666a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy      Compute elliptical angle, major and minor axes, eccentricity, & intensity.
1667a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    */
1668a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    channel_moments[channel].centroid=centroid[channel];
1669a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    channel_moments[channel].ellipse_axis.x=sqrt((2.0/M00[channel])*
1670a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy      ((M20[channel]+M02[channel])+sqrt(4.0*M11[channel]*M11[channel]+
1671a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy      (M20[channel]-M02[channel])*(M20[channel]-M02[channel]))));
1672a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    channel_moments[channel].ellipse_axis.y=sqrt((2.0/M00[channel])*
1673a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy      ((M20[channel]+M02[channel])-sqrt(4.0*M11[channel]*M11[channel]+
1674a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy      (M20[channel]-M02[channel])*(M20[channel]-M02[channel]))));
1675a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    channel_moments[channel].ellipse_angle=RadiansToDegrees(0.5*atan(2.0*
1676c17edf220b9be5b9d35d28687cdba90a641b0edfcristy      M11[channel]/(M20[channel]-M02[channel]+MagickEpsilon)));
1677a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    channel_moments[channel].ellipse_eccentricity=sqrt(1.0-(
1678a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy      channel_moments[channel].ellipse_axis.y/
1679c17edf220b9be5b9d35d28687cdba90a641b0edfcristy      (channel_moments[channel].ellipse_axis.x+MagickEpsilon)));
16800c0bae941a2dc028b90b78c9f7086a93ab6417becristy    channel_moments[channel].ellipse_intensity=M00[channel]/
1681794f200f5b83a30d81027733122ed5f3506d3e03cristy      (MagickPI*channel_moments[channel].ellipse_axis.x*
1682c17edf220b9be5b9d35d28687cdba90a641b0edfcristy      channel_moments[channel].ellipse_axis.y+MagickEpsilon);
1683a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy  }
1684a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy  for (channel=0; channel <= MaxPixelChannels; channel++)
1685a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy  {
1686a520f2362aafd6cb7ae888ff3559b09ac20b7924cristy    /*
16872a22aaab1509397c26047182cc73275f1f251075cristy      Normalize image moments.
16882a22aaab1509397c26047182cc73275f1f251075cristy    */
16892b8f9ffb1ee6c2011758352e89efcbf640112873cristy    M10[channel]=0.0;
16902b8f9ffb1ee6c2011758352e89efcbf640112873cristy    M01[channel]=0.0;
1691b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M11[channel]/=pow(M00[channel],1.0+(1.0+1.0)/2.0);
1692b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M20[channel]/=pow(M00[channel],1.0+(2.0+0.0)/2.0);
1693b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M02[channel]/=pow(M00[channel],1.0+(0.0+2.0)/2.0);
1694b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M21[channel]/=pow(M00[channel],1.0+(2.0+1.0)/2.0);
1695b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M12[channel]/=pow(M00[channel],1.0+(1.0+2.0)/2.0);
1696b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M22[channel]/=pow(M00[channel],1.0+(2.0+2.0)/2.0);
1697b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M30[channel]/=pow(M00[channel],1.0+(3.0+0.0)/2.0);
1698b51417b1df71e6b1d82bb44e01db9ffdb0719709cristy    M03[channel]/=pow(M00[channel],1.0+(0.0+3.0)/2.0);
16992b8f9ffb1ee6c2011758352e89efcbf640112873cristy    M00[channel]=1.0;
17002a22aaab1509397c26047182cc73275f1f251075cristy  }
170194a757875f6ef9dcbbc4f97bbca32b736d28de4ecristy  image_view=DestroyCacheView(image_view);
17022a22aaab1509397c26047182cc73275f1f251075cristy  for (channel=0; channel <= MaxPixelChannels; channel++)
17032a22aaab1509397c26047182cc73275f1f251075cristy  {
17042a22aaab1509397c26047182cc73275f1f251075cristy    /*
17052a22aaab1509397c26047182cc73275f1f251075cristy      Compute Hu invariant moments.
17062a22aaab1509397c26047182cc73275f1f251075cristy    */
170757f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[0]=M20[channel]+M02[channel];
170857f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[1]=(M20[channel]-M02[channel])*
17092a22aaab1509397c26047182cc73275f1f251075cristy      (M20[channel]-M02[channel])+4.0*M11[channel]*M11[channel];
171057f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[2]=(M30[channel]-3.0*M12[channel])*
17112a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]-3.0*M12[channel])+(3.0*M21[channel]-M03[channel])*
17122a22aaab1509397c26047182cc73275f1f251075cristy      (3.0*M21[channel]-M03[channel]);
171357f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[3]=(M30[channel]+M12[channel])*
17142a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])+(M21[channel]+M03[channel])*
17152a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel]);
171657f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[4]=(M30[channel]-3.0*M12[channel])*
17172a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])*((M30[channel]+M12[channel])*
17182a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])-3.0*(M21[channel]+M03[channel])*
17192a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel]))+(3.0*M21[channel]-M03[channel])*
17202a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel])*(3.0*(M30[channel]+M12[channel])*
17212a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])-(M21[channel]+M03[channel])*
17222a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel]));
172357f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[5]=(M20[channel]-M02[channel])*
17242a22aaab1509397c26047182cc73275f1f251075cristy      ((M30[channel]+M12[channel])*(M30[channel]+M12[channel])-
17252a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel])*(M21[channel]+M03[channel]))+
17262a22aaab1509397c26047182cc73275f1f251075cristy      4.0*M11[channel]*(M30[channel]+M12[channel])*(M21[channel]+M03[channel]);
172757f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[6]=(3.0*M21[channel]-M03[channel])*
17282a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])*((M30[channel]+M12[channel])*
17292a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])-3.0*(M21[channel]+M03[channel])*
17302a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel]))-(M30[channel]-3*M12[channel])*
17312a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel])*(3.0*(M30[channel]+M12[channel])*
17322a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])-(M21[channel]+M03[channel])*
17332a22aaab1509397c26047182cc73275f1f251075cristy      (M21[channel]+M03[channel]));
173457f71289ef12fb275c908972156e7e397d9e07bbcristy    channel_moments[channel].invariant[7]=M11[channel]*((M30[channel]+
173557f71289ef12fb275c908972156e7e397d9e07bbcristy      M12[channel])*(M30[channel]+M12[channel])-(M03[channel]+M21[channel])*
17362a22aaab1509397c26047182cc73275f1f251075cristy      (M03[channel]+M21[channel]))-(M20[channel]-M02[channel])*
17372a22aaab1509397c26047182cc73275f1f251075cristy      (M30[channel]+M12[channel])*(M03[channel]+M21[channel]);
17382a22aaab1509397c26047182cc73275f1f251075cristy  }
17392a22aaab1509397c26047182cc73275f1f251075cristy  if (y < (ssize_t) image->rows)
1740bd4a3c228c0e785517b8ab630b2cc6095373f710cristy    channel_moments=(ChannelMoments *) RelinquishMagickMemory(channel_moments);
1741bd4a3c228c0e785517b8ab630b2cc6095373f710cristy  return(channel_moments);
17423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
174346f08209f719f4adeea742c45873c2714e80cdb9cristy
17443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
17453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
17463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
17473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
17483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1749f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%   G e t I m a g e C h a n n e l P e r c e p t u a l H a s h                 %
1750f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%                                                                             %
1751f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%                                                                             %
1752f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%                                                                             %
1753f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1754f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1755b3538ec3d53d5853f18e99b510cd855ac870c281cristy%  GetImagePerceptualHash() returns the perceptual hash of one or more
1756f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%  image channels.
1757f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1758b3538ec3d53d5853f18e99b510cd855ac870c281cristy%  The format of the GetImagePerceptualHash method is:
1759f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1760b3538ec3d53d5853f18e99b510cd855ac870c281cristy%      ChannelPerceptualHash *GetImagePerceptualHash(const Image *image,
1761f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%        ExceptionInfo *exception)
1762f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1763f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%  A description of each parameter follows:
1764f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1765f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%    o image: the image.
1766f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1767f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%    o exception: return any errors or warnings in this structure.
1768f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%
1769f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy*/
1770f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1771f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristystatic inline double MagickLog10(const double x)
1772f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy{
1773f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy#define Log10Epsilon  (1.0e-11)
1774f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1775f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy if (fabs(x) < Log10Epsilon)
1776f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy   return(log10(Log10Epsilon));
1777f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy return(log10(fabs(x)));
1778f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy}
1779f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1780b3538ec3d53d5853f18e99b510cd855ac870c281cristyMagickExport ChannelPerceptualHash *GetImagePerceptualHash(
1781f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  const Image *image,ExceptionInfo *exception)
1782f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy{
1783f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  ChannelMoments
1784f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    *moments;
1785f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1786f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  ChannelPerceptualHash
1787f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    *perceptual_hash;
1788f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1789f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  Image
1790f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    *hash_image;
1791f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1792f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  MagickBooleanType
1793f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    status;
1794f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1795f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  register ssize_t
1796f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    i;
1797f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1798f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  ssize_t
1799f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    channel;
1800f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1801f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  /*
1802f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    Blur then transform to sRGB colorspace.
1803f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  */
1804f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  hash_image=BlurImage(image,0.0,1.0,exception);
1805f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (hash_image == (Image *) NULL)
1806f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    return((ChannelPerceptualHash *) NULL);
1807f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  hash_image->depth=8;
1808f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  status=TransformImageColorspace(hash_image,sRGBColorspace,exception);
1809f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (status == MagickFalse)
1810f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    return((ChannelPerceptualHash *) NULL);
1811f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  moments=GetImageMoments(hash_image,exception);
1812f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  hash_image=DestroyImage(hash_image);
1813f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (moments == (ChannelMoments *) NULL)
1814f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    return((ChannelPerceptualHash *) NULL);
1815f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  perceptual_hash=(ChannelPerceptualHash *) AcquireQuantumMemory(
181650debe5028731f7b7218c99c9c70e87ae5d43832Cristy    MaxPixelChannels+1UL,sizeof(*perceptual_hash));
1817f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (perceptual_hash == (ChannelPerceptualHash *) NULL)
1818f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    return((ChannelPerceptualHash *) NULL);
1819f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  for (channel=0; channel <= MaxPixelChannels; channel++)
18203ac6aa903557af75f8149bad7c8aa512158fa445cristy    for (i=0; i < MaximumNumberOfImageMoments; i++)
1821c018762fb6f380c9d0b1057ec2390e7422ab5178cristy      perceptual_hash[channel].srgb_hu_phash[i]=
182257f71289ef12fb275c908972156e7e397d9e07bbcristy        (-MagickLog10(moments[channel].invariant[i]));
1823f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  moments=(ChannelMoments *) RelinquishMagickMemory(moments);
1824f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  /*
1825f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    Blur then transform to HCLp colorspace.
1826f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  */
1827f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  hash_image=BlurImage(image,0.0,1.0,exception);
1828f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (hash_image == (Image *) NULL)
1829f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    {
1830f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy      perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
1831f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy        perceptual_hash);
1832f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy      return((ChannelPerceptualHash *) NULL);
1833f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    }
1834f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  hash_image->depth=8;
1835f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  status=TransformImageColorspace(hash_image,HCLpColorspace,exception);
1836f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (status == MagickFalse)
1837f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    {
1838f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy      perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
1839f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy        perceptual_hash);
1840f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy      return((ChannelPerceptualHash *) NULL);
1841f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    }
1842f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  moments=GetImageMoments(hash_image,exception);
1843f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  hash_image=DestroyImage(hash_image);
1844f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  if (moments == (ChannelMoments *) NULL)
1845f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    {
1846f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy      perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
1847f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy        perceptual_hash);
1848f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy      return((ChannelPerceptualHash *) NULL);
1849f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy    }
1850f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  for (channel=0; channel <= MaxPixelChannels; channel++)
18513ac6aa903557af75f8149bad7c8aa512158fa445cristy    for (i=0; i < MaximumNumberOfImageMoments; i++)
1852c018762fb6f380c9d0b1057ec2390e7422ab5178cristy      perceptual_hash[channel].hclp_hu_phash[i]=
185357f71289ef12fb275c908972156e7e397d9e07bbcristy        (-MagickLog10(moments[channel].invariant[i]));
1854f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  moments=(ChannelMoments *) RelinquishMagickMemory(moments);
1855f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy  return(perceptual_hash);
1856f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy}
1857f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy
1858f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy/*
1859f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1860f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%                                                                             %
1861f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%                                                                             %
1862f8f39d49973e8d7305a84f53f5ad2f569d7cb020cristy%                                                                             %
1863d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%   G e t I m a g e R a n g e                                                 %
18643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1869d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  GetImageRange() returns the range of one or more image channels.
18703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1871d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  The format of the GetImageRange method is:
18723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1873d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%      MagickBooleanType GetImageRange(const Image *image,double *minima,
1874d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%        double *maxima,ExceptionInfo *exception)
18753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
18773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
18793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o minima: the minimum value in the channel.
18813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o maxima: the maximum value in the channel.
18833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
18853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1887d42d995b9cb2a16e13221e665554417a5b7ec7fbcristyMagickExport MagickBooleanType GetImageRange(const Image *image,double *minima,
1888d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy  double *maxima,ExceptionInfo *exception)
18893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
18904a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy  CacheView
18914a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy    *image_view;
18924a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy
18934a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy  MagickBooleanType
18942729a440ea51d1e8ad8a4b9dcc4946bc7168ff1ecristy    initialize,
18954a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy    status;
18963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18979d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
18989d314ff2c17a77996c05413c2013880387e50f0ecristy    y;
18999d314ff2c17a77996c05413c2013880387e50f0ecristy
19003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
1901e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
19023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
19033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
19044a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy  status=MagickTrue;
19052729a440ea51d1e8ad8a4b9dcc4946bc7168ff1ecristy  initialize=MagickTrue;
19062729a440ea51d1e8ad8a4b9dcc4946bc7168ff1ecristy  *maxima=0.0;
19072729a440ea51d1e8ad8a4b9dcc4946bc7168ff1ecristy  *minima=0.0;
190846ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireVirtualCacheView(image,exception);
19094a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
19109a5a52fdbea9190e1c868ba9298a6f64d1c896d1cristy  #pragma omp parallel for schedule(static,4) shared(status,initialize) \
19115e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(image,image,image->rows,1)
19124a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy#endif
1913bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
19143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
191504f8f595a51a10b105729d196ac3ca06a5b9102cdirk    double
1916c44a78234bb6cae67df1c068e45bc4ce4565c0f2Cristy      row_maxima = 0.0,
1917c44a78234bb6cae67df1c068e45bc4ce4565c0f2Cristy      row_minima = 0.0;
191804f8f595a51a10b105729d196ac3ca06a5b9102cdirk
191904f8f595a51a10b105729d196ac3ca06a5b9102cdirk    MagickBooleanType
192004f8f595a51a10b105729d196ac3ca06a5b9102cdirk      row_initialize;
192104f8f595a51a10b105729d196ac3ca06a5b9102cdirk
19224c08aed51c5899665ade97263692328eea4af106cristy    register const Quantum
192305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
19243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1925bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    register ssize_t
19263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      x;
19273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19284a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy    if (status == MagickFalse)
19294a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy      continue;
19304a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
19314c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
19324a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy      {
19334a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy        status=MagickFalse;
19344a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy        continue;
19354a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy      }
193604f8f595a51a10b105729d196ac3ca06a5b9102cdirk    row_initialize=MagickTrue;
1937bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
19383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
19394a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy      register ssize_t
19404a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy        i;
19414a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy
1942883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,p) == 0)
194310a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        {
194410a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          p+=GetPixelChannels(image);
194510a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          continue;
194610a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        }
19474a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
19484a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy      {
19495a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
19505a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
19514a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy        if (traits == UndefinedPixelTrait)
19524a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy          continue;
19534a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy        if ((traits & UpdatePixelTrait) == 0)
19544a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy          continue;
195504f8f595a51a10b105729d196ac3ca06a5b9102cdirk        if (row_initialize != MagickFalse)
195604f8f595a51a10b105729d196ac3ca06a5b9102cdirk          {
195704f8f595a51a10b105729d196ac3ca06a5b9102cdirk            row_minima=(double) p[i];
195804f8f595a51a10b105729d196ac3ca06a5b9102cdirk            row_maxima=(double) p[i];
195904f8f595a51a10b105729d196ac3ca06a5b9102cdirk            row_initialize=MagickFalse;
196004f8f595a51a10b105729d196ac3ca06a5b9102cdirk          }
196104f8f595a51a10b105729d196ac3ca06a5b9102cdirk        else
196204f8f595a51a10b105729d196ac3ca06a5b9102cdirk          {
196304f8f595a51a10b105729d196ac3ca06a5b9102cdirk            if ((double) p[i] < row_minima)
196404f8f595a51a10b105729d196ac3ca06a5b9102cdirk              row_minima=(double) p[i];
196504f8f595a51a10b105729d196ac3ca06a5b9102cdirk            if ((double) p[i] > row_maxima)
196604f8f595a51a10b105729d196ac3ca06a5b9102cdirk              row_maxima=(double) p[i];
196704f8f595a51a10b105729d196ac3ca06a5b9102cdirk         }
196804f8f595a51a10b105729d196ac3ca06a5b9102cdirk      }
196904f8f595a51a10b105729d196ac3ca06a5b9102cdirk      p+=GetPixelChannels(image);
197004f8f595a51a10b105729d196ac3ca06a5b9102cdirk    }
19714a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
197204f8f595a51a10b105729d196ac3ca06a5b9102cdirk#pragma omp critical (MagickCore_GetImageRange)
19734a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy#endif
197404f8f595a51a10b105729d196ac3ca06a5b9102cdirk    {
197504f8f595a51a10b105729d196ac3ca06a5b9102cdirk      if (initialize != MagickFalse)
19763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
197704f8f595a51a10b105729d196ac3ca06a5b9102cdirk          *minima=row_minima;
197804f8f595a51a10b105729d196ac3ca06a5b9102cdirk          *maxima=row_maxima;
197904f8f595a51a10b105729d196ac3ca06a5b9102cdirk          initialize=MagickFalse;
198004f8f595a51a10b105729d196ac3ca06a5b9102cdirk        }
198104f8f595a51a10b105729d196ac3ca06a5b9102cdirk      else
198204f8f595a51a10b105729d196ac3ca06a5b9102cdirk        {
198304f8f595a51a10b105729d196ac3ca06a5b9102cdirk          if (row_minima < *minima)
198404f8f595a51a10b105729d196ac3ca06a5b9102cdirk            *minima=row_minima;
198504f8f595a51a10b105729d196ac3ca06a5b9102cdirk          if (row_maxima > *maxima)
198604f8f595a51a10b105729d196ac3ca06a5b9102cdirk            *maxima=row_maxima;
19873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
19893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
19904a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy  image_view=DestroyCacheView(image_view);
19914a9be6876d64847303b0a02f831a48d6a7fa3c5ccristy  return(status);
19923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
19933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
19943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
19953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
19963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
19973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
19983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1999d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%   G e t I m a g e S t a t i s t i c s                                       %
20003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
20013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
20023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
20033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
20043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
20055048d30ffd6670a4b4c9986bbcb46b228afdd884cristy%  GetImageStatistics() returns statistics for each channel in the image.  The
20065048d30ffd6670a4b4c9986bbcb46b228afdd884cristy%  statistics include the channel depth, its minima, maxima, mean, standard
20075048d30ffd6670a4b4c9986bbcb46b228afdd884cristy%  deviation, kurtosis and skewness.  You can access the red channel mean, for
20085048d30ffd6670a4b4c9986bbcb46b228afdd884cristy%  example, like this:
20093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2010d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%      channel_statistics=GetImageStatistics(image,exception);
201149dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy%      red_mean=channel_statistics[RedPixelChannel].mean;
20123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
20133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Use MagickRelinquishMemory() to free the statistics buffer.
20143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2015d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%  The format of the GetImageStatistics method is:
20163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2017d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy%      ChannelStatistics *GetImageStatistics(const Image *image,
20183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        ExceptionInfo *exception)
20193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
20203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
20213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
20223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
20233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
20243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
20253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
20263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2027d42d995b9cb2a16e13221e665554417a5b7ec7fbcristyMagickExport ChannelStatistics *GetImageStatistics(const Image *image,
20283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ExceptionInfo *exception)
20293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
20303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ChannelStatistics
20313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *channel_statistics;
20323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
203381c3360b2dfd109013aa2116eeb3a3caa29dd362cristy  double
203481c3360b2dfd109013aa2116eeb3a3caa29dd362cristy    *histogram;
203581c3360b2dfd109013aa2116eeb3a3caa29dd362cristy
20363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickStatusType
20373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
20383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  QuantumAny
20403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    range;
20413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2042bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
20433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
20443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
20469d314ff2c17a77996c05413c2013880387e50f0ecristy    channels,
204749dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy    depth;
20483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20499d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
20509d314ff2c17a77996c05413c2013880387e50f0ecristy    y;
20513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
2053e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
20543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
20553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2056d0f9c810bc403c9ffa931c001e57664670be931fcristy  histogram=(double *) AcquireQuantumMemory(MaxMap+1UL,MaxPixelChannels*
205781c3360b2dfd109013aa2116eeb3a3caa29dd362cristy    sizeof(*histogram));
205849dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy  channel_statistics=(ChannelStatistics *) AcquireQuantumMemory(
205949dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy    MaxPixelChannels+1,sizeof(*channel_statistics));
206081c3360b2dfd109013aa2116eeb3a3caa29dd362cristy  if ((channel_statistics == (ChannelStatistics *) NULL) ||
206181c3360b2dfd109013aa2116eeb3a3caa29dd362cristy      (histogram == (double *) NULL))
206281c3360b2dfd109013aa2116eeb3a3caa29dd362cristy    {
206381c3360b2dfd109013aa2116eeb3a3caa29dd362cristy      if (histogram != (double *) NULL)
206481c3360b2dfd109013aa2116eeb3a3caa29dd362cristy        histogram=(double *) RelinquishMagickMemory(histogram);
206581c3360b2dfd109013aa2116eeb3a3caa29dd362cristy      if (channel_statistics != (ChannelStatistics *) NULL)
206681c3360b2dfd109013aa2116eeb3a3caa29dd362cristy        channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
206781c3360b2dfd109013aa2116eeb3a3caa29dd362cristy          channel_statistics);
206881c3360b2dfd109013aa2116eeb3a3caa29dd362cristy      return(channel_statistics);
206981c3360b2dfd109013aa2116eeb3a3caa29dd362cristy    }
207049dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy  (void) ResetMagickMemory(channel_statistics,0,(MaxPixelChannels+1)*
20713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    sizeof(*channel_statistics));
207225a5f2fa49cd7276c378ee37cb0afb5e2182a433cristy  for (i=0; i <= (ssize_t) MaxPixelChannels; i++)
20733e37d9e8095bc3876bd4ff214d8ac33513ddb12bcristy  {
20743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    channel_statistics[i].depth=1;
2075fe181a767c3b3e61b9133829c504e75e34916de8cristy    channel_statistics[i].maxima=(-MagickMaximumValue);
2076fe181a767c3b3e61b9133829c504e75e34916de8cristy    channel_statistics[i].minima=MagickMaximumValue;
20773e37d9e8095bc3876bd4ff214d8ac33513ddb12bcristy  }
2078d0f9c810bc403c9ffa931c001e57664670be931fcristy  (void) ResetMagickMemory(histogram,0,(MaxMap+1)*MaxPixelChannels*
207981c3360b2dfd109013aa2116eeb3a3caa29dd362cristy    sizeof(*histogram));
2080bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
20813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
20824c08aed51c5899665ade97263692328eea4af106cristy    register const Quantum
208305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
20843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2085bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    register ssize_t
20863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      x;
20873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
20894c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
20903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
209149dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy    for (x=0; x < (ssize_t) image->columns; x++)
20923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
209349dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      register ssize_t
209449dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy        i;
209549dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy
2096883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,p) == 0)
209710a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        {
209810a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          p+=GetPixelChannels(image);
209910a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy          continue;
210010a6c61544fb48d72f29ec8f9573bdcd52abf1b7cristy        }
210149dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
210249dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      {
21035a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
21045a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
210549dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy        if (traits == UndefinedPixelTrait)
210649dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy          continue;
21073cad9cd91c3f7cb8b1d7379c0931623220bab523cristy        if (channel_statistics[channel].depth != MAGICKCORE_QUANTUM_DEPTH)
210849dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy          {
21093cad9cd91c3f7cb8b1d7379c0931623220bab523cristy            depth=channel_statistics[channel].depth;
211049dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy            range=GetQuantumRange(depth);
211149dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy            status=p[i] != ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),
211249dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy              range) ? MagickTrue : MagickFalse;
211349dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy            if (status != MagickFalse)
211449dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy              {
2115cd8ce3e1bebfd93cbfee86e2e489907000945053cristy                channel_statistics[channel].depth++;
21166f7d3a9b4da141841c306f024b4944f5d8b8431fcristy                i--;
211749dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy                continue;
211849dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy              }
21193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
21203e37d9e8095bc3876bd4ff214d8ac33513ddb12bcristy        if ((double) p[i] < channel_statistics[channel].minima)
21213e37d9e8095bc3876bd4ff214d8ac33513ddb12bcristy          channel_statistics[channel].minima=(double) p[i];
21223e37d9e8095bc3876bd4ff214d8ac33513ddb12bcristy        if ((double) p[i] > channel_statistics[channel].maxima)
21233e37d9e8095bc3876bd4ff214d8ac33513ddb12bcristy          channel_statistics[channel].maxima=(double) p[i];
2124cd8ce3e1bebfd93cbfee86e2e489907000945053cristy        channel_statistics[channel].sum+=p[i];
2125cd8ce3e1bebfd93cbfee86e2e489907000945053cristy        channel_statistics[channel].sum_squared+=(double) p[i]*p[i];
2126cd8ce3e1bebfd93cbfee86e2e489907000945053cristy        channel_statistics[channel].sum_cubed+=(double) p[i]*p[i]*p[i];
2127cd8ce3e1bebfd93cbfee86e2e489907000945053cristy        channel_statistics[channel].sum_fourth_power+=(double) p[i]*p[i]*p[i]*
2128cd8ce3e1bebfd93cbfee86e2e489907000945053cristy          p[i];
21295048d30ffd6670a4b4c9986bbcb46b228afdd884cristy        channel_statistics[channel].area++;
213081c3360b2dfd109013aa2116eeb3a3caa29dd362cristy        histogram[GetPixelChannels(image)*ScaleQuantumToMap(
213181c3360b2dfd109013aa2116eeb3a3caa29dd362cristy          ClampToQuantum((double) p[i]))+i]++;
213249dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy      }
2133ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
21343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
21353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
213625a5f2fa49cd7276c378ee37cb0afb5e2182a433cristy  for (i=0; i < (ssize_t) MaxPixelChannels; i++)
21373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2138a38fb2c21b8d9b37615b279b45d0547596796ddccristy    double
2139a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy      area,
2140a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy      number_bins;
2141a38fb2c21b8d9b37615b279b45d0547596796ddccristy
214281c3360b2dfd109013aa2116eeb3a3caa29dd362cristy    register ssize_t
214381c3360b2dfd109013aa2116eeb3a3caa29dd362cristy      j;
214481c3360b2dfd109013aa2116eeb3a3caa29dd362cristy
21453e3ec3afbb0782697f201cbe30a56794c10dc7efcristy    area=PerceptibleReciprocal(channel_statistics[i].area);
2146a38fb2c21b8d9b37615b279b45d0547596796ddccristy    channel_statistics[i].sum*=area;
2147a38fb2c21b8d9b37615b279b45d0547596796ddccristy    channel_statistics[i].sum_squared*=area;
2148a38fb2c21b8d9b37615b279b45d0547596796ddccristy    channel_statistics[i].sum_cubed*=area;
2149a38fb2c21b8d9b37615b279b45d0547596796ddccristy    channel_statistics[i].sum_fourth_power*=area;
2150fd9dcd4a312944c590a433c5d519146364fa6932cristy    channel_statistics[i].mean=channel_statistics[i].sum;
2151fd9dcd4a312944c590a433c5d519146364fa6932cristy    channel_statistics[i].variance=channel_statistics[i].sum_squared;
2152fd9dcd4a312944c590a433c5d519146364fa6932cristy    channel_statistics[i].standard_deviation=sqrt(
2153fd9dcd4a312944c590a433c5d519146364fa6932cristy      channel_statistics[i].variance-(channel_statistics[i].mean*
2154fd9dcd4a312944c590a433c5d519146364fa6932cristy      channel_statistics[i].mean));
2155a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy    number_bins=0.0;
2156a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy    for (j=0; j < (ssize_t) (MaxMap+1U); j++)
2157a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy      if (histogram[GetPixelChannels(image)*j+i] > 0.0)
2158a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy        number_bins++;
21597a61d4cc5307ed5b767f9b6115de23f542d998a3cristy    for (j=0; j < (ssize_t) (MaxMap+1U); j++)
21607a61d4cc5307ed5b767f9b6115de23f542d998a3cristy    {
21617a61d4cc5307ed5b767f9b6115de23f542d998a3cristy      double
21627a61d4cc5307ed5b767f9b6115de23f542d998a3cristy        count;
216381c3360b2dfd109013aa2116eeb3a3caa29dd362cristy
21647a61d4cc5307ed5b767f9b6115de23f542d998a3cristy      count=histogram[GetPixelChannels(image)*j+i]*area;
21657a61d4cc5307ed5b767f9b6115de23f542d998a3cristy      channel_statistics[i].entropy+=-count*MagickLog10(count)/
2166a42b4f3db63a5cf1f29a348d55dfd625baf59e30cristy        MagickLog10(number_bins);
21677a61d4cc5307ed5b767f9b6115de23f542d998a3cristy    }
21683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
216925a5f2fa49cd7276c378ee37cb0afb5e2182a433cristy  for (i=0; i < (ssize_t) MaxPixelChannels; i++)
21703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
217140a5c455ade0046871a4e93e41585465ff6c575acristy    PixelTrait traits=GetPixelChannelTraits(image,(PixelChannel) i);
2172a5bc74d9d068e19282bdafd0c6c39264af465fcdcristy    if ((traits & UpdatePixelTrait) == 0)
2173a5bc74d9d068e19282bdafd0c6c39264af465fcdcristy      continue;
2174a933607bd9aba71608aa30d9145e54323975b8f0cristy    channel_statistics[CompositePixelChannel].area+=channel_statistics[i].area;
2175a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy    channel_statistics[CompositePixelChannel].minima=MagickMin(
21765f95f4f77efc46ff53593d750491c8f60698c983cristy      channel_statistics[CompositePixelChannel].minima,
217732daba40c8ba87808abfe7d4bfec678d073cd63fcristy      channel_statistics[i].minima);
2178a50f0c85d273f79dee2726d0ad8481423f4bc5f8cristy    channel_statistics[CompositePixelChannel].maxima=EvaluateMax(
21795f95f4f77efc46ff53593d750491c8f60698c983cristy      channel_statistics[CompositePixelChannel].maxima,
218032daba40c8ba87808abfe7d4bfec678d073cd63fcristy      channel_statistics[i].maxima);
21815f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].sum+=channel_statistics[i].sum;
21825f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].sum_squared+=
2183fd9dcd4a312944c590a433c5d519146364fa6932cristy      channel_statistics[i].sum_squared;
21845f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].sum_cubed+=
218532daba40c8ba87808abfe7d4bfec678d073cd63fcristy      channel_statistics[i].sum_cubed;
21865f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].sum_fourth_power+=
2187a8178ed437f3602d0290c41ebeccb51bb9ecccd7cristy      channel_statistics[i].sum_fourth_power;
21885f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].mean+=channel_statistics[i].mean;
21895f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].variance+=
219032daba40c8ba87808abfe7d4bfec678d073cd63fcristy      channel_statistics[i].variance-channel_statistics[i].mean*
219132daba40c8ba87808abfe7d4bfec678d073cd63fcristy      channel_statistics[i].mean;
21925f95f4f77efc46ff53593d750491c8f60698c983cristy    channel_statistics[CompositePixelChannel].standard_deviation+=
2193fd9dcd4a312944c590a433c5d519146364fa6932cristy      channel_statistics[i].variance-channel_statistics[i].mean*
2194fd9dcd4a312944c590a433c5d519146364fa6932cristy      channel_statistics[i].mean;
21957a61d4cc5307ed5b767f9b6115de23f542d998a3cristy    if (channel_statistics[i].entropy > MagickEpsilon)
21967a61d4cc5307ed5b767f9b6115de23f542d998a3cristy      channel_statistics[CompositePixelChannel].entropy+=
21977a61d4cc5307ed5b767f9b6115de23f542d998a3cristy        channel_statistics[i].entropy;
21983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
219949dd6a0c1bab5e1e6f99369c0f70a5e0184810d4cristy  channels=GetImageChannels(image);
2200a933607bd9aba71608aa30d9145e54323975b8f0cristy  channel_statistics[CompositePixelChannel].area/=channels;
22015f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].sum/=channels;
22025f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].sum_squared/=channels;
22035f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].sum_cubed/=channels;
22045f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].sum_fourth_power/=channels;
22055f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].mean/=channels;
22065f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].variance/=channels;
22075f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].standard_deviation=
22085f95f4f77efc46ff53593d750491c8f60698c983cristy    sqrt(channel_statistics[CompositePixelChannel].standard_deviation/channels);
22095f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].kurtosis/=channels;
22105f95f4f77efc46ff53593d750491c8f60698c983cristy  channel_statistics[CompositePixelChannel].skewness/=channels;
221181c3360b2dfd109013aa2116eeb3a3caa29dd362cristy  channel_statistics[CompositePixelChannel].entropy/=channels;
221225a5f2fa49cd7276c378ee37cb0afb5e2182a433cristy  for (i=0; i <= (ssize_t) MaxPixelChannels; i++)
22133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2214a38fb2c21b8d9b37615b279b45d0547596796ddccristy    double
2215a38fb2c21b8d9b37615b279b45d0547596796ddccristy      standard_deviation;
2216a38fb2c21b8d9b37615b279b45d0547596796ddccristy
22176d94a308cc4b42b09f5020acce05d779e24faa47cristy    if (channel_statistics[i].standard_deviation == 0.0)
22186d94a308cc4b42b09f5020acce05d779e24faa47cristy      continue;
22193e3ec3afbb0782697f201cbe30a56794c10dc7efcristy    standard_deviation=PerceptibleReciprocal(
2220a38fb2c21b8d9b37615b279b45d0547596796ddccristy      channel_statistics[i].standard_deviation);
2221e2a912b6c9086c98ec838baa0824cd8deca55538cristy    channel_statistics[i].skewness=(channel_statistics[i].sum_cubed-3.0*
2222e2a912b6c9086c98ec838baa0824cd8deca55538cristy      channel_statistics[i].mean*channel_statistics[i].sum_squared+2.0*
2223e2a912b6c9086c98ec838baa0824cd8deca55538cristy      channel_statistics[i].mean*channel_statistics[i].mean*
2224a38fb2c21b8d9b37615b279b45d0547596796ddccristy      channel_statistics[i].mean)*(standard_deviation*standard_deviation*
2225a38fb2c21b8d9b37615b279b45d0547596796ddccristy      standard_deviation);
2226e2a912b6c9086c98ec838baa0824cd8deca55538cristy    channel_statistics[i].kurtosis=(channel_statistics[i].sum_fourth_power-4.0*
2227e2a912b6c9086c98ec838baa0824cd8deca55538cristy      channel_statistics[i].mean*channel_statistics[i].sum_cubed+6.0*
2228e2a912b6c9086c98ec838baa0824cd8deca55538cristy      channel_statistics[i].mean*channel_statistics[i].mean*
2229a8178ed437f3602d0290c41ebeccb51bb9ecccd7cristy      channel_statistics[i].sum_squared-3.0*channel_statistics[i].mean*
2230a8178ed437f3602d0290c41ebeccb51bb9ecccd7cristy      channel_statistics[i].mean*1.0*channel_statistics[i].mean*
2231a38fb2c21b8d9b37615b279b45d0547596796ddccristy      channel_statistics[i].mean)*(standard_deviation*standard_deviation*
2232a38fb2c21b8d9b37615b279b45d0547596796ddccristy      standard_deviation*standard_deviation)-3.0;
22333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
223481c3360b2dfd109013aa2116eeb3a3caa29dd362cristy  histogram=(double *) RelinquishMagickMemory(histogram);
2235e287bbaee17bb627af090e3127082e5a316337e5cristy  if (y < (ssize_t) image->rows)
2236e287bbaee17bb627af090e3127082e5a316337e5cristy    channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
2237e287bbaee17bb627af090e3127082e5a316337e5cristy      channel_statistics);
22383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(channel_statistics);
22393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
224099bd523143cfe6d0407e260adf99d7384c30532dcristy
224199bd523143cfe6d0407e260adf99d7384c30532dcristy/*
224299bd523143cfe6d0407e260adf99d7384c30532dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224399bd523143cfe6d0407e260adf99d7384c30532dcristy%                                                                             %
224499bd523143cfe6d0407e260adf99d7384c30532dcristy%                                                                             %
2245f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%                                                                             %
2246f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%     P o l y n o m i a l I m a g e                                           %
2247f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%                                                                             %
2248f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%                                                                             %
2249f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%                                                                             %
2250f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2251f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2252f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%  PolynomialImage() returns a new image where each pixel is the sum of the
2253f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%  pixels in the image sequence after applying its corresponding terms
2254dbc2da927c5fcf9d3518af20203fa5bc32e572a0cristy%  (coefficient and degree pairs).
2255f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2256f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%  The format of the PolynomialImage method is:
2257f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
225841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy%      Image *PolynomialImage(const Image *images,const size_t number_terms,
2259f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%        const double *terms,ExceptionInfo *exception)
2260f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2261f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%  A description of each parameter follows:
2262f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
226341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy%    o images: the image sequence.
2264f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2265f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%    o number_terms: the number of terms in the list.  The actual list length
2266f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%      is 2 x number_terms + 1 (the constant).
2267f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2268f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%    o terms: the list of polynomial coefficients and degree pairs and a
2269f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%      constant.
2270f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2271f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%    o exception: return any errors or warnings in this structure.
2272f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%
2273f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy*/
2274f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy
227541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristyMagickExport Image *PolynomialImage(const Image *images,
2276f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy  const size_t number_terms,const double *terms,ExceptionInfo *exception)
2277f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy{
227841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy#define PolynomialImageTag  "Polynomial/Image"
227941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
228041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  CacheView
228141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    *polynomial_view;
228241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
2283f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy  Image
228441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    *image;
2285f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy
2286f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy  MagickBooleanType
2287f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy    status;
2288f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy
228941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  MagickOffsetType
229041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    progress;
229141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
229241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  PixelChannels
229305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk    **magick_restrict polynomial_pixels;
229441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
229541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  size_t
229641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    number_images;
229741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
229841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  ssize_t
229941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    y;
230041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
230141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  assert(images != (Image *) NULL);
2302e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(images->signature == MagickCoreSignature);
230341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  if (images->debug != MagickFalse)
230441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
2305f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy  assert(exception != (ExceptionInfo *) NULL);
2306e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
230741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  image=CloneImage(images,images->columns,images->rows,MagickTrue,
2308f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy    exception);
230941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  if (image == (Image *) NULL)
2310f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy    return((Image *) NULL);
231141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2312f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy    {
231341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      image=DestroyImage(image);
2314f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy      return((Image *) NULL);
2315f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy    }
231641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  number_images=GetImageListLength(images);
2317751a6671c9b7480f3672a7ef6aa6e392f064b46ddirk  polynomial_pixels=AcquirePixelThreadSet(images);
231841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  if (polynomial_pixels == (PixelChannels **) NULL)
231941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    {
232041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      image=DestroyImage(image);
232141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      (void) ThrowMagickException(exception,GetMagickModule(),
2322efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy        ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
232341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      return((Image *) NULL);
232441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    }
232541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  /*
232641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    Polynomial image pixels.
232741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  */
232841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  status=MagickTrue;
232941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  progress=0;
233046ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  polynomial_view=AcquireAuthenticCacheView(image,exception);
233141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
233241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
23335e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(image,image,image->rows,1)
233441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy#endif
233541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  for (y=0; y < (ssize_t) image->rows; y++)
233641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  {
233741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    CacheView
233841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      *image_view;
233941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
234041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    const Image
234141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      *next;
234241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
234341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    const int
234441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      id = GetOpenMPThreadId();
234541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
234641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    register ssize_t
234741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      i,
234841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      x;
234941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
235041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    register PixelChannels
235141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      *polynomial_pixel;
235241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
235341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    register Quantum
235405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
235541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
235641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    ssize_t
235741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      j;
235841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
235941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    if (status == MagickFalse)
236041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      continue;
2361edb3f510ac6109703f134e42f9a2a0cc21866d78cristy    q=QueueCacheViewAuthenticPixels(polynomial_view,0,y,image->columns,1,
2362edb3f510ac6109703f134e42f9a2a0cc21866d78cristy      exception);
236341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    if (q == (Quantum *) NULL)
236441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      {
236541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        status=MagickFalse;
236641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        continue;
236741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      }
236841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    polynomial_pixel=polynomial_pixels[id];
236941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    for (j=0; j < (ssize_t) image->columns; j++)
237041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      for (i=0; i < MaxPixelChannels; i++)
237141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        polynomial_pixel[j].channel[i]=0.0;
237241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    next=images;
237341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    for (j=0; j < (ssize_t) number_images; j++)
237441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    {
237541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      register const Quantum
237641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        *p;
237741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
237802016cff038d0ddb255d4c84bf31a78f5c8714f0cristy      if (j >= (ssize_t) number_terms)
237902016cff038d0ddb255d4c84bf31a78f5c8714f0cristy        continue;
238046ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy      image_view=AcquireVirtualCacheView(next,exception);
2381edb3f510ac6109703f134e42f9a2a0cc21866d78cristy      p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
238241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      if (p == (const Quantum *) NULL)
238341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        {
238441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          image_view=DestroyCacheView(image_view);
238541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          break;
238641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        }
2387edb3f510ac6109703f134e42f9a2a0cc21866d78cristy      for (x=0; x < (ssize_t) image->columns; x++)
238841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      {
238941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        register ssize_t
239041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          i;
239141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
2392883fde11debec15cedb05dc5d7228d8588066bc0cristy        if (GetPixelReadMask(next,p) == 0)
239341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          {
239441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy            p+=GetPixelChannels(next);
239541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy            continue;
239641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          }
239741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        for (i=0; i < (ssize_t) GetPixelChannels(next); i++)
239841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        {
239941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          MagickRealType
240041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy            coefficient,
240141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy            degree;
240241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
24035a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          PixelChannel channel=GetPixelChannelChannel(image,i);
24045a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          PixelTrait traits=GetPixelChannelTraits(next,channel);
24055a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          PixelTrait polynomial_traits=GetPixelChannelTraits(image,channel);
240641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          if ((traits == UndefinedPixelTrait) ||
240741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy              (polynomial_traits == UndefinedPixelTrait))
240841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy            continue;
240941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          if ((traits & UpdatePixelTrait) == 0)
241041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy            continue;
24114a2059693f03167d5ee07470a38c2bdaa4e3688acristy          coefficient=(MagickRealType) terms[2*j];
24124a2059693f03167d5ee07470a38c2bdaa4e3688acristy          degree=(MagickRealType) terms[(j << 1)+1];
241341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          polynomial_pixel[x].channel[i]+=coefficient*
2414cef3b9988777b669bc008f2ce876c1bacf22e333cristy            pow(QuantumScale*GetPixelChannel(image,channel,p),degree);
241541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        }
241641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        p+=GetPixelChannels(next);
241741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      }
241841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      image_view=DestroyCacheView(image_view);
241941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      next=GetNextImageInList(next);
242041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    }
242141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    for (x=0; x < (ssize_t) image->columns; x++)
242241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    {
242341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      register ssize_t
242441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        i;
242541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
2426883fde11debec15cedb05dc5d7228d8588066bc0cristy      if (GetPixelReadMask(image,q) == 0)
242741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        {
242841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          q+=GetPixelChannels(image);
242941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          continue;
243041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        }
243141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
243241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      {
24335a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
24345a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
243541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        if (traits == UndefinedPixelTrait)
243641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          continue;
243741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        if ((traits & UpdatePixelTrait) == 0)
243841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          continue;
2439cef3b9988777b669bc008f2ce876c1bacf22e333cristy        q[i]=ClampToQuantum(QuantumRange*polynomial_pixel[x].channel[i]);
244041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      }
244141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      q+=GetPixelChannels(image);
244241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    }
244341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    if (SyncCacheViewAuthenticPixels(polynomial_view,exception) == MagickFalse)
244441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      status=MagickFalse;
244541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    if (images->progress_monitor != (MagickProgressMonitor) NULL)
244641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      {
244741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        MagickBooleanType
244841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          proceed;
244941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy
245041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
245141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        #pragma omp critical (MagickCore_PolynomialImages)
245241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy#endif
245341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        proceed=SetImageProgress(images,PolynomialImageTag,progress++,
245441f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          image->rows);
245541f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy        if (proceed == MagickFalse)
245641f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy          status=MagickFalse;
245741f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy      }
245841f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  }
245941f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  polynomial_view=DestroyCacheView(polynomial_view);
246041f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  polynomial_pixels=DestroyPixelThreadSet(polynomial_pixels);
246141f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  if (status == MagickFalse)
246241f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy    image=DestroyImage(image);
246341f5fe9f39b5f0d7d8be74eaed6e5358888c6f1bcristy  return(image);
2464f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy}
2465f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy
2466f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy/*
2467f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2468f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%                                                                             %
2469f56e6ad6da167beca48fb23194201c25cd3dfb8ecristy%                                                                             %
247099bd523143cfe6d0407e260adf99d7384c30532dcristy%                                                                             %
247199bd523143cfe6d0407e260adf99d7384c30532dcristy%     S t a t i s t i c I m a g e                                             %
247299bd523143cfe6d0407e260adf99d7384c30532dcristy%                                                                             %
247399bd523143cfe6d0407e260adf99d7384c30532dcristy%                                                                             %
247499bd523143cfe6d0407e260adf99d7384c30532dcristy%                                                                             %
247599bd523143cfe6d0407e260adf99d7384c30532dcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247699bd523143cfe6d0407e260adf99d7384c30532dcristy%
247799bd523143cfe6d0407e260adf99d7384c30532dcristy%  StatisticImage() makes each pixel the min / max / median / mode / etc. of
247899bd523143cfe6d0407e260adf99d7384c30532dcristy%  the neighborhood of the specified width and height.
247999bd523143cfe6d0407e260adf99d7384c30532dcristy%
248099bd523143cfe6d0407e260adf99d7384c30532dcristy%  The format of the StatisticImage method is:
248199bd523143cfe6d0407e260adf99d7384c30532dcristy%
248299bd523143cfe6d0407e260adf99d7384c30532dcristy%      Image *StatisticImage(const Image *image,const StatisticType type,
248399bd523143cfe6d0407e260adf99d7384c30532dcristy%        const size_t width,const size_t height,ExceptionInfo *exception)
248499bd523143cfe6d0407e260adf99d7384c30532dcristy%
248599bd523143cfe6d0407e260adf99d7384c30532dcristy%  A description of each parameter follows:
248699bd523143cfe6d0407e260adf99d7384c30532dcristy%
248799bd523143cfe6d0407e260adf99d7384c30532dcristy%    o image: the image.
248899bd523143cfe6d0407e260adf99d7384c30532dcristy%
248999bd523143cfe6d0407e260adf99d7384c30532dcristy%    o type: the statistic type (median, mode, etc.).
249099bd523143cfe6d0407e260adf99d7384c30532dcristy%
249199bd523143cfe6d0407e260adf99d7384c30532dcristy%    o width: the width of the pixel neighborhood.
249299bd523143cfe6d0407e260adf99d7384c30532dcristy%
249399bd523143cfe6d0407e260adf99d7384c30532dcristy%    o height: the height of the pixel neighborhood.
249499bd523143cfe6d0407e260adf99d7384c30532dcristy%
249599bd523143cfe6d0407e260adf99d7384c30532dcristy%    o exception: return any errors or warnings in this structure.
249699bd523143cfe6d0407e260adf99d7384c30532dcristy%
249799bd523143cfe6d0407e260adf99d7384c30532dcristy*/
249899bd523143cfe6d0407e260adf99d7384c30532dcristy
249999bd523143cfe6d0407e260adf99d7384c30532dcristytypedef struct _SkipNode
250099bd523143cfe6d0407e260adf99d7384c30532dcristy{
250199bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
250299bd523143cfe6d0407e260adf99d7384c30532dcristy    next[9],
250399bd523143cfe6d0407e260adf99d7384c30532dcristy    count,
250499bd523143cfe6d0407e260adf99d7384c30532dcristy    signature;
250599bd523143cfe6d0407e260adf99d7384c30532dcristy} SkipNode;
250699bd523143cfe6d0407e260adf99d7384c30532dcristy
250799bd523143cfe6d0407e260adf99d7384c30532dcristytypedef struct _SkipList
250899bd523143cfe6d0407e260adf99d7384c30532dcristy{
250999bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
251099bd523143cfe6d0407e260adf99d7384c30532dcristy    level;
251199bd523143cfe6d0407e260adf99d7384c30532dcristy
251299bd523143cfe6d0407e260adf99d7384c30532dcristy  SkipNode
251399bd523143cfe6d0407e260adf99d7384c30532dcristy    *nodes;
251499bd523143cfe6d0407e260adf99d7384c30532dcristy} SkipList;
251599bd523143cfe6d0407e260adf99d7384c30532dcristy
251699bd523143cfe6d0407e260adf99d7384c30532dcristytypedef struct _PixelList
251799bd523143cfe6d0407e260adf99d7384c30532dcristy{
251899bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
251999bd523143cfe6d0407e260adf99d7384c30532dcristy    length,
252099bd523143cfe6d0407e260adf99d7384c30532dcristy    seed;
252199bd523143cfe6d0407e260adf99d7384c30532dcristy
252299bd523143cfe6d0407e260adf99d7384c30532dcristy  SkipList
252399bd523143cfe6d0407e260adf99d7384c30532dcristy    skip_list;
252499bd523143cfe6d0407e260adf99d7384c30532dcristy
252599bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
252699bd523143cfe6d0407e260adf99d7384c30532dcristy    signature;
252799bd523143cfe6d0407e260adf99d7384c30532dcristy} PixelList;
252899bd523143cfe6d0407e260adf99d7384c30532dcristy
252999bd523143cfe6d0407e260adf99d7384c30532dcristystatic PixelList *DestroyPixelList(PixelList *pixel_list)
253099bd523143cfe6d0407e260adf99d7384c30532dcristy{
253199bd523143cfe6d0407e260adf99d7384c30532dcristy  if (pixel_list == (PixelList *) NULL)
253299bd523143cfe6d0407e260adf99d7384c30532dcristy    return((PixelList *) NULL);
253399bd523143cfe6d0407e260adf99d7384c30532dcristy  if (pixel_list->skip_list.nodes != (SkipNode *) NULL)
253499bd523143cfe6d0407e260adf99d7384c30532dcristy    pixel_list->skip_list.nodes=(SkipNode *) RelinquishMagickMemory(
253599bd523143cfe6d0407e260adf99d7384c30532dcristy      pixel_list->skip_list.nodes);
253699bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list=(PixelList *) RelinquishMagickMemory(pixel_list);
253799bd523143cfe6d0407e260adf99d7384c30532dcristy  return(pixel_list);
253899bd523143cfe6d0407e260adf99d7384c30532dcristy}
253999bd523143cfe6d0407e260adf99d7384c30532dcristy
254099bd523143cfe6d0407e260adf99d7384c30532dcristystatic PixelList **DestroyPixelListThreadSet(PixelList **pixel_list)
254199bd523143cfe6d0407e260adf99d7384c30532dcristy{
254299bd523143cfe6d0407e260adf99d7384c30532dcristy  register ssize_t
254399bd523143cfe6d0407e260adf99d7384c30532dcristy    i;
254499bd523143cfe6d0407e260adf99d7384c30532dcristy
254599bd523143cfe6d0407e260adf99d7384c30532dcristy  assert(pixel_list != (PixelList **) NULL);
2546ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
254799bd523143cfe6d0407e260adf99d7384c30532dcristy    if (pixel_list[i] != (PixelList *) NULL)
254899bd523143cfe6d0407e260adf99d7384c30532dcristy      pixel_list[i]=DestroyPixelList(pixel_list[i]);
254999bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list=(PixelList **) RelinquishMagickMemory(pixel_list);
255099bd523143cfe6d0407e260adf99d7384c30532dcristy  return(pixel_list);
255199bd523143cfe6d0407e260adf99d7384c30532dcristy}
255299bd523143cfe6d0407e260adf99d7384c30532dcristy
255399bd523143cfe6d0407e260adf99d7384c30532dcristystatic PixelList *AcquirePixelList(const size_t width,const size_t height)
255499bd523143cfe6d0407e260adf99d7384c30532dcristy{
255599bd523143cfe6d0407e260adf99d7384c30532dcristy  PixelList
255699bd523143cfe6d0407e260adf99d7384c30532dcristy    *pixel_list;
255799bd523143cfe6d0407e260adf99d7384c30532dcristy
255899bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list=(PixelList *) AcquireMagickMemory(sizeof(*pixel_list));
255999bd523143cfe6d0407e260adf99d7384c30532dcristy  if (pixel_list == (PixelList *) NULL)
256099bd523143cfe6d0407e260adf99d7384c30532dcristy    return(pixel_list);
256199bd523143cfe6d0407e260adf99d7384c30532dcristy  (void) ResetMagickMemory((void *) pixel_list,0,sizeof(*pixel_list));
256299bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list->length=width*height;
256399bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list->skip_list.nodes=(SkipNode *) AcquireQuantumMemory(65537UL,
256499bd523143cfe6d0407e260adf99d7384c30532dcristy    sizeof(*pixel_list->skip_list.nodes));
256599bd523143cfe6d0407e260adf99d7384c30532dcristy  if (pixel_list->skip_list.nodes == (SkipNode *) NULL)
256699bd523143cfe6d0407e260adf99d7384c30532dcristy    return(DestroyPixelList(pixel_list));
256799bd523143cfe6d0407e260adf99d7384c30532dcristy  (void) ResetMagickMemory(pixel_list->skip_list.nodes,0,65537UL*
256899bd523143cfe6d0407e260adf99d7384c30532dcristy    sizeof(*pixel_list->skip_list.nodes));
2569e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  pixel_list->signature=MagickCoreSignature;
257099bd523143cfe6d0407e260adf99d7384c30532dcristy  return(pixel_list);
257199bd523143cfe6d0407e260adf99d7384c30532dcristy}
257299bd523143cfe6d0407e260adf99d7384c30532dcristy
257399bd523143cfe6d0407e260adf99d7384c30532dcristystatic PixelList **AcquirePixelListThreadSet(const size_t width,
257499bd523143cfe6d0407e260adf99d7384c30532dcristy  const size_t height)
257599bd523143cfe6d0407e260adf99d7384c30532dcristy{
257699bd523143cfe6d0407e260adf99d7384c30532dcristy  PixelList
257799bd523143cfe6d0407e260adf99d7384c30532dcristy    **pixel_list;
257899bd523143cfe6d0407e260adf99d7384c30532dcristy
257999bd523143cfe6d0407e260adf99d7384c30532dcristy  register ssize_t
258099bd523143cfe6d0407e260adf99d7384c30532dcristy    i;
258199bd523143cfe6d0407e260adf99d7384c30532dcristy
258299bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
258399bd523143cfe6d0407e260adf99d7384c30532dcristy    number_threads;
258499bd523143cfe6d0407e260adf99d7384c30532dcristy
25859357bdd9a30c3d65ef8812e45220f7552dc4376bcristy  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
258699bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list=(PixelList **) AcquireQuantumMemory(number_threads,
258799bd523143cfe6d0407e260adf99d7384c30532dcristy    sizeof(*pixel_list));
258899bd523143cfe6d0407e260adf99d7384c30532dcristy  if (pixel_list == (PixelList **) NULL)
258999bd523143cfe6d0407e260adf99d7384c30532dcristy    return((PixelList **) NULL);
259099bd523143cfe6d0407e260adf99d7384c30532dcristy  (void) ResetMagickMemory(pixel_list,0,number_threads*sizeof(*pixel_list));
259199bd523143cfe6d0407e260adf99d7384c30532dcristy  for (i=0; i < (ssize_t) number_threads; i++)
259299bd523143cfe6d0407e260adf99d7384c30532dcristy  {
259399bd523143cfe6d0407e260adf99d7384c30532dcristy    pixel_list[i]=AcquirePixelList(width,height);
259499bd523143cfe6d0407e260adf99d7384c30532dcristy    if (pixel_list[i] == (PixelList *) NULL)
259599bd523143cfe6d0407e260adf99d7384c30532dcristy      return(DestroyPixelListThreadSet(pixel_list));
259699bd523143cfe6d0407e260adf99d7384c30532dcristy  }
259799bd523143cfe6d0407e260adf99d7384c30532dcristy  return(pixel_list);
259899bd523143cfe6d0407e260adf99d7384c30532dcristy}
259999bd523143cfe6d0407e260adf99d7384c30532dcristy
260099bd523143cfe6d0407e260adf99d7384c30532dcristystatic void AddNodePixelList(PixelList *pixel_list,const size_t color)
260199bd523143cfe6d0407e260adf99d7384c30532dcristy{
260299bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
260399bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
260499bd523143cfe6d0407e260adf99d7384c30532dcristy
260599bd523143cfe6d0407e260adf99d7384c30532dcristy  register ssize_t
260699bd523143cfe6d0407e260adf99d7384c30532dcristy    level;
260799bd523143cfe6d0407e260adf99d7384c30532dcristy
260899bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
260999bd523143cfe6d0407e260adf99d7384c30532dcristy    search,
261099bd523143cfe6d0407e260adf99d7384c30532dcristy    update[9];
261199bd523143cfe6d0407e260adf99d7384c30532dcristy
261299bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
261399bd523143cfe6d0407e260adf99d7384c30532dcristy    Initialize the node.
261499bd523143cfe6d0407e260adf99d7384c30532dcristy  */
261599bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
261699bd523143cfe6d0407e260adf99d7384c30532dcristy  p->nodes[color].signature=pixel_list->signature;
261799bd523143cfe6d0407e260adf99d7384c30532dcristy  p->nodes[color].count=1;
261899bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
261999bd523143cfe6d0407e260adf99d7384c30532dcristy    Determine where it belongs in the list.
262099bd523143cfe6d0407e260adf99d7384c30532dcristy  */
262199bd523143cfe6d0407e260adf99d7384c30532dcristy  search=65536UL;
262299bd523143cfe6d0407e260adf99d7384c30532dcristy  for (level=p->level; level >= 0; level--)
262399bd523143cfe6d0407e260adf99d7384c30532dcristy  {
262499bd523143cfe6d0407e260adf99d7384c30532dcristy    while (p->nodes[search].next[level] < color)
262599bd523143cfe6d0407e260adf99d7384c30532dcristy      search=p->nodes[search].next[level];
262699bd523143cfe6d0407e260adf99d7384c30532dcristy    update[level]=search;
262799bd523143cfe6d0407e260adf99d7384c30532dcristy  }
262899bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
262999bd523143cfe6d0407e260adf99d7384c30532dcristy    Generate a pseudo-random level for this node.
263099bd523143cfe6d0407e260adf99d7384c30532dcristy  */
263199bd523143cfe6d0407e260adf99d7384c30532dcristy  for (level=0; ; level++)
263299bd523143cfe6d0407e260adf99d7384c30532dcristy  {
263399bd523143cfe6d0407e260adf99d7384c30532dcristy    pixel_list->seed=(pixel_list->seed*42893621L)+1L;
263499bd523143cfe6d0407e260adf99d7384c30532dcristy    if ((pixel_list->seed & 0x300) != 0x300)
263599bd523143cfe6d0407e260adf99d7384c30532dcristy      break;
263699bd523143cfe6d0407e260adf99d7384c30532dcristy  }
263799bd523143cfe6d0407e260adf99d7384c30532dcristy  if (level > 8)
263899bd523143cfe6d0407e260adf99d7384c30532dcristy    level=8;
263999bd523143cfe6d0407e260adf99d7384c30532dcristy  if (level > (p->level+2))
264099bd523143cfe6d0407e260adf99d7384c30532dcristy    level=p->level+2;
264199bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
264299bd523143cfe6d0407e260adf99d7384c30532dcristy    If we're raising the list's level, link back to the root node.
264399bd523143cfe6d0407e260adf99d7384c30532dcristy  */
264499bd523143cfe6d0407e260adf99d7384c30532dcristy  while (level > p->level)
264599bd523143cfe6d0407e260adf99d7384c30532dcristy  {
264699bd523143cfe6d0407e260adf99d7384c30532dcristy    p->level++;
264799bd523143cfe6d0407e260adf99d7384c30532dcristy    update[p->level]=65536UL;
264899bd523143cfe6d0407e260adf99d7384c30532dcristy  }
264999bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
265099bd523143cfe6d0407e260adf99d7384c30532dcristy    Link the node into the skip-list.
265199bd523143cfe6d0407e260adf99d7384c30532dcristy  */
265299bd523143cfe6d0407e260adf99d7384c30532dcristy  do
265399bd523143cfe6d0407e260adf99d7384c30532dcristy  {
265499bd523143cfe6d0407e260adf99d7384c30532dcristy    p->nodes[color].next[level]=p->nodes[update[level]].next[level];
265599bd523143cfe6d0407e260adf99d7384c30532dcristy    p->nodes[update[level]].next[level]=color;
265699bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (level-- > 0);
265799bd523143cfe6d0407e260adf99d7384c30532dcristy}
265899bd523143cfe6d0407e260adf99d7384c30532dcristy
265999bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetMaximumPixelList(PixelList *pixel_list,Quantum *pixel)
266099bd523143cfe6d0407e260adf99d7384c30532dcristy{
266199bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
266299bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
266399bd523143cfe6d0407e260adf99d7384c30532dcristy
266499bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
266599bd523143cfe6d0407e260adf99d7384c30532dcristy    color,
266699bd523143cfe6d0407e260adf99d7384c30532dcristy    maximum;
266799bd523143cfe6d0407e260adf99d7384c30532dcristy
266899bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
266999bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
267099bd523143cfe6d0407e260adf99d7384c30532dcristy
267199bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
267299bd523143cfe6d0407e260adf99d7384c30532dcristy    Find the maximum value for each of the color.
267399bd523143cfe6d0407e260adf99d7384c30532dcristy  */
267499bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
267599bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536L;
267699bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
267799bd523143cfe6d0407e260adf99d7384c30532dcristy  maximum=p->nodes[color].next[0];
267899bd523143cfe6d0407e260adf99d7384c30532dcristy  do
267999bd523143cfe6d0407e260adf99d7384c30532dcristy  {
268099bd523143cfe6d0407e260adf99d7384c30532dcristy    color=p->nodes[color].next[0];
268199bd523143cfe6d0407e260adf99d7384c30532dcristy    if (color > maximum)
268299bd523143cfe6d0407e260adf99d7384c30532dcristy      maximum=color;
268399bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
268499bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count < (ssize_t) pixel_list->length);
268599bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) maximum);
268699bd523143cfe6d0407e260adf99d7384c30532dcristy}
268799bd523143cfe6d0407e260adf99d7384c30532dcristy
268899bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetMeanPixelList(PixelList *pixel_list,Quantum *pixel)
268999bd523143cfe6d0407e260adf99d7384c30532dcristy{
2690a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
269199bd523143cfe6d0407e260adf99d7384c30532dcristy    sum;
269299bd523143cfe6d0407e260adf99d7384c30532dcristy
269399bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
269499bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
269599bd523143cfe6d0407e260adf99d7384c30532dcristy
269699bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
269799bd523143cfe6d0407e260adf99d7384c30532dcristy    color;
269899bd523143cfe6d0407e260adf99d7384c30532dcristy
269999bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
270099bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
270199bd523143cfe6d0407e260adf99d7384c30532dcristy
270299bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
270399bd523143cfe6d0407e260adf99d7384c30532dcristy    Find the mean value for each of the color.
270499bd523143cfe6d0407e260adf99d7384c30532dcristy  */
270599bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
270699bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536L;
270799bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
270899bd523143cfe6d0407e260adf99d7384c30532dcristy  sum=0.0;
270999bd523143cfe6d0407e260adf99d7384c30532dcristy  do
271099bd523143cfe6d0407e260adf99d7384c30532dcristy  {
271199bd523143cfe6d0407e260adf99d7384c30532dcristy    color=p->nodes[color].next[0];
2712a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    sum+=(double) p->nodes[color].count*color;
271399bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
271499bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count < (ssize_t) pixel_list->length);
271599bd523143cfe6d0407e260adf99d7384c30532dcristy  sum/=pixel_list->length;
271699bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) sum);
271799bd523143cfe6d0407e260adf99d7384c30532dcristy}
271899bd523143cfe6d0407e260adf99d7384c30532dcristy
271999bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetMedianPixelList(PixelList *pixel_list,Quantum *pixel)
272099bd523143cfe6d0407e260adf99d7384c30532dcristy{
272199bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
272299bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
272399bd523143cfe6d0407e260adf99d7384c30532dcristy
272499bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
272599bd523143cfe6d0407e260adf99d7384c30532dcristy    color;
272699bd523143cfe6d0407e260adf99d7384c30532dcristy
272799bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
272899bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
272999bd523143cfe6d0407e260adf99d7384c30532dcristy
273099bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
273199bd523143cfe6d0407e260adf99d7384c30532dcristy    Find the median value for each of the color.
273299bd523143cfe6d0407e260adf99d7384c30532dcristy  */
273399bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
273499bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536L;
273599bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
273699bd523143cfe6d0407e260adf99d7384c30532dcristy  do
273799bd523143cfe6d0407e260adf99d7384c30532dcristy  {
273899bd523143cfe6d0407e260adf99d7384c30532dcristy    color=p->nodes[color].next[0];
273999bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
274099bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count <= (ssize_t) (pixel_list->length >> 1));
274199bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) color);
274299bd523143cfe6d0407e260adf99d7384c30532dcristy}
274399bd523143cfe6d0407e260adf99d7384c30532dcristy
274499bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetMinimumPixelList(PixelList *pixel_list,Quantum *pixel)
274599bd523143cfe6d0407e260adf99d7384c30532dcristy{
274699bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
274799bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
274899bd523143cfe6d0407e260adf99d7384c30532dcristy
274999bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
275099bd523143cfe6d0407e260adf99d7384c30532dcristy    color,
275199bd523143cfe6d0407e260adf99d7384c30532dcristy    minimum;
275299bd523143cfe6d0407e260adf99d7384c30532dcristy
275399bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
275499bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
275599bd523143cfe6d0407e260adf99d7384c30532dcristy
275699bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
275799bd523143cfe6d0407e260adf99d7384c30532dcristy    Find the minimum value for each of the color.
275899bd523143cfe6d0407e260adf99d7384c30532dcristy  */
275999bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
276099bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
276199bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536UL;
276299bd523143cfe6d0407e260adf99d7384c30532dcristy  minimum=p->nodes[color].next[0];
276399bd523143cfe6d0407e260adf99d7384c30532dcristy  do
276499bd523143cfe6d0407e260adf99d7384c30532dcristy  {
276599bd523143cfe6d0407e260adf99d7384c30532dcristy    color=p->nodes[color].next[0];
276699bd523143cfe6d0407e260adf99d7384c30532dcristy    if (color < minimum)
276799bd523143cfe6d0407e260adf99d7384c30532dcristy      minimum=color;
276899bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
276999bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count < (ssize_t) pixel_list->length);
277099bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) minimum);
277199bd523143cfe6d0407e260adf99d7384c30532dcristy}
277299bd523143cfe6d0407e260adf99d7384c30532dcristy
277399bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetModePixelList(PixelList *pixel_list,Quantum *pixel)
277499bd523143cfe6d0407e260adf99d7384c30532dcristy{
277599bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
277699bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
277799bd523143cfe6d0407e260adf99d7384c30532dcristy
277899bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
277999bd523143cfe6d0407e260adf99d7384c30532dcristy    color,
278099bd523143cfe6d0407e260adf99d7384c30532dcristy    max_count,
278199bd523143cfe6d0407e260adf99d7384c30532dcristy    mode;
278299bd523143cfe6d0407e260adf99d7384c30532dcristy
278399bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
278499bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
278599bd523143cfe6d0407e260adf99d7384c30532dcristy
278699bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
278799bd523143cfe6d0407e260adf99d7384c30532dcristy    Make each pixel the 'predominant color' of the specified neighborhood.
278899bd523143cfe6d0407e260adf99d7384c30532dcristy  */
278999bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
279099bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536L;
279199bd523143cfe6d0407e260adf99d7384c30532dcristy  mode=color;
279299bd523143cfe6d0407e260adf99d7384c30532dcristy  max_count=p->nodes[mode].count;
279399bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
279499bd523143cfe6d0407e260adf99d7384c30532dcristy  do
279599bd523143cfe6d0407e260adf99d7384c30532dcristy  {
279699bd523143cfe6d0407e260adf99d7384c30532dcristy    color=p->nodes[color].next[0];
279799bd523143cfe6d0407e260adf99d7384c30532dcristy    if (p->nodes[color].count > max_count)
279899bd523143cfe6d0407e260adf99d7384c30532dcristy      {
279999bd523143cfe6d0407e260adf99d7384c30532dcristy        mode=color;
280099bd523143cfe6d0407e260adf99d7384c30532dcristy        max_count=p->nodes[mode].count;
280199bd523143cfe6d0407e260adf99d7384c30532dcristy      }
280299bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
280399bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count < (ssize_t) pixel_list->length);
280499bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) mode);
280599bd523143cfe6d0407e260adf99d7384c30532dcristy}
280699bd523143cfe6d0407e260adf99d7384c30532dcristy
280799bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetNonpeakPixelList(PixelList *pixel_list,Quantum *pixel)
280899bd523143cfe6d0407e260adf99d7384c30532dcristy{
280999bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
281099bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
281199bd523143cfe6d0407e260adf99d7384c30532dcristy
281299bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
281399bd523143cfe6d0407e260adf99d7384c30532dcristy    color,
281499bd523143cfe6d0407e260adf99d7384c30532dcristy    next,
281599bd523143cfe6d0407e260adf99d7384c30532dcristy    previous;
281699bd523143cfe6d0407e260adf99d7384c30532dcristy
281799bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
281899bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
281999bd523143cfe6d0407e260adf99d7384c30532dcristy
282099bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
282199bd523143cfe6d0407e260adf99d7384c30532dcristy    Finds the non peak value for each of the colors.
282299bd523143cfe6d0407e260adf99d7384c30532dcristy  */
282399bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
282499bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536L;
282599bd523143cfe6d0407e260adf99d7384c30532dcristy  next=p->nodes[color].next[0];
282699bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
282799bd523143cfe6d0407e260adf99d7384c30532dcristy  do
282899bd523143cfe6d0407e260adf99d7384c30532dcristy  {
282999bd523143cfe6d0407e260adf99d7384c30532dcristy    previous=color;
283099bd523143cfe6d0407e260adf99d7384c30532dcristy    color=next;
283199bd523143cfe6d0407e260adf99d7384c30532dcristy    next=p->nodes[color].next[0];
283299bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
283399bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count <= (ssize_t) (pixel_list->length >> 1));
283499bd523143cfe6d0407e260adf99d7384c30532dcristy  if ((previous == 65536UL) && (next != 65536UL))
283599bd523143cfe6d0407e260adf99d7384c30532dcristy    color=next;
283699bd523143cfe6d0407e260adf99d7384c30532dcristy  else
283799bd523143cfe6d0407e260adf99d7384c30532dcristy    if ((previous != 65536UL) && (next == 65536UL))
283899bd523143cfe6d0407e260adf99d7384c30532dcristy      color=previous;
283999bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) color);
284099bd523143cfe6d0407e260adf99d7384c30532dcristy}
284199bd523143cfe6d0407e260adf99d7384c30532dcristy
2842180908c3457893af93b890e3d01a992727574877cristystatic inline void GetRootMeanSquarePixelList(PixelList *pixel_list,
2843180908c3457893af93b890e3d01a992727574877cristy  Quantum *pixel)
2844180908c3457893af93b890e3d01a992727574877cristy{
2845180908c3457893af93b890e3d01a992727574877cristy  double
2846180908c3457893af93b890e3d01a992727574877cristy    sum;
2847180908c3457893af93b890e3d01a992727574877cristy
2848180908c3457893af93b890e3d01a992727574877cristy  register SkipList
2849180908c3457893af93b890e3d01a992727574877cristy    *p;
2850180908c3457893af93b890e3d01a992727574877cristy
2851180908c3457893af93b890e3d01a992727574877cristy  size_t
2852180908c3457893af93b890e3d01a992727574877cristy    color;
2853180908c3457893af93b890e3d01a992727574877cristy
2854180908c3457893af93b890e3d01a992727574877cristy  ssize_t
2855180908c3457893af93b890e3d01a992727574877cristy    count;
2856180908c3457893af93b890e3d01a992727574877cristy
2857180908c3457893af93b890e3d01a992727574877cristy  /*
2858f6841eb57b1dd6793ceed3d28dba80e999d35dc4cristy    Find the root mean square value for each of the color.
2859180908c3457893af93b890e3d01a992727574877cristy  */
2860180908c3457893af93b890e3d01a992727574877cristy  p=(&pixel_list->skip_list);
2861180908c3457893af93b890e3d01a992727574877cristy  color=65536L;
2862180908c3457893af93b890e3d01a992727574877cristy  count=0;
2863180908c3457893af93b890e3d01a992727574877cristy  sum=0.0;
2864180908c3457893af93b890e3d01a992727574877cristy  do
2865180908c3457893af93b890e3d01a992727574877cristy  {
2866180908c3457893af93b890e3d01a992727574877cristy    color=p->nodes[color].next[0];
28671db95d8518770b18cb8a69f5c3d3366843c3064fcristy    sum+=(double) (p->nodes[color].count*color*color);
2868180908c3457893af93b890e3d01a992727574877cristy    count+=p->nodes[color].count;
2869180908c3457893af93b890e3d01a992727574877cristy  } while (count < (ssize_t) pixel_list->length);
2870180908c3457893af93b890e3d01a992727574877cristy  sum/=pixel_list->length;
2871180908c3457893af93b890e3d01a992727574877cristy  *pixel=ScaleShortToQuantum((unsigned short) sqrt(sum));
2872180908c3457893af93b890e3d01a992727574877cristy}
2873180908c3457893af93b890e3d01a992727574877cristy
287499bd523143cfe6d0407e260adf99d7384c30532dcristystatic inline void GetStandardDeviationPixelList(PixelList *pixel_list,
287599bd523143cfe6d0407e260adf99d7384c30532dcristy  Quantum *pixel)
287699bd523143cfe6d0407e260adf99d7384c30532dcristy{
2877a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
287899bd523143cfe6d0407e260adf99d7384c30532dcristy    sum,
287999bd523143cfe6d0407e260adf99d7384c30532dcristy    sum_squared;
288099bd523143cfe6d0407e260adf99d7384c30532dcristy
288199bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
288299bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
288399bd523143cfe6d0407e260adf99d7384c30532dcristy
288499bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
288599bd523143cfe6d0407e260adf99d7384c30532dcristy    color;
288699bd523143cfe6d0407e260adf99d7384c30532dcristy
288799bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
288899bd523143cfe6d0407e260adf99d7384c30532dcristy    count;
288999bd523143cfe6d0407e260adf99d7384c30532dcristy
289099bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
289199bd523143cfe6d0407e260adf99d7384c30532dcristy    Find the standard-deviation value for each of the color.
289299bd523143cfe6d0407e260adf99d7384c30532dcristy  */
289399bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
289499bd523143cfe6d0407e260adf99d7384c30532dcristy  color=65536L;
289599bd523143cfe6d0407e260adf99d7384c30532dcristy  count=0;
289699bd523143cfe6d0407e260adf99d7384c30532dcristy  sum=0.0;
289799bd523143cfe6d0407e260adf99d7384c30532dcristy  sum_squared=0.0;
289899bd523143cfe6d0407e260adf99d7384c30532dcristy  do
289999bd523143cfe6d0407e260adf99d7384c30532dcristy  {
290099bd523143cfe6d0407e260adf99d7384c30532dcristy    register ssize_t
290199bd523143cfe6d0407e260adf99d7384c30532dcristy      i;
290299bd523143cfe6d0407e260adf99d7384c30532dcristy
290399bd523143cfe6d0407e260adf99d7384c30532dcristy    color=p->nodes[color].next[0];
2904a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy    sum+=(double) p->nodes[color].count*color;
290599bd523143cfe6d0407e260adf99d7384c30532dcristy    for (i=0; i < (ssize_t) p->nodes[color].count; i++)
2906a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy      sum_squared+=((double) color)*((double) color);
290799bd523143cfe6d0407e260adf99d7384c30532dcristy    count+=p->nodes[color].count;
290899bd523143cfe6d0407e260adf99d7384c30532dcristy  } while (count < (ssize_t) pixel_list->length);
290999bd523143cfe6d0407e260adf99d7384c30532dcristy  sum/=pixel_list->length;
291099bd523143cfe6d0407e260adf99d7384c30532dcristy  sum_squared/=pixel_list->length;
291199bd523143cfe6d0407e260adf99d7384c30532dcristy  *pixel=ScaleShortToQuantum((unsigned short) sqrt(sum_squared-(sum*sum)));
291299bd523143cfe6d0407e260adf99d7384c30532dcristy}
291399bd523143cfe6d0407e260adf99d7384c30532dcristy
2914b0de93fdedaac769cb08e15b3ec176d4c9078907cristystatic inline void InsertPixelList(const Quantum pixel,PixelList *pixel_list)
291599bd523143cfe6d0407e260adf99d7384c30532dcristy{
291699bd523143cfe6d0407e260adf99d7384c30532dcristy  size_t
291799bd523143cfe6d0407e260adf99d7384c30532dcristy    signature;
291899bd523143cfe6d0407e260adf99d7384c30532dcristy
291999bd523143cfe6d0407e260adf99d7384c30532dcristy  unsigned short
292099bd523143cfe6d0407e260adf99d7384c30532dcristy    index;
292199bd523143cfe6d0407e260adf99d7384c30532dcristy
292299bd523143cfe6d0407e260adf99d7384c30532dcristy  index=ScaleQuantumToShort(pixel);
292399bd523143cfe6d0407e260adf99d7384c30532dcristy  signature=pixel_list->skip_list.nodes[index].signature;
292499bd523143cfe6d0407e260adf99d7384c30532dcristy  if (signature == pixel_list->signature)
292599bd523143cfe6d0407e260adf99d7384c30532dcristy    {
292699bd523143cfe6d0407e260adf99d7384c30532dcristy      pixel_list->skip_list.nodes[index].count++;
292799bd523143cfe6d0407e260adf99d7384c30532dcristy      return;
292899bd523143cfe6d0407e260adf99d7384c30532dcristy    }
292999bd523143cfe6d0407e260adf99d7384c30532dcristy  AddNodePixelList(pixel_list,index);
293099bd523143cfe6d0407e260adf99d7384c30532dcristy}
293199bd523143cfe6d0407e260adf99d7384c30532dcristy
293299bd523143cfe6d0407e260adf99d7384c30532dcristystatic void ResetPixelList(PixelList *pixel_list)
293399bd523143cfe6d0407e260adf99d7384c30532dcristy{
293499bd523143cfe6d0407e260adf99d7384c30532dcristy  int
293599bd523143cfe6d0407e260adf99d7384c30532dcristy    level;
293699bd523143cfe6d0407e260adf99d7384c30532dcristy
293799bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipNode
293899bd523143cfe6d0407e260adf99d7384c30532dcristy    *root;
293999bd523143cfe6d0407e260adf99d7384c30532dcristy
294099bd523143cfe6d0407e260adf99d7384c30532dcristy  register SkipList
294199bd523143cfe6d0407e260adf99d7384c30532dcristy    *p;
294299bd523143cfe6d0407e260adf99d7384c30532dcristy
294399bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
294499bd523143cfe6d0407e260adf99d7384c30532dcristy    Reset the skip-list.
294599bd523143cfe6d0407e260adf99d7384c30532dcristy  */
294699bd523143cfe6d0407e260adf99d7384c30532dcristy  p=(&pixel_list->skip_list);
294799bd523143cfe6d0407e260adf99d7384c30532dcristy  root=p->nodes+65536UL;
294899bd523143cfe6d0407e260adf99d7384c30532dcristy  p->level=0;
294999bd523143cfe6d0407e260adf99d7384c30532dcristy  for (level=0; level < 9; level++)
295099bd523143cfe6d0407e260adf99d7384c30532dcristy    root->next[level]=65536UL;
295199bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list->seed=pixel_list->signature++;
295299bd523143cfe6d0407e260adf99d7384c30532dcristy}
295399bd523143cfe6d0407e260adf99d7384c30532dcristy
295499bd523143cfe6d0407e260adf99d7384c30532dcristyMagickExport Image *StatisticImage(const Image *image,const StatisticType type,
295599bd523143cfe6d0407e260adf99d7384c30532dcristy  const size_t width,const size_t height,ExceptionInfo *exception)
295699bd523143cfe6d0407e260adf99d7384c30532dcristy{
295799bd523143cfe6d0407e260adf99d7384c30532dcristy#define StatisticImageTag  "Statistic/Image"
295899bd523143cfe6d0407e260adf99d7384c30532dcristy
295999bd523143cfe6d0407e260adf99d7384c30532dcristy  CacheView
296099bd523143cfe6d0407e260adf99d7384c30532dcristy    *image_view,
296199bd523143cfe6d0407e260adf99d7384c30532dcristy    *statistic_view;
296299bd523143cfe6d0407e260adf99d7384c30532dcristy
296399bd523143cfe6d0407e260adf99d7384c30532dcristy  Image
296499bd523143cfe6d0407e260adf99d7384c30532dcristy    *statistic_image;
296599bd523143cfe6d0407e260adf99d7384c30532dcristy
296699bd523143cfe6d0407e260adf99d7384c30532dcristy  MagickBooleanType
296799bd523143cfe6d0407e260adf99d7384c30532dcristy    status;
296899bd523143cfe6d0407e260adf99d7384c30532dcristy
296999bd523143cfe6d0407e260adf99d7384c30532dcristy  MagickOffsetType
297099bd523143cfe6d0407e260adf99d7384c30532dcristy    progress;
297199bd523143cfe6d0407e260adf99d7384c30532dcristy
297299bd523143cfe6d0407e260adf99d7384c30532dcristy  PixelList
297305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk    **magick_restrict pixel_list;
297499bd523143cfe6d0407e260adf99d7384c30532dcristy
297599bd523143cfe6d0407e260adf99d7384c30532dcristy  ssize_t
297699bd523143cfe6d0407e260adf99d7384c30532dcristy    center,
297799bd523143cfe6d0407e260adf99d7384c30532dcristy    y;
297899bd523143cfe6d0407e260adf99d7384c30532dcristy
297999bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
298099bd523143cfe6d0407e260adf99d7384c30532dcristy    Initialize statistics image attributes.
298199bd523143cfe6d0407e260adf99d7384c30532dcristy  */
298299bd523143cfe6d0407e260adf99d7384c30532dcristy  assert(image != (Image *) NULL);
2983e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
298499bd523143cfe6d0407e260adf99d7384c30532dcristy  if (image->debug != MagickFalse)
298599bd523143cfe6d0407e260adf99d7384c30532dcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
298699bd523143cfe6d0407e260adf99d7384c30532dcristy  assert(exception != (ExceptionInfo *) NULL);
2987e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
298899bd523143cfe6d0407e260adf99d7384c30532dcristy  statistic_image=CloneImage(image,image->columns,image->rows,MagickTrue,
298999bd523143cfe6d0407e260adf99d7384c30532dcristy    exception);
299099bd523143cfe6d0407e260adf99d7384c30532dcristy  if (statistic_image == (Image *) NULL)
299199bd523143cfe6d0407e260adf99d7384c30532dcristy    return((Image *) NULL);
299299bd523143cfe6d0407e260adf99d7384c30532dcristy  status=SetImageStorageClass(statistic_image,DirectClass,exception);
299399bd523143cfe6d0407e260adf99d7384c30532dcristy  if (status == MagickFalse)
299499bd523143cfe6d0407e260adf99d7384c30532dcristy    {
299599bd523143cfe6d0407e260adf99d7384c30532dcristy      statistic_image=DestroyImage(statistic_image);
299699bd523143cfe6d0407e260adf99d7384c30532dcristy      return((Image *) NULL);
299799bd523143cfe6d0407e260adf99d7384c30532dcristy    }
299899bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list=AcquirePixelListThreadSet(MagickMax(width,1),MagickMax(height,1));
299999bd523143cfe6d0407e260adf99d7384c30532dcristy  if (pixel_list == (PixelList **) NULL)
300099bd523143cfe6d0407e260adf99d7384c30532dcristy    {
300199bd523143cfe6d0407e260adf99d7384c30532dcristy      statistic_image=DestroyImage(statistic_image);
300299bd523143cfe6d0407e260adf99d7384c30532dcristy      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
300399bd523143cfe6d0407e260adf99d7384c30532dcristy    }
300499bd523143cfe6d0407e260adf99d7384c30532dcristy  /*
300599bd523143cfe6d0407e260adf99d7384c30532dcristy    Make each pixel the min / max / median / mode / etc. of the neighborhood.
300699bd523143cfe6d0407e260adf99d7384c30532dcristy  */
300799bd523143cfe6d0407e260adf99d7384c30532dcristy  center=(ssize_t) GetPixelChannels(image)*(image->columns+MagickMax(width,1))*
300899bd523143cfe6d0407e260adf99d7384c30532dcristy    (MagickMax(height,1)/2L)+GetPixelChannels(image)*(MagickMax(width,1)/2L);
300999bd523143cfe6d0407e260adf99d7384c30532dcristy  status=MagickTrue;
301099bd523143cfe6d0407e260adf99d7384c30532dcristy  progress=0;
301146ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  image_view=AcquireVirtualCacheView(image,exception);
301246ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy  statistic_view=AcquireAuthenticCacheView(statistic_image,exception);
301399bd523143cfe6d0407e260adf99d7384c30532dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
3014ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy  #pragma omp parallel for schedule(static,4) shared(progress,status) \
30155e6b259130f9dbe0da4666f734937017babe573acristy    magick_threads(image,statistic_image,statistic_image->rows,1)
301699bd523143cfe6d0407e260adf99d7384c30532dcristy#endif
301799bd523143cfe6d0407e260adf99d7384c30532dcristy  for (y=0; y < (ssize_t) statistic_image->rows; y++)
301899bd523143cfe6d0407e260adf99d7384c30532dcristy  {
301999bd523143cfe6d0407e260adf99d7384c30532dcristy    const int
302099bd523143cfe6d0407e260adf99d7384c30532dcristy      id = GetOpenMPThreadId();
302199bd523143cfe6d0407e260adf99d7384c30532dcristy
302299bd523143cfe6d0407e260adf99d7384c30532dcristy    register const Quantum
302305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict p;
302499bd523143cfe6d0407e260adf99d7384c30532dcristy
302599bd523143cfe6d0407e260adf99d7384c30532dcristy    register Quantum
302605d2ff7ebf21f659f5b11e45afb294e152f4330cdirk      *magick_restrict q;
302799bd523143cfe6d0407e260adf99d7384c30532dcristy
302899bd523143cfe6d0407e260adf99d7384c30532dcristy    register ssize_t
302999bd523143cfe6d0407e260adf99d7384c30532dcristy      x;
303099bd523143cfe6d0407e260adf99d7384c30532dcristy
303199bd523143cfe6d0407e260adf99d7384c30532dcristy    if (status == MagickFalse)
303299bd523143cfe6d0407e260adf99d7384c30532dcristy      continue;
303399bd523143cfe6d0407e260adf99d7384c30532dcristy    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) MagickMax(width,1)/2L),y-
303499bd523143cfe6d0407e260adf99d7384c30532dcristy      (ssize_t) (MagickMax(height,1)/2L),image->columns+MagickMax(width,1),
303599bd523143cfe6d0407e260adf99d7384c30532dcristy      MagickMax(height,1),exception);
303699bd523143cfe6d0407e260adf99d7384c30532dcristy    q=QueueCacheViewAuthenticPixels(statistic_view,0,y,statistic_image->columns,      1,exception);
303799bd523143cfe6d0407e260adf99d7384c30532dcristy    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
303899bd523143cfe6d0407e260adf99d7384c30532dcristy      {
303999bd523143cfe6d0407e260adf99d7384c30532dcristy        status=MagickFalse;
304099bd523143cfe6d0407e260adf99d7384c30532dcristy        continue;
304199bd523143cfe6d0407e260adf99d7384c30532dcristy      }
304299bd523143cfe6d0407e260adf99d7384c30532dcristy    for (x=0; x < (ssize_t) statistic_image->columns; x++)
304399bd523143cfe6d0407e260adf99d7384c30532dcristy    {
304499bd523143cfe6d0407e260adf99d7384c30532dcristy      register ssize_t
304599bd523143cfe6d0407e260adf99d7384c30532dcristy        i;
304699bd523143cfe6d0407e260adf99d7384c30532dcristy
304799bd523143cfe6d0407e260adf99d7384c30532dcristy      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
304899bd523143cfe6d0407e260adf99d7384c30532dcristy      {
304999bd523143cfe6d0407e260adf99d7384c30532dcristy        Quantum
305099bd523143cfe6d0407e260adf99d7384c30532dcristy          pixel;
305199bd523143cfe6d0407e260adf99d7384c30532dcristy
305299bd523143cfe6d0407e260adf99d7384c30532dcristy        register const Quantum
305305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk          *magick_restrict pixels;
305499bd523143cfe6d0407e260adf99d7384c30532dcristy
305599bd523143cfe6d0407e260adf99d7384c30532dcristy        register ssize_t
305699bd523143cfe6d0407e260adf99d7384c30532dcristy          u;
305799bd523143cfe6d0407e260adf99d7384c30532dcristy
305899bd523143cfe6d0407e260adf99d7384c30532dcristy        ssize_t
305999bd523143cfe6d0407e260adf99d7384c30532dcristy          v;
306099bd523143cfe6d0407e260adf99d7384c30532dcristy
30615a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelChannel channel=GetPixelChannelChannel(image,i);
30625a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait traits=GetPixelChannelTraits(image,channel);
30635a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy        PixelTrait statistic_traits=GetPixelChannelTraits(statistic_image,
30645a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy          channel);
306599bd523143cfe6d0407e260adf99d7384c30532dcristy        if ((traits == UndefinedPixelTrait) ||
306699bd523143cfe6d0407e260adf99d7384c30532dcristy            (statistic_traits == UndefinedPixelTrait))
306799bd523143cfe6d0407e260adf99d7384c30532dcristy          continue;
30681eced097f7f4f51d5aa14d46079292fa1dcf0e77cristy        if (((statistic_traits & CopyPixelTrait) != 0) ||
3069883fde11debec15cedb05dc5d7228d8588066bc0cristy            (GetPixelReadMask(image,p) == 0))
307099bd523143cfe6d0407e260adf99d7384c30532dcristy          {
307199bd523143cfe6d0407e260adf99d7384c30532dcristy            SetPixelChannel(statistic_image,channel,p[center+i],q);
307299bd523143cfe6d0407e260adf99d7384c30532dcristy            continue;
307399bd523143cfe6d0407e260adf99d7384c30532dcristy          }
307499bd523143cfe6d0407e260adf99d7384c30532dcristy        pixels=p;
307599bd523143cfe6d0407e260adf99d7384c30532dcristy        ResetPixelList(pixel_list[id]);
307699bd523143cfe6d0407e260adf99d7384c30532dcristy        for (v=0; v < (ssize_t) MagickMax(height,1); v++)
307799bd523143cfe6d0407e260adf99d7384c30532dcristy        {
307899bd523143cfe6d0407e260adf99d7384c30532dcristy          for (u=0; u < (ssize_t) MagickMax(width,1); u++)
307999bd523143cfe6d0407e260adf99d7384c30532dcristy          {
3080b0de93fdedaac769cb08e15b3ec176d4c9078907cristy            InsertPixelList(pixels[i],pixel_list[id]);
308199bd523143cfe6d0407e260adf99d7384c30532dcristy            pixels+=GetPixelChannels(image);
308299bd523143cfe6d0407e260adf99d7384c30532dcristy          }
30830c7bac1cfcf74e19cc41d9069a904b0a6fc9c291cristy          pixels+=GetPixelChannels(image)*image->columns;
308499bd523143cfe6d0407e260adf99d7384c30532dcristy        }
308599bd523143cfe6d0407e260adf99d7384c30532dcristy        switch (type)
308699bd523143cfe6d0407e260adf99d7384c30532dcristy        {
308799bd523143cfe6d0407e260adf99d7384c30532dcristy          case GradientStatistic:
308899bd523143cfe6d0407e260adf99d7384c30532dcristy          {
3089a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            double
309099bd523143cfe6d0407e260adf99d7384c30532dcristy              maximum,
309199bd523143cfe6d0407e260adf99d7384c30532dcristy              minimum;
309299bd523143cfe6d0407e260adf99d7384c30532dcristy
309399bd523143cfe6d0407e260adf99d7384c30532dcristy            GetMinimumPixelList(pixel_list[id],&pixel);
3094a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            minimum=(double) pixel;
309599bd523143cfe6d0407e260adf99d7384c30532dcristy            GetMaximumPixelList(pixel_list[id],&pixel);
3096a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy            maximum=(double) pixel;
309799bd523143cfe6d0407e260adf99d7384c30532dcristy            pixel=ClampToQuantum(MagickAbsoluteValue(maximum-minimum));
309899bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
309999bd523143cfe6d0407e260adf99d7384c30532dcristy          }
310099bd523143cfe6d0407e260adf99d7384c30532dcristy          case MaximumStatistic:
310199bd523143cfe6d0407e260adf99d7384c30532dcristy          {
310299bd523143cfe6d0407e260adf99d7384c30532dcristy            GetMaximumPixelList(pixel_list[id],&pixel);
310399bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
310499bd523143cfe6d0407e260adf99d7384c30532dcristy          }
310599bd523143cfe6d0407e260adf99d7384c30532dcristy          case MeanStatistic:
310699bd523143cfe6d0407e260adf99d7384c30532dcristy          {
310799bd523143cfe6d0407e260adf99d7384c30532dcristy            GetMeanPixelList(pixel_list[id],&pixel);
310899bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
310999bd523143cfe6d0407e260adf99d7384c30532dcristy          }
311099bd523143cfe6d0407e260adf99d7384c30532dcristy          case MedianStatistic:
311199bd523143cfe6d0407e260adf99d7384c30532dcristy          default:
311299bd523143cfe6d0407e260adf99d7384c30532dcristy          {
311399bd523143cfe6d0407e260adf99d7384c30532dcristy            GetMedianPixelList(pixel_list[id],&pixel);
311499bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
311599bd523143cfe6d0407e260adf99d7384c30532dcristy          }
311699bd523143cfe6d0407e260adf99d7384c30532dcristy          case MinimumStatistic:
311799bd523143cfe6d0407e260adf99d7384c30532dcristy          {
311899bd523143cfe6d0407e260adf99d7384c30532dcristy            GetMinimumPixelList(pixel_list[id],&pixel);
311999bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
312099bd523143cfe6d0407e260adf99d7384c30532dcristy          }
312199bd523143cfe6d0407e260adf99d7384c30532dcristy          case ModeStatistic:
312299bd523143cfe6d0407e260adf99d7384c30532dcristy          {
312399bd523143cfe6d0407e260adf99d7384c30532dcristy            GetModePixelList(pixel_list[id],&pixel);
312499bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
312599bd523143cfe6d0407e260adf99d7384c30532dcristy          }
312699bd523143cfe6d0407e260adf99d7384c30532dcristy          case NonpeakStatistic:
312799bd523143cfe6d0407e260adf99d7384c30532dcristy          {
312899bd523143cfe6d0407e260adf99d7384c30532dcristy            GetNonpeakPixelList(pixel_list[id],&pixel);
312999bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
313099bd523143cfe6d0407e260adf99d7384c30532dcristy          }
3131180908c3457893af93b890e3d01a992727574877cristy          case RootMeanSquareStatistic:
3132180908c3457893af93b890e3d01a992727574877cristy          {
3133180908c3457893af93b890e3d01a992727574877cristy            GetRootMeanSquarePixelList(pixel_list[id],&pixel);
3134180908c3457893af93b890e3d01a992727574877cristy            break;
3135180908c3457893af93b890e3d01a992727574877cristy          }
313699bd523143cfe6d0407e260adf99d7384c30532dcristy          case StandardDeviationStatistic:
313799bd523143cfe6d0407e260adf99d7384c30532dcristy          {
313899bd523143cfe6d0407e260adf99d7384c30532dcristy            GetStandardDeviationPixelList(pixel_list[id],&pixel);
313999bd523143cfe6d0407e260adf99d7384c30532dcristy            break;
314099bd523143cfe6d0407e260adf99d7384c30532dcristy          }
314199bd523143cfe6d0407e260adf99d7384c30532dcristy        }
314299bd523143cfe6d0407e260adf99d7384c30532dcristy        SetPixelChannel(statistic_image,channel,pixel,q);
314399bd523143cfe6d0407e260adf99d7384c30532dcristy      }
314499bd523143cfe6d0407e260adf99d7384c30532dcristy      p+=GetPixelChannels(image);
314599bd523143cfe6d0407e260adf99d7384c30532dcristy      q+=GetPixelChannels(statistic_image);
314699bd523143cfe6d0407e260adf99d7384c30532dcristy    }
314799bd523143cfe6d0407e260adf99d7384c30532dcristy    if (SyncCacheViewAuthenticPixels(statistic_view,exception) == MagickFalse)
314899bd523143cfe6d0407e260adf99d7384c30532dcristy      status=MagickFalse;
314999bd523143cfe6d0407e260adf99d7384c30532dcristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
315099bd523143cfe6d0407e260adf99d7384c30532dcristy      {
315199bd523143cfe6d0407e260adf99d7384c30532dcristy        MagickBooleanType
315299bd523143cfe6d0407e260adf99d7384c30532dcristy          proceed;
315399bd523143cfe6d0407e260adf99d7384c30532dcristy
315499bd523143cfe6d0407e260adf99d7384c30532dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT)
3155ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy        #pragma omp critical (MagickCore_StatisticImage)
315699bd523143cfe6d0407e260adf99d7384c30532dcristy#endif
315799bd523143cfe6d0407e260adf99d7384c30532dcristy        proceed=SetImageProgress(image,StatisticImageTag,progress++,
315899bd523143cfe6d0407e260adf99d7384c30532dcristy          image->rows);
315999bd523143cfe6d0407e260adf99d7384c30532dcristy        if (proceed == MagickFalse)
316099bd523143cfe6d0407e260adf99d7384c30532dcristy          status=MagickFalse;
316199bd523143cfe6d0407e260adf99d7384c30532dcristy      }
316299bd523143cfe6d0407e260adf99d7384c30532dcristy  }
316399bd523143cfe6d0407e260adf99d7384c30532dcristy  statistic_view=DestroyCacheView(statistic_view);
316499bd523143cfe6d0407e260adf99d7384c30532dcristy  image_view=DestroyCacheView(image_view);
316599bd523143cfe6d0407e260adf99d7384c30532dcristy  pixel_list=DestroyPixelListThreadSet(pixel_list);
31661c2f48d0fbbad5757296fca9324fa14033f56632cristy  if (status == MagickFalse)
31671c2f48d0fbbad5757296fca9324fa14033f56632cristy    statistic_image=DestroyImage(statistic_image);
316899bd523143cfe6d0407e260adf99d7384c30532dcristy  return(statistic_image);
316999bd523143cfe6d0407e260adf99d7384c30532dcristy}
3170