]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Sun, 7 Mar 2010 17:39:52 +0000 (17:39 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Sun, 7 Mar 2010 17:39:52 +0000 (17:39 +0000)
15 files changed:
ChangeLog
PerlMagick/Magick.xs
magick/deprecate.c
magick/deprecate.h
magick/option.c
magick/statistic.c
magick/statistic.h
utilities/convert.1.in
utilities/mogrify.1.in
wand/convert.c
wand/deprecate.c
wand/deprecate.h
wand/magick-image.c
wand/magick-image.h
wand/mogrify.c

index 2dd8b2cdc348091bdb7aac244976f28fea429b6e..ed53fe52c2f690052fd6599bc5987bb19f665553 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2010-03-05  6.6.0-3 Cristy  <quetzlzacatenango@image...>
+  * The -evaluate-sequence option behaves like -evaluate except it operates
+    on a sequence of images.
+
 2010-03-05  6.6.0-2 Cristy  <quetzlzacatenango@image...>
   * Add support for the -maximum and -minimum options.
 
index 3cfdef5bb00918dfacb58b136c0dbbf4c0666d57..6decaf47b0896482e27be3678dc746f2ee8210f8 100644 (file)
@@ -2636,7 +2636,7 @@ Average(ref)
           PackageName);
         goto PerlException;
       }
-    image=AverageImages(image,exception);
+    image=EvaluateImages(image,MeanEvaluateOperator,exception);
     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
       goto PerlException;
     /*
@@ -3525,6 +3525,163 @@ Display(ref,...)
 #                                                                             #
 #                                                                             #
 #                                                                             #
+#   E v a l u a t e I m a g e s                                               #
+#                                                                             #
+#                                                                             #
+#                                                                             #
+###############################################################################
+#
+#
+void
+EvaluateImages(ref)
+  Image::Magick ref=NO_INIT
+  ALIAS:
+    EvaluateImages   = 1
+    evaluateimages   = 2
+  PPCODE:
+  {
+    AV
+      *av;
+
+    char
+      *attribute,
+      *p;
+
+    ExceptionInfo
+      *exception;
+
+    HV
+      *hv;
+
+    Image
+      *image;
+
+    MagickEvaluateOperator
+      op;
+
+    register long
+      i;
+
+    struct PackageInfo
+      *info;
+
+    SV
+      *perl_exception,
+      *reference,
+      *rv,
+      *sv;
+
+    exception=AcquireExceptionInfo();
+    perl_exception=newSVpv("",0);
+    if (sv_isobject(ST(0)) == 0)
+      {
+        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
+          PackageName);
+        goto PerlException;
+      }
+    reference=SvRV(ST(0));
+    hv=SvSTASH(reference);
+    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
+    if (image == (Image *) NULL)
+      {
+        ThrowPerlException(exception,OptionError,"NoImagesDefined",
+          PackageName);
+        goto PerlException;
+      }
+    op=MeanEvaluateOperator;
+    if (items == 2)
+      {
+        long
+          in;
+
+        in=ParseMagickOption(MagickEvaluateOptions,MagickFalse,(char *)
+          SvPV(ST(1),na));
+        if (in < 0)
+          {
+            ThrowPerlException(exception,OptionError,"UnrecognizedType",
+              SvPV(ST(i),na));
+            return;
+          }
+        op=(MagickEvaluateOperator) in;
+      }
+    else
+      for (i=2; i < items; i+=2)
+      {
+        attribute=(char *) SvPV(ST(i-1),na);
+        switch (*attribute)
+        {
+          case 'O':
+          case 'o':
+          {
+            if (LocaleCompare(attribute,"operator") == 0)
+              {
+                Image
+                  *next;
+
+                long
+                  in;
+
+                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
+                  MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
+                if (in < 0)
+                  {
+                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
+                      SvPV(ST(i),na));
+                    return;
+                  }
+                op=(MagickEvaluateOperator) in;
+                break;
+              }
+            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
+              attribute);
+            break;
+          }
+          default:
+          {
+            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
+              attribute);
+            break;
+          }
+        }
+      }
+    image=EvaluateImages(image,op,exception);
+    if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
+      goto PerlException;
+    /*
+      Create blessed Perl array for the returned image.
+    */
+    av=newAV();
+    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
+    SvREFCNT_dec(av);
+    AddImageToRegistry(image);
+    rv=newRV(sv);
+    av_push(av,sv_bless(rv,hv));
+    SvREFCNT_dec(sv);
+    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
+    (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
+      "evaluate-%.*s",(int) (MaxTextExtent-9),
+      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
+    (void) CopyMagickString(image->filename,info->image_info->filename,
+      MaxTextExtent);
+    SetImageInfo(info->image_info,0,exception);
+    exception=DestroyExceptionInfo(exception);
+    SvREFCNT_dec(perl_exception);
+    XSRETURN(1);
+
+  PerlException:
+    InheritPerlException(exception,perl_exception);
+    exception=DestroyExceptionInfo(exception);
+    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
+    SvPOK_on(perl_exception);
+    ST(0)=sv_2mortal(perl_exception);
+    XSRETURN(1);
+  }
+\f
+#
+###############################################################################
+#                                                                             #
+#                                                                             #
+#                                                                             #
 #   F e a t u r e s                                                           #
 #                                                                             #
 #                                                                             #
@@ -6752,196 +6909,6 @@ MagickToMime(ref,name)
 #                                                                             #
 #                                                                             #
 #                                                                             #
-#   M a x i m u m                                                             #
-#                                                                             #
-#                                                                             #
-#                                                                             #
-###############################################################################
-#
-#
-void
-Maximum(ref)
-  Image::Magick ref=NO_INIT
-  ALIAS:
-    MaximumImage   = 1
-    maximum        = 2
-    maximumimage   = 3
-  PPCODE:
-  {
-    AV
-      *av;
-
-    char
-      *p;
-
-    ExceptionInfo
-      *exception;
-
-    HV
-      *hv;
-
-    Image
-      *image;
-
-    struct PackageInfo
-      *info;
-
-    SV
-      *perl_exception,
-      *reference,
-      *rv,
-      *sv;
-
-    exception=AcquireExceptionInfo();
-    perl_exception=newSVpv("",0);
-    if (sv_isobject(ST(0)) == 0)
-      {
-        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
-          PackageName);
-        goto PerlException;
-      }
-    reference=SvRV(ST(0));
-    hv=SvSTASH(reference);
-    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
-    if (image == (Image *) NULL)
-      {
-        ThrowPerlException(exception,OptionError,"NoImagesDefined",
-          PackageName);
-        goto PerlException;
-      }
-    image=MaximumImages(image,exception);
-    if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
-      goto PerlException;
-    /*
-      Create blessed Perl array for the returned image.
-    */
-    av=newAV();
-    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
-    SvREFCNT_dec(av);
-    AddImageToRegistry(image);
-    rv=newRV(sv);
-    av_push(av,sv_bless(rv,hv));
-    SvREFCNT_dec(sv);
-    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
-    (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
-      "max-%.*s",(int) (MaxTextExtent-9),
-      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
-    (void) CopyMagickString(image->filename,info->image_info->filename,
-      MaxTextExtent);
-    SetImageInfo(info->image_info,0,exception);
-    exception=DestroyExceptionInfo(exception);
-    SvREFCNT_dec(perl_exception);
-    XSRETURN(1);
-
-  PerlException:
-    InheritPerlException(exception,perl_exception);
-    exception=DestroyExceptionInfo(exception);
-    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
-    SvPOK_on(perl_exception);
-    ST(0)=sv_2mortal(perl_exception);
-    XSRETURN(1);
-  }
-\f
-#
-###############################################################################
-#                                                                             #
-#                                                                             #
-#                                                                             #
-#   M i n i m u m                                                             #
-#                                                                             #
-#                                                                             #
-#                                                                             #
-###############################################################################
-#
-#
-void
-Minimum(ref)
-  Image::Magick ref=NO_INIT
-  ALIAS:
-    MinimumImage   = 1
-    minimum        = 2
-    minimumimage   = 3
-  PPCODE:
-  {
-    AV
-      *av;
-
-    char
-      *p;
-
-    ExceptionInfo
-      *exception;
-
-    HV
-      *hv;
-
-    Image
-      *image;
-
-    struct PackageInfo
-      *info;
-
-    SV
-      *perl_exception,
-      *reference,
-      *rv,
-      *sv;
-
-    exception=AcquireExceptionInfo();
-    perl_exception=newSVpv("",0);
-    if (sv_isobject(ST(0)) == 0)
-      {
-        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
-          PackageName);
-        goto PerlException;
-      }
-    reference=SvRV(ST(0));
-    hv=SvSTASH(reference);
-    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
-    if (image == (Image *) NULL)
-      {
-        ThrowPerlException(exception,OptionError,"NoImagesDefined",
-          PackageName);
-        goto PerlException;
-      }
-    image=MinimumImages(image,exception);
-    if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
-      goto PerlException;
-    /*
-      Create blessed Perl array for the returned image.
-    */
-    av=newAV();
-    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
-    SvREFCNT_dec(av);
-    AddImageToRegistry(image);
-    rv=newRV(sv);
-    av_push(av,sv_bless(rv,hv));
-    SvREFCNT_dec(sv);
-    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
-    (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
-      "minimum-%.*s",(int) (MaxTextExtent-9),
-      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
-    (void) CopyMagickString(image->filename,info->image_info->filename,
-      MaxTextExtent);
-    SetImageInfo(info->image_info,0,exception);
-    exception=DestroyExceptionInfo(exception);
-    SvREFCNT_dec(perl_exception);
-    XSRETURN(1);
-
-  PerlException:
-    InheritPerlException(exception,perl_exception);
-    exception=DestroyExceptionInfo(exception);
-    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
-    SvPOK_on(perl_exception);
-    ST(0)=sv_2mortal(perl_exception);
-    XSRETURN(1);
-  }
-\f
-#
-###############################################################################
-#                                                                             #
-#                                                                             #
-#                                                                             #
 #   M o g r i f y                                                             #
 #                                                                             #
 #                                                                             #
index 02abbf8b1b49fbbd7009b4df3a491071d7cd9673..29a4b155cd5168146a087ad9dcec9da6e2bff44b 100644 (file)
@@ -81,6 +81,7 @@
 #include "magick/semaphore.h"
 #include "magick/segment.h"
 #include "magick/splay-tree.h"
+#include "magick/statistic.h"
 #include "magick/string_.h"
 #include "magick/threshold.h"
 #include "magick/transform.h"
@@ -166,8 +167,7 @@ MagickExport const PixelPacket *AcquireCacheViewPixels(
 %                                                                             %
 %                                                                             %
 %   A c q u i r e I m a g e P i x e l s                                        %
-%                                                                             %
-%                                                                             %
+%                                                                             % %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
@@ -182,9 +182,9 @@ MagickExport const PixelPacket *AcquireCacheViewPixels(
 %
 %  Pixels accessed via the returned pointer represent a simple array of type
 %  PixelPacket.  If the image type is CMYK or the storage class is PseudoClass,
-%  call GetAuthenticIndexQueue() after invoking GetAuthenticPixels() to access the
-%  black color component or to obtain the colormap indexes (of type IndexPacket)
-%  corresponding to the region.
+%  call GetAuthenticIndexQueue() after invoking GetAuthenticPixels() to access
+%  the black color component or to obtain the colormap indexes (of type
+%  IndexPacket) corresponding to the region.
 %
 %  If you plan to modify the pixels, use GetAuthenticPixels() instead.
 %
@@ -687,7 +687,7 @@ MagickExport void AllocateNextImage(const ImageInfo *image_info,Image *image)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   A c q u i r e S t r i n g                                                 %
+%   A l l o c a t e S t r i n g                                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
@@ -730,6 +730,39 @@ MagickExport char *AllocateString(const char *source)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%     A v e r a g e I m a g e s                                               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  AverageImages() takes a set of images and averages them together.  Each
+%  image in the set must have the same width and height.  AverageImages()
+%  returns a single image with each corresponding pixel component of each
+%  image averaged.   On failure, a NULL image is returned and exception
+%  describes the reason for the failure.
+%
+%  The format of the AverageImages method is:
+%
+%      Image *AverageImages(Image *images,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image sequence.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *AverageImages(const Image *images,ExceptionInfo *exception)
+{
+  return(EvaluateImages(images,MeanEvaluateOperator,exception));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %     C h a n n e l I m a g e                                                 %
 %                                                                             %
 %                                                                             %
@@ -4204,6 +4237,64 @@ MagickExport MagickBooleanType MatteFloodfillImage(Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%     M a x i m u m I m a g e s                                               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MaximumImages() returns the maximum intensity of an image sequence.
+%
+%  The format of the MaxImages method is:
+%
+%      Image *MaximumImages(Image *images,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o images: the image sequence.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *MaximumImages(const Image *images,ExceptionInfo *exception)
+{
+  return(EvaluateImages(images,MinEvaluateOperator,exception));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%     M i n i m u m I m a g e s                                               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MinimumImages() returns the minimum intensity of an image sequence.
+%
+%  The format of the MinimumImages method is:
+%
+%      Image *MinimumImages(Image *images,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o images: the image sequence.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *MinimumImages(const Image *images,ExceptionInfo *exception)
+{
+  return(EvaluateImages(images,MinEvaluateOperator,exception));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %     M o s a i c I m a g e s                                                 %
 %                                                                             %
 %                                                                             %
index 3d7af6e48a4eee15fb380a8969e182a7ba2bb0d1..89c44aa24f7a8252165c3aef25dd26fbe541d241 100644 (file)
@@ -93,6 +93,11 @@ extern MagickExport char
   *TranslateText(const ImageInfo *,Image *,const char *)
      magick_attribute((deprecated));
 
+extern MagickExport Image
+  *AverageImages(const Image *,ExceptionInfo *),
+  *MaximumImages(const Image *,ExceptionInfo *),
+  *MinimumImages(const Image *,ExceptionInfo *);
+
 extern MagickExport const ImageAttribute
   *GetImageAttribute(const Image *,const char *),
   *GetImageClippingPathAttribute(Image *) magick_attribute((deprecated)),
index 8c1eb29c8748326361fc74f196719e4ff4236a45..196bb6ffbaef7c21f7dbd721f8b1c296dd541c01 100644 (file)
@@ -318,6 +318,8 @@ static const OptionInfo
     { "-equalize", 0L, MagickFalse },
     { "+evaluate", 0L, MagickFalse },
     { "-evaluate", 2L, MagickFalse },
+    { "+evaluate-sequence", 0L, MagickFalse },
+    { "-evaluate-sequence", 1L, MagickFalse },
     { "+extent", 0L, MagickFalse },
     { "-extent", 1L, MagickFalse },
     { "+extract", 0L, MagickFalse },
@@ -885,6 +887,7 @@ static const OptionInfo
     { "LeftShift", (long) LeftShiftEvaluateOperator, MagickFalse },
     { "Log", (long) LogEvaluateOperator, MagickFalse },
     { "Max", (long) MaxEvaluateOperator, MagickFalse },
+    { "Mean", (long) MeanEvaluateOperator, MagickFalse },
     { "Min", (long) MinEvaluateOperator, MagickFalse },
     { "MultiplicativeNoise", (long) MultiplicativeNoiseEvaluateOperator, MagickFalse },
     { "Multiply", (long) MultiplyEvaluateOperator, MagickFalse },
@@ -975,6 +978,7 @@ static const OptionInfo
     { "debug", MagickTrue, MagickFalse },
     { "deconstruct", MagickTrue, MagickFalse },
     { "delete", MagickTrue, MagickFalse },
+    { "evaluate-seqence", MagickTrue, MagickFalse },
     { "fft", MagickTrue, MagickFalse },
     { "flatten", MagickTrue, MagickFalse },
     { "fx", MagickTrue, MagickFalse },
index ebf1297d03cab2fa08efe3b8ade6f19b7a48a1b8..09337873f5d39e064fe2fc12a4338dd0c55b4a40 100644 (file)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%     A v e r a g e I m a g e s                                               %
+%     E v a l u a t e I m a g e                                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  AverageImages() takes a set of images and averages them together.  Each
-%  image in the set must have the same width and height.  AverageImages()
-%  returns a single image with each corresponding pixel component of each
-%  image averaged.   On failure, a NULL image is returned and exception
-%  describes the reason for the failure.
+%  EvaluateImage() applies a value to the image with an arithmetic, relational,
+%  or logical operator to an image. Use these operations to lighten or darken
+%  an image, to increase or decrease contrast in an image, or to produce the
+%  "negative" of an image.
 %
-%  The format of the AverageImages method is:
+%  The format of the EvaluateImageChannel method is:
 %
-%      Image *AverageImages(Image *images,ExceptionInfo *exception)
+%      MagickBooleanType EvaluateImage(Image *image,
+%        const MagickEvaluateOperator op,const double value,
+%        ExceptionInfo *exception)
+%      MagickBooleanType EvaluateImages(Image *images,
+%        const MagickEvaluateOperator op,const double value,
+%        ExceptionInfo *exception)
+%      MagickBooleanType EvaluateImageChannel(Image *image,
+%        const ChannelType channel,const MagickEvaluateOperator op,
+%        const double value,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
-%    o image: the image sequence.
+%    o image: the image.
+%
+%    o channel: the channel.
+%
+%    o op: A channel op.
+%
+%    o value: A value value.
 %
 %    o exception: return any errors or warnings in this structure.
 %
@@ -162,230 +175,6 @@ static MagickPixelPacket **AcquirePixelThreadSet(const Image *image)
   return(pixels);
 }
 
-MagickExport Image *AverageImages(const Image *images,ExceptionInfo *exception)
-{
-#define AverageImageTag  "Average/Image"
-
-  CacheView
-    *average_view;
-
-  const Image
-    *next;
-
-  Image
-    *average_image;
-
-  long
-    progress,
-    y;
-
-  MagickBooleanType
-    status;
-
-  MagickPixelPacket
-    **restrict average_pixels,
-    zero;
-
-  unsigned long
-    number_images;
-
-  /*
-    Ensure the image are the same size.
-  */
-  assert(images != (Image *) NULL);
-  assert(images->signature == MagickSignature);
-  if (images->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
-    if ((next->columns != images->columns) || (next->rows != images->rows))
-      {
-        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-          "ImageWidthsOrHeightsDiffer","`%s'",images->filename);
-        return((Image *) NULL);
-      }
-  /*
-    Initialize average next attributes.
-  */
-  average_image=CloneImage(images,images->columns,images->rows,MagickTrue,
-    exception);
-  if (average_image == (Image *) NULL)
-    return((Image *) NULL);
-  if (SetImageStorageClass(average_image,DirectClass) == MagickFalse)
-    {
-      InheritException(exception,&average_image->exception);
-      average_image=DestroyImage(average_image);
-      return((Image *) NULL);
-    }
-  average_pixels=AcquirePixelThreadSet(images);
-  if (average_pixels == (MagickPixelPacket **) NULL)
-    {
-      average_image=DestroyImage(average_image);
-      (void) ThrowMagickException(exception,GetMagickModule(),
-        ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
-      return((Image *) NULL);
-    }
-  /*
-    Average image pixels.
-  */
-  status=MagickTrue;
-  progress=0;
-  GetMagickPixelPacket(images,&zero);
-  number_images=GetImageListLength(images);
-  average_view=AcquireCacheView(average_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic) shared(progress,status)
-#endif
-  for (y=0; y < (long) average_image->rows; y++)
-  {
-    CacheView
-      *image_view;
-
-    const Image
-      *next;
-
-    MagickPixelPacket
-      pixel;
-
-    register IndexPacket
-      *restrict average_indexes;
-
-    register long
-      i,
-      id,
-      x;
-
-    register MagickPixelPacket
-      *average_pixel;
-
-    register PixelPacket
-      *restrict q;
-
-    if (status == MagickFalse)
-      continue;
-    q=QueueCacheViewAuthenticPixels(average_view,0,y,average_image->columns,1,
-      exception);
-    if (q == (PixelPacket *) NULL)
-      {
-        status=MagickFalse;
-        continue;
-      }
-    average_indexes=GetCacheViewAuthenticIndexQueue(average_view);
-    pixel=zero;
-    id=GetOpenMPThreadId();
-    average_pixel=average_pixels[id];
-    for (x=0; x < (long) average_image->columns; x++)
-      average_pixel[x]=zero;
-    next=images;
-    for (i=0; i < (long) number_images; i++)
-    {
-      register const IndexPacket
-        *indexes;
-
-      register const PixelPacket
-        *p;
-
-      image_view=AcquireCacheView(next);
-      p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
-      if (p == (const PixelPacket *) NULL)
-        {
-          image_view=DestroyCacheView(image_view);
-          break;
-        }
-      indexes=GetCacheViewVirtualIndexQueue(image_view);
-      for (x=0; x < (long) next->columns; x++)
-      {
-        SetMagickPixelPacket(next,p,indexes+x,&pixel);
-        average_pixel[x].red+=QuantumScale*pixel.red;
-        average_pixel[x].green+=QuantumScale*pixel.green;
-        average_pixel[x].blue+=QuantumScale*pixel.blue;
-        average_pixel[x].opacity+=QuantumScale*pixel.opacity;
-        if (average_image->colorspace == CMYKColorspace)
-          average_pixel[x].index+=QuantumScale*pixel.index;
-        p++;
-      }
-      image_view=DestroyCacheView(image_view);
-      next=GetNextImageInList(next);
-    }
-    for (x=0; x < (long) average_image->columns; x++)
-    {
-      average_pixel[x].red=(MagickRealType) (QuantumRange*
-        average_pixel[x].red/number_images);
-      average_pixel[x].green=(MagickRealType) (QuantumRange*
-        average_pixel[x].green/number_images);
-      average_pixel[x].blue=(MagickRealType) (QuantumRange*
-        average_pixel[x].blue/number_images);
-      average_pixel[x].opacity=(MagickRealType) (QuantumRange*
-        average_pixel[x].opacity/number_images);
-      if (average_image->colorspace == CMYKColorspace)
-        average_pixel[x].index=(MagickRealType) (QuantumRange*
-          average_pixel[x].index/number_images);
-      SetPixelPacket(average_image,&average_pixel[x],q,average_indexes+x);
-      q++;
-    }
-    if (SyncCacheViewAuthenticPixels(average_view,exception) == MagickFalse)
-      status=MagickFalse;
-    if (images->progress_monitor != (MagickProgressMonitor) NULL)
-      {
-        MagickBooleanType
-          proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-        #pragma omp critical (MagickCore_AverageImages)
-#endif
-        proceed=SetImageProgress(images,AverageImageTag,progress++,
-          average_image->rows);
-        if (proceed == MagickFalse)
-          status=MagickFalse;
-      }
-  }
-  average_view=DestroyCacheView(average_view);
-  average_pixels=DestroyPixelThreadSet(average_pixels);
-  if (status == MagickFalse)
-    average_image=DestroyImage(average_image);
-  return(average_image);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%     E v a l u a t e I m a g e                                               %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  EvaluateImage() applies a value to the image with an arithmetic, relational,
-%  or logical operator to an image. Use these operations to lighten or darken
-%  an image, to increase or decrease contrast in an image, or to produce the
-%  "negative" of an image.
-%
-%  The format of the EvaluateImageChannel method is:
-%
-%      MagickBooleanType EvaluateImage(Image *image,
-%        const MagickEvaluateOperator op,const double value,
-%        ExceptionInfo *exception)
-%      MagickBooleanType EvaluateImageChannel(Image *image,
-%        const ChannelType channel,const MagickEvaluateOperator op,
-%        const double value,ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%    o channel: the channel.
-%
-%    o op: A channel op.
-%
-%    o value: A value value.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-
 static inline double MagickMax(const double x,const double y)
 {
   if (x > y)
@@ -400,8 +189,8 @@ static inline double MagickMin(const double x,const double y)
   return(y);
 }
 
-static Quantum ApplyEvaluateOperator(RandomInfo *random_info,Quantum pixel,
-  const MagickEvaluateOperator op,const MagickRealType value)
+static MagickRealType ApplyEvaluateOperator(RandomInfo *random_info,
+  Quantum pixel,const MagickEvaluateOperator op,const MagickRealType value)
 {
   MagickRealType
     result;
@@ -571,7 +360,7 @@ static Quantum ApplyEvaluateOperator(RandomInfo *random_info,Quantum pixel,
       break;
     }
   }
-  return(ClampToQuantum(result));
+  return(result);
 }
 
 MagickExport MagickBooleanType EvaluateImage(Image *image,
@@ -584,12 +373,199 @@ MagickExport MagickBooleanType EvaluateImage(Image *image,
   return(status);
 }
 
+MagickExport Image *EvaluateImages(const Image *images,
+  const MagickEvaluateOperator op,ExceptionInfo *exception)
+{
+#define EvaluateImageTag  "Evaluate/Image"
+
+  CacheView
+    *evaluate_view;
+
+  const Image
+    *next;
+
+  Image
+    *evaluate_image;
+
+  long
+    progress,
+    y;
+
+  MagickBooleanType
+    status;
+
+  MagickPixelPacket
+    **restrict evaluate_pixels,
+    zero;
+
+  RandomInfo
+    **restrict random_info;
+
+  unsigned long
+    number_images;
+
+  /*
+    Ensure the image are the same size.
+  */
+  assert(images != (Image *) NULL);
+  assert(images->signature == MagickSignature);
+  if (images->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
+    if ((next->columns != images->columns) || (next->rows != images->rows))
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+          "ImageWidthsOrHeightsDiffer","`%s'",images->filename);
+        return((Image *) NULL);
+      }
+  /*
+    Initialize evaluate next attributes.
+  */
+  evaluate_image=CloneImage(images,images->columns,images->rows,MagickTrue,
+    exception);
+  if (evaluate_image == (Image *) NULL)
+    return((Image *) NULL);
+  if (SetImageStorageClass(evaluate_image,DirectClass) == MagickFalse)
+    {
+      InheritException(exception,&evaluate_image->exception);
+      evaluate_image=DestroyImage(evaluate_image);
+      return((Image *) NULL);
+    }
+  evaluate_pixels=AcquirePixelThreadSet(images);
+  if (evaluate_pixels == (MagickPixelPacket **) NULL)
+    {
+      evaluate_image=DestroyImage(evaluate_image);
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
+      return((Image *) NULL);
+    }
+  /*
+    Evaluate image pixels.
+  */
+  status=MagickTrue;
+  progress=0;
+  GetMagickPixelPacket(images,&zero);
+  random_info=AcquireRandomInfoThreadSet();
+  number_images=GetImageListLength(images);
+  evaluate_view=AcquireCacheView(evaluate_image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(dynamic) shared(progress,status)
+#endif
+  for (y=0; y < (long) evaluate_image->rows; y++)
+  {
+    CacheView
+      *image_view;
+
+    const Image
+      *next;
+
+    MagickPixelPacket
+      pixel;
+
+    register IndexPacket
+      *restrict evaluate_indexes;
+
+    register long
+      i,
+      id,
+      x;
+
+    register MagickPixelPacket
+      *evaluate_pixel;
+
+    register PixelPacket
+      *restrict q;
+
+    if (status == MagickFalse)
+      continue;
+    q=QueueCacheViewAuthenticPixels(evaluate_view,0,y,evaluate_image->columns,1,
+      exception);
+    if (q == (PixelPacket *) NULL)
+      {
+        status=MagickFalse;
+        continue;
+      }
+    evaluate_indexes=GetCacheViewAuthenticIndexQueue(evaluate_view);
+    pixel=zero;
+    id=GetOpenMPThreadId();
+    evaluate_pixel=evaluate_pixels[id];
+    for (x=0; x < (long) evaluate_image->columns; x++)
+      evaluate_pixel[x]=zero;
+    next=images;
+    for (i=0; i < (long) number_images; i++)
+    {
+      register const IndexPacket
+        *indexes;
+
+      register const PixelPacket
+        *p;
+
+      image_view=AcquireCacheView(next);
+      p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
+      if (p == (const PixelPacket *) NULL)
+        {
+          image_view=DestroyCacheView(image_view);
+          break;
+        }
+      indexes=GetCacheViewVirtualIndexQueue(image_view);
+      for (x=0; x < (long) next->columns; x++)
+      {
+        evaluate_pixel[x].red=ApplyEvaluateOperator(random_info[id],p->red,
+          op,evaluate_pixel[x].red);
+        evaluate_pixel[x].green=ApplyEvaluateOperator(random_info[id],p->green,
+          op,evaluate_pixel[x].green);
+        evaluate_pixel[x].blue=ApplyEvaluateOperator(random_info[id],p->blue,
+          op,evaluate_pixel[x].blue);
+        evaluate_pixel[x].opacity=ApplyEvaluateOperator(random_info[id],
+          p->opacity,op,evaluate_pixel[x].opacity);
+        if (evaluate_image->colorspace == CMYKColorspace)
+          evaluate_pixel[x].index=ApplyEvaluateOperator(random_info[id],
+            indexes[x],op,evaluate_pixel[x].index);
+        p++;
+      }
+      image_view=DestroyCacheView(image_view);
+      next=GetNextImageInList(next);
+    }
+    for (x=0; x < (long) evaluate_image->columns; x++)
+    {
+      q->red=ClampToQuantum(evaluate_pixel[x].red);
+      q->green=ClampToQuantum(evaluate_pixel[x].green);
+      q->blue=ClampToQuantum(evaluate_pixel[x].blue);
+      q->opacity=ClampToQuantum(evaluate_pixel[x].opacity);
+      if (evaluate_image->colorspace == CMYKColorspace)
+        evaluate_indexes[x]=ClampToQuantum(evaluate_pixel[x].index);
+      q++;
+    }
+    if (SyncCacheViewAuthenticPixels(evaluate_view,exception) == MagickFalse)
+      status=MagickFalse;
+    if (images->progress_monitor != (MagickProgressMonitor) NULL)
+      {
+        MagickBooleanType
+          proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+        #pragma omp critical (MagickCore_EvaluateImages)
+#endif
+        proceed=SetImageProgress(images,EvaluateImageTag,progress++,
+          evaluate_image->rows);
+        if (proceed == MagickFalse)
+          status=MagickFalse;
+      }
+  }
+  evaluate_view=DestroyCacheView(evaluate_view);
+  evaluate_pixels=DestroyPixelThreadSet(evaluate_pixels);
+  random_info=DestroyRandomInfoThreadSet(random_info);
+  if (status == MagickFalse)
+    evaluate_image=DestroyImage(evaluate_image);
+  return(evaluate_image);
+}
+
 MagickExport MagickBooleanType EvaluateImageChannel(Image *image,
   const ChannelType channel,const MagickEvaluateOperator op,const double value,
   ExceptionInfo *exception)
 {
-#define EvaluateImageTag  "Evaluate/Image "
-
   CacheView
     *image_view;
 
@@ -646,23 +622,26 @@ MagickExport MagickBooleanType EvaluateImageChannel(Image *image,
     for (x=0; x < (long) image->columns; x++)
     {
       if ((channel & RedChannel) != 0)
-        q->red=ApplyEvaluateOperator(random_info[id],q->red,op,value);
+        q->red=ClampToQuantum(ApplyEvaluateOperator(random_info[id],q->red,op,
+          value));
       if ((channel & GreenChannel) != 0)
-        q->green=ApplyEvaluateOperator(random_info[id],q->green,op,value);
+        q->green=ClampToQuantum(ApplyEvaluateOperator(random_info[id],q->green,
+          op,value));
       if ((channel & BlueChannel) != 0)
-        q->blue=ApplyEvaluateOperator(random_info[id],q->blue,op,value);
+        q->blue=ClampToQuantum(ApplyEvaluateOperator(random_info[id],q->blue,op,
+          value));
       if ((channel & OpacityChannel) != 0)
         {
           if (image->matte == MagickFalse)
-            q->opacity=ApplyEvaluateOperator(random_info[id],q->opacity,op,
-              value);
+            q->opacity=ClampToQuantum(ApplyEvaluateOperator(random_info[id],
+              q->opacity,op,value));
           else
-            q->opacity=(Quantum) QuantumRange-ApplyEvaluateOperator(
-              random_info[id],(Quantum) GetAlphaPixelComponent(q),op,value);
+            q->opacity=ClampToQuantum(QuantumRange-ApplyEvaluateOperator(
+              random_info[id],(Quantum) GetAlphaPixelComponent(q),op,value));
         }
       if (((channel & IndexChannel) != 0) && (indexes != (IndexPacket *) NULL))
-        indexes[x]=(IndexPacket) ApplyEvaluateOperator(random_info[id],
-          indexes[x],op,value);
+        indexes[x]=(IndexPacket) ClampToQuantum(ApplyEvaluateOperator(
+          random_info[id],indexes[x],op,value));
       q++;
     }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -1683,201 +1662,3 @@ MagickExport ChannelStatistics *GetImageChannelStatistics(const Image *image,
   }
   return(channel_statistics);
 }
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%     M a x i m u m I m a g e s                                               %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  MaximumImages() returns the maximum intensity of an image sequence.
-%
-%  The format of the MaxImages method is:
-%
-%      Image *MaximumImages(Image *images,ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o images: the image sequence.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport Image *MaximumImages(const Image *images,ExceptionInfo *exception)
-{
-#define MaximumImageTag  "Maximum/Image"
-
-  const Image
-    *next;
-
-  Image
-    *maximum_image;
-
-  MagickBooleanType
-    status;
-
-  register long
-    i;
-
-  unsigned long
-    number_images;
-
-  /*
-    Ensure the image are the same size.
-  */
-  assert(images != (Image *) NULL);
-  assert(images->signature == MagickSignature);
-  if (images->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
-    if ((next->columns != images->columns) || (next->rows != images->rows))
-      {
-        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-          "ImageWidthsOrHeightsDiffer","`%s'",images->filename);
-        return((Image *) NULL);
-      }
-  /*
-    Initialize maximum itensity image.
-  */
-  maximum_image=CloneImage(images,0,0,MagickTrue,exception);
-  if (maximum_image == (Image *) NULL)
-    return((Image *) NULL);
-  if (SetImageStorageClass(maximum_image,DirectClass) == MagickFalse)
-    {
-      InheritException(exception,&maximum_image->exception);
-      maximum_image=DestroyImage(maximum_image);
-      return((Image *) NULL);
-    }
-  /*
-    Compute the maximum intensity of an image sequence.
-  */
-  i=0;
-  number_images=GetImageListLength(images);
-  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
-  {
-    status=CompositeImage(maximum_image,LightenCompositeOp,next,0,0);
-    if (status == MagickFalse)
-      {
-        InheritException(exception,&maximum_image->exception);
-        maximum_image=DestroyImage(maximum_image);
-        break;
-      }
-    if (images->progress_monitor != (MagickProgressMonitor) NULL)
-      {
-        MagickBooleanType
-          proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-        #pragma omp critical (MagickCore_MaximumImages)
-#endif
-        proceed=SetImageProgress(images,MaximumImageTag,i++,number_images);
-      }
-  }
-  return(maximum_image);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%     M i n i m u m I m a g e s                                               %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  MinimumImages() returns the minimum intensity of an image sequence.
-%
-%  The format of the MinimumImages method is:
-%
-%      Image *MinimumImages(Image *images,ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o images: the image sequence.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport Image *MinimumImages(const Image *images,ExceptionInfo *exception)
-{
-#define MinimumImageTag  "Minimum/Image"
-
-  const Image
-    *next;
-
-  Image
-    *minimum_image;
-
-  MagickBooleanType
-    status;
-
-  register long
-    i;
-
-  unsigned long
-    number_images;
-
-  /*
-    Ensure the image are the same size.
-  */
-  assert(images != (Image *) NULL);
-  assert(images->signature == MagickSignature);
-  if (images->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
-    if ((next->columns != images->columns) || (next->rows != images->rows))
-      {
-        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-          "ImageWidthsOrHeightsDiffer","`%s'",images->filename);
-        return((Image *) NULL);
-      }
-  /*
-    Initialize minimum intensity image.
-  */
-  minimum_image=CloneImage(images,0,0,MagickTrue,exception);
-  if (minimum_image == (Image *) NULL)
-    return((Image *) NULL);
-  if (SetImageStorageClass(minimum_image,DirectClass) == MagickFalse)
-    {
-      InheritException(exception,&minimum_image->exception);
-      minimum_image=DestroyImage(minimum_image);
-      return((Image *) NULL);
-    }
-  /*
-    Compute the minimum intensity of an image sequence.
-  */
-  i=0;
-  number_images=GetImageListLength(images);
-  for (next=images; next != (Image *) NULL; next=GetNextImageInList(next))
-  {
-    status=CompositeImage(minimum_image,DarkenCompositeOp,next,0,0);
-    if (status == MagickFalse)
-      {
-        InheritException(exception,&minimum_image->exception);
-        minimum_image=DestroyImage(minimum_image);
-        break;
-      }
-    if (images->progress_monitor != (MagickProgressMonitor) NULL)
-      {
-        MagickBooleanType
-          proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-        #pragma omp critical (MagickCore_MaxImages)
-#endif
-        proceed=SetImageProgress(images,MinimumImageTag,i++,number_images);
-      }
-  }
-  return(minimum_image);
-}
index b896e76a660891d6a2e44a312c5ec48331f0e16e..580e9feafc7a7a910d9f7417993a3c65b9f7144b 100644 (file)
@@ -80,9 +80,7 @@ extern MagickExport ChannelStatistics
   *GetImageChannelStatistics(const Image *,ExceptionInfo *);
 
 extern MagickExport Image
-  *AverageImages(const Image *,ExceptionInfo *),
-  *MaximumImages(const Image *,ExceptionInfo *),
-  *MinimumImages(const Image *,ExceptionInfo *);
+  *EvaluateImages(const Image *,const MagickEvaluateOperator,ExceptionInfo *);
 
 extern MagickExport MagickBooleanType
   EvaluateImage(Image *,const MagickEvaluateOperator,const double,
index 617533866852c01326fd8ac5f46a273edd41e689..fbac6254140e41e746e1db7d91c28c4aba9586e6 100644 (file)
@@ -221,18 +221,17 @@ Image Operators:
 Image Sequence Operators:
   \-affinity filename   transform image colors to match this set of colors
   \-append              append an image sequence
-  \-average             average an image sequence
   \-clut                apply a color lookup table to the image
   \-coalesce            merge a sequence of images
   \-combine             combine a sequence of images
   \-composite           composite image
   \-crop geometry       cut out a rectangular region of the image
   \-deconstruct         break down an image sequence into constituent parts
+  \-evaluate-sequence operator
+                       evaluate an arithmetic, relational, or logical expression
   \-flatten             flatten a sequence of images
   \-fx expression       apply mathematical expression to an image channel(s)
   \-hald-clut           apply a Hald color lookup table to the image
-  \-maximum             the maximum intensity of an image sequence
-  \-minimum             the minimum intensity of an image sequence
   \-morph value         morph an image sequence
   \-mosaic              create a mosaic from an image sequence
   \-process arguments   process the image with a custom image filter
index f978f25203fbe5ecb175c7c7e57a6f73cafa4e92..e47dd8d624af97b50134f5a1f0c53867ab1e5595 100644 (file)
@@ -223,18 +223,17 @@ Image Operators:
 Image Sequence Operators:
   \-affinity filename   transform image colors to match this set of colors
   \-append              append an image sequence
-  \-average             average an image sequence
   \-clut                apply a color lookup table to the image
   \-coalesce            merge a sequence of images
   \-combine             combine a sequence of images
   \-composite           composite image
   \-crop geometry       cut out a rectangular region of the image
   \-deconstruct         break down an image sequence into constituent parts
+  \-evaluate-sequence operator
+                       evaluate an arithmetic, relational, or logical expression
   \-flatten             flatten a sequence of images
   \-fx expression       apply mathematical expression to an image channel(s)
   \-hald-clut           apply a Hald color lookup table to the image
-  \-maximum             the maximum intensity of an image sequence
-  \-minimum             the minimum intensity of an image sequence
   \-morph value         morph an image sequence
   \-mosaic              create a mosaic from an image sequence
   \-process arguments   process the image with a custom image filter
index 4eeea668ac48f5a97ba4319e7b3a437f88a93d4f..3f1d4e2ffcbcaefc3f9598f519e6c0c60617c72b 100644 (file)
@@ -189,7 +189,7 @@ static MagickBooleanType ConvertUsage(void)
       "-enhance             apply a digital filter to enhance a noisy image",
       "-equalize            perform histogram equalization to an image",
       "-evaluate operator value",
-      "                     evaluate an expression over image values",
+      "                     evaluate an arithmetic, relational, or logical expression",
       "-extent geometry     set the image size",
       "-extract geometry    extract area from image",
       "-fft                 implements the discrete Fourier transform (DFT)",
@@ -292,18 +292,17 @@ static MagickBooleanType ConvertUsage(void)
     *sequence_operators[]=
     {
       "-append              append an image sequence",
-      "-average             average an image sequence",
       "-clut                apply a color lookup table to the image",
       "-coalesce            merge a sequence of images",
       "-combine             combine a sequence of images",
       "-composite           composite image",
       "-crop geometry       cut out a rectangular region of the image",
       "-deconstruct         break down an image sequence into constituent parts",
+      "-evaluate-sequence operator",
+      "                     evaluate an arithmetic, relational, or logical expression",
       "-flatten             flatten a sequence of images",
       "-fx expression       apply mathematical expression to an image channel(s)",
       "-hald-clut           apply a Hald color lookup table to the image",
-      "-max                 return the maximum intensity of an image sequence",
-      "-min                 return the minimum intensity of an image sequence",
       "-morph value         morph an image sequence",
       "-mosaic              create a mosaic from an image sequence",
       "-process arguments   process the image with a custom image filter",
@@ -1358,6 +1357,22 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info,
               ThrowConvertInvalidArgumentException(option,argv[i]);
             break;
           }
+        if (LocaleCompare("evaluate-sequence",option+1) == 0)
+          {
+            long
+              op;
+
+            if (*option == '+')
+              break;
+            i++;
+            if (i == (long) argc)
+              ThrowConvertException(OptionError,"MissingArgument",option);
+            op=ParseMagickOption(MagickEvaluateOptions,MagickFalse,argv[i]);
+            if (op < 0)
+              ThrowConvertException(OptionError,"UnrecognizedEvaluateOperator",
+                argv[i]);
+            break;
+          }
         if (LocaleCompare("extent",option+1) == 0)
           {
             if (*option == '+')
index 7f43fb5ae3b0e6c2dcb639ee0e350343ab797c16..4bd5f29751f1d4a36af52f11eb3b327b3241276e 100644 (file)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   M a g i c k A v e r a g e I m a g e s                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MagickAverageImages() average a set of images.
+%
+%  The format of the MagickAverageImages method is:
+%
+%      MagickWand *MagickAverageImages(MagickWand *wand)
+%
+%  A description of each parameter follows:
+%
+%    o wand: the magick wand.
+%
+*/
+
+static MagickWand *CloneMagickWandFromImages(const MagickWand *wand,
+  Image *images)
+{
+  MagickWand
+    *clone_wand;
+
+  assert(wand != (MagickWand *) NULL);
+  assert(wand->signature == WandSignature);
+  if (wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  clone_wand=(MagickWand *) AcquireAlignedMemory(1,sizeof(*clone_wand));
+  if (clone_wand == (MagickWand *) NULL)
+    ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
+      images->filename);
+  (void) ResetMagickMemory(clone_wand,0,sizeof(*clone_wand));
+  clone_wand->id=AcquireWandId();
+  (void) FormatMagickString(clone_wand->name,MaxTextExtent,"%s-%lu",
+    MagickWandId,clone_wand->id);
+  clone_wand->exception=AcquireExceptionInfo();
+  InheritException(clone_wand->exception,wand->exception);
+  clone_wand->image_info=CloneImageInfo(wand->image_info);
+  clone_wand->quantize_info=CloneQuantizeInfo(wand->quantize_info);
+  clone_wand->images=images;
+  clone_wand->debug=IsEventLogging();
+  if (clone_wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_wand->name);
+  clone_wand->signature=WandSignature;
+  return(clone_wand);
+}
+
+WandExport MagickWand *MagickAverageImages(MagickWand *wand)
+{
+  Image
+    *average_image;
+
+  assert(wand != (MagickWand *) NULL);
+  assert(wand->signature == WandSignature);
+  if (wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  if (wand->images == (Image *) NULL)
+    return((MagickWand *) NULL);
+  average_image=EvaluateImages(wand->images,MeanEvaluateOperator,
+    wand->exception);
+  if (average_image == (Image *) NULL)
+    return((MagickWand *) NULL);
+  return(CloneMagickWandFromImages(wand,average_image));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   M a g i c k C l i p P a t h I m a g e                                     %
 %                                                                             %
 %                                                                             %
@@ -419,37 +490,6 @@ WandExport char *MagickDescribeImage(MagickWand *wand)
 %    o wand: the magick wand.
 %
 */
-
-static MagickWand *CloneMagickWandFromImages(const MagickWand *wand,
-  Image *images)
-{
-  MagickWand
-    *clone_wand;
-
-  assert(wand != (MagickWand *) NULL);
-  assert(wand->signature == WandSignature);
-  if (wand->debug != MagickFalse)
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
-  clone_wand=(MagickWand *) AcquireAlignedMemory(1,sizeof(*clone_wand));
-  if (clone_wand == (MagickWand *) NULL)
-    ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
-      images->filename);
-  (void) ResetMagickMemory(clone_wand,0,sizeof(*clone_wand));
-  clone_wand->id=AcquireWandId();
-  (void) FormatMagickString(clone_wand->name,MaxTextExtent,"%s-%lu",
-    MagickWandId,clone_wand->id);
-  clone_wand->exception=AcquireExceptionInfo();
-  InheritException(clone_wand->exception,wand->exception);
-  clone_wand->image_info=CloneImageInfo(wand->image_info);
-  clone_wand->quantize_info=CloneQuantizeInfo(wand->quantize_info);
-  clone_wand->images=images;
-  clone_wand->debug=IsEventLogging();
-  if (clone_wand->debug != MagickFalse)
-    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_wand->name);
-  clone_wand->signature=WandSignature;
-  return(clone_wand);
-}
-
 WandExport MagickWand *MagickFlattenImages(MagickWand *wand)
 {
   Image
@@ -871,6 +911,86 @@ WandExport MagickBooleanType MagickMatteFloodfillImage(MagickWand *wand,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   M a g i c k M a x i m u m I m a g e s                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MagickMaximumImages() returns the maximum intensity of an image sequence.
+%
+%  The format of the MagickMaximumImages method is:
+%
+%      MagickWand *MagickMaximumImages(MagickWand *wand)
+%
+%  A description of each parameter follows:
+%
+%    o wand: the magick wand.
+%
+*/
+WandExport MagickWand *MagickMaximumImages(MagickWand *wand)
+{
+  Image
+    *maximum_image;
+
+  assert(wand != (MagickWand *) NULL);
+  assert(wand->signature == WandSignature);
+  if (wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  if (wand->images == (Image *) NULL)
+    return((MagickWand *) NULL);
+  maximum_image=EvaluateImages(wand->images,MaxEvaluateOperator,
+    wand->exception);
+  if (maximum_image == (Image *) NULL)
+    return((MagickWand *) NULL);
+  return(CloneMagickWandFromImages(wand,maximum_image));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   M a g i c k M i n i m u m I m a g e s                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MagickMinimumImages() returns the minimum intensity of an image sequence.
+%
+%  The format of the MagickMinimumImages method is:
+%
+%      MagickWand *MagickMinimumImages(MagickWand *wand)
+%
+%  A description of each parameter follows:
+%
+%    o wand: the magick wand.
+%
+*/
+WandExport MagickWand *MagickMinimumImages(MagickWand *wand)
+{
+  Image
+    *minimum_image;
+
+  assert(wand != (MagickWand *) NULL);
+  assert(wand->signature == WandSignature);
+  if (wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  if (wand->images == (Image *) NULL)
+    return((MagickWand *) NULL);
+  minimum_image=EvaluateImages(wand->images,MinEvaluateOperator,
+    wand->exception);
+  if (minimum_image == (Image *) NULL)
+    return((MagickWand *) NULL);
+  return(CloneMagickWandFromImages(wand,minimum_image));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   M a g i c k M o s a i c I m a g e s                                       %
 %                                                                             %
 %                                                                             %
index 24888b91750b724e9190a109ef601fe1f257a641..7568f284fa679b92a0c99784e21dccaad57a43f0 100644 (file)
@@ -90,7 +90,10 @@ extern WandExport MagickBooleanType
     const double) magick_attribute((deprecated));
 
 extern WandExport MagickWand
+  *MagickAverageImages(MagickWand *),
   *MagickFlattenImages(MagickWand *) magick_attribute((deprecated)),
+  *MagickMaximumImages(MagickWand *),
+  *MagickMinimumImages(MagickWand *),
   *MagickMosaicImages(MagickWand *) magick_attribute((deprecated)),
   *MagickRegionOfInterestImage(MagickWand *,const unsigned long,
     const unsigned long,const long,const long) magick_attribute((deprecated));
index 22dfe7c98f87f3874aff6204fbb57c4734e831ad..ad0aa48c8100b7299e68ac1805b0f5c19902c452 100644 (file)
@@ -2994,6 +2994,8 @@ WandExport MagickBooleanType MagickEqualizeImageChannel(MagickWand *wand,
 %
 %      MagickBooleanType MagickEvaluateImage(MagickWand *wand,
 %        const MagickEvaluateOperator operator,const double value)
+%      MagickBooleanType MagickEvaluateImages(MagickWand *wand,
+%        const MagickEvaluateOperator operator)
 %      MagickBooleanType MagickEvaluateImageChannel(MagickWand *wand,
 %        const ChannelType channel,const MagickEvaluateOperator op,
 %        const double value)
@@ -3028,6 +3030,24 @@ WandExport MagickBooleanType MagickEvaluateImage(MagickWand *wand,
   return(status);
 }
 
+WandExport MagickWand *MagickEvaluateImages(MagickWand *wand,
+  const MagickEvaluateOperator op)
+{
+  Image
+    *evaluate_image;
+
+  assert(wand != (MagickWand *) NULL);
+  assert(wand->signature == WandSignature);
+  if (wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  if (wand->images == (Image *) NULL)
+    return((MagickWand *) NULL);
+  evaluate_image=EvaluateImages(wand->images,op,wand->exception);
+  if (evaluate_image == (Image *) NULL)
+    return((MagickWand *) NULL);
+  return(CloneMagickWandFromImages(wand,evaluate_image));
+}
+
 WandExport MagickBooleanType MagickEvaluateImageChannel(MagickWand *wand,
   const ChannelType channel,const MagickEvaluateOperator op,const double value)
 {
index 6a80ecfc9c11798430a37b4bc410bffc658e31e8..c279c7ee7879ab1a20fdda04f12661d1efb5c56e 100644 (file)
@@ -371,7 +371,6 @@ WandExport MagickProgressMonitor
 
 extern WandExport MagickWand
   *MagickAppendImages(MagickWand *,const MagickBooleanType),
-  *MagickAverageImages(MagickWand *),
   *MagickCoalesceImages(MagickWand *),
   *MagickCombineImages(MagickWand *,const ChannelType),
   *MagickCompareImageChannels(MagickWand *,const MagickWand *,const ChannelType,
@@ -380,14 +379,13 @@ extern WandExport MagickWand
     double *),
   *MagickCompareImageLayers(MagickWand *,const ImageLayerMethod),
   *MagickDeconstructImages(MagickWand *),
+  *MagickEvaluateImages(MagickWand *,const MagickEvaluateOperator),
   *MagickFxImage(MagickWand *,const char *),
   *MagickFxImageChannel(MagickWand *,const ChannelType,const char *),
   *MagickGetImage(MagickWand *),
   *MagickGetImageClipMask(MagickWand *),
   *MagickGetImageRegion(MagickWand *,const unsigned long,const unsigned long,
     const long,const long),
-  *MagickMaximumImages(MagickWand *),
-  *MagickMinimumImages(MagickWand *),
   *MagickMergeImageLayers(MagickWand *,const ImageLayerMethod),
   *MagickMorphImages(MagickWand *,const unsigned long),
   *MagickMontageImage(MagickWand *,const DrawingWand *,const char *,
index a0b32fd91868178e466f9fbed503809a210f0ac7..10a8f1cf7d3de075f786d6eaa389388301ef5384 100644 (file)
@@ -3696,7 +3696,7 @@ static MagickBooleanType MogrifyUsage(void)
       "-enhance             apply a digital filter to enhance a noisy image",
       "-equalize            perform histogram equalization to an image",
       "-evaluate operator value",
-      "                     evaluate an expression over image values",
+      "                     evaluate an arithmetic, relational, or logical expression",
       "-extent geometry     set the image size",
       "-extract geometry    extract area from image",
       "-fft                 implements the discrete Fourier transform (DFT)",
@@ -3799,18 +3799,17 @@ static MagickBooleanType MogrifyUsage(void)
     *sequence_operators[]=
     {
       "-append              append an image sequence",
-      "-average             average an image sequence",
       "-clut                apply a color lookup table to the image",
       "-coalesce            merge a sequence of images",
       "-combine             combine a sequence of images",
       "-composite           composite image",
       "-crop geometry       cut out a rectangular region of the image",
       "-deconstruct         break down an image sequence into constituent parts",
+      "-evaluate-sequence operator",
+      "                     evaluate an arithmetic, relational, or logical expression",
       "-flatten             flatten a sequence of images",
       "-fx expression       apply mathematical expression to an image channel(s)",
       "-hald-clut           apply a Hald color lookup table to the image",
-      "-maximum             return the maximum intensity of an image sequence",
-      "-minimum             return the minimum intensity of an image sequence",
       "-morph value         morph an image sequence",
       "-mosaic              create a mosaic from an image sequence",
       "-process arguments   process the image with a custom image filter",
@@ -4840,6 +4839,22 @@ WandExport MagickBooleanType MogrifyImageCommand(ImageInfo *image_info,
               ThrowMogrifyInvalidArgumentException(option,argv[i]);
             break;
           }
+        if (LocaleCompare("evaluate-sequence",option+1) == 0)
+          {
+            long
+              op;
+
+            if (*option == '+')
+              break;
+            i++;
+            if (i == (long) argc)
+              ThrowMogrifyException(OptionError,"MissingArgument",option);
+            op=ParseMagickOption(MagickEvaluateOptions,MagickFalse,argv[i]);
+            if (op < 0)
+              ThrowMogrifyException(OptionError,"UnrecognizedEvaluateOperator",
+                argv[i]);
+            break;
+          }
         if (LocaleCompare("extent",option+1) == 0)
           {
             if (*option == '+')
@@ -7582,8 +7597,12 @@ WandExport MagickBooleanType MogrifyImageList(ImageInfo *image_info,
             Image
               *average_image;
 
+            /*
+              Average an image sequence (deprecated).
+            */
             (void) SyncImagesSettings(image_info,*images);
-            average_image=AverageImages(*images,exception);
+            average_image=EvaluateImages(*images,MeanEvaluateOperator,
+              exception);
             if (average_image == (Image *) NULL)
               {
                 status=MagickFalse;
@@ -7775,6 +7794,31 @@ WandExport MagickBooleanType MogrifyImageList(ImageInfo *image_info,
           }
         break;
       }
+      case 'e':
+      {
+        if (LocaleCompare("evaluate-sequence",option+1) == 0)
+          {
+            Image
+              *evaluate_image;
+
+            MagickEvaluateOperator
+              op;
+
+            (void) SyncImageSettings(image_info,*images);
+            op=(MagickEvaluateOperator) ParseMagickOption(MagickEvaluateOptions,
+              MagickFalse,argv[i+1]);
+            evaluate_image=EvaluateImages(*images,op,exception);
+            if (evaluate_image == (Image *) NULL)
+              {
+                status=MagickFalse;
+                break;
+              }
+            *images=DestroyImageList(*images);
+            *images=evaluate_image;
+            break;
+          }
+        break;
+      }
       case 'f':
       {
         if (LocaleCompare("fft",option+1) == 0)
@@ -8111,8 +8155,11 @@ WandExport MagickBooleanType MogrifyImageList(ImageInfo *image_info,
             Image
               *maximum_image;
 
+            /*
+              Maximum image sequence (deprecated).
+            */
             (void) SyncImagesSettings(image_info,*images);
-            maximum_image=MaximumImages(*images,exception);
+            maximum_image=EvaluateImages(*images,MaxEvaluateOperator,exception);
             if (maximum_image == (Image *) NULL)
               {
                 status=MagickFalse;
@@ -8127,8 +8174,11 @@ WandExport MagickBooleanType MogrifyImageList(ImageInfo *image_info,
             Image
               *minimum_image;
 
+            /*
+              Minimum image sequence (deprecated).
+            */
             (void) SyncImagesSettings(image_info,*images);
-            minimum_image=MinimumImages(*images,exception);
+            minimum_image=EvaluateImages(*images,MinEvaluateOperator,exception);
             if (minimum_image == (Image *) NULL)
               {
                 status=MagickFalse;