diff --git a/magick/effect.c b/magick/effect.c
index 92334cb..7fbcd8c 100644
--- a/magick/effect.c
+++ b/magick/effect.c
@@ -5453,6 +5453,211 @@
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%     S t a t i s t i c I m a g e                                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  StatisticImage() makes each pixel the min / max / median / mode / etc. of
+%  the neighborhood of the specified radius.
+%
+%  The format of the StatisticImage method is:
+%
+%      Image *StatisticImage(const Image *image,const StatisticType type,
+%        const double radius,ExceptionInfo *exception)
+%      Image *StatisticImageChannel(const Image *image,
+%        const ChannelType channel,const StatisticType type,
+%        const double radius,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o channel: the image channel.
+%
+%    o type: the statistic type (median, mode, etc.).
+%
+%    o radius: the radius of the pixel neighborhood.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+MagickExport Image *StatisticImage(const Image *image,const StatisticType type,
+  const double radius,ExceptionInfo *exception)
+{
+  return(StatisticImageChannel(image,DefaultChannels,type,radius,exception));
+}
+
+MagickExport Image *StatisticImageChannel(const Image *image,
+  const ChannelType channel,const StatisticType type,const double radius,
+  ExceptionInfo *exception)
+{
+#define StatisticImageTag  "Statistic/Image"
+
+  CacheView
+    *image_view,
+    *statistic_view;
+
+  Image
+    *statistic_image;
+
+  MagickBooleanType
+    status;
+
+  MagickOffsetType
+    progress;
+
+  PixelList
+    **restrict pixel_list;
+
+  size_t
+    width;
+
+  ssize_t
+    y;
+
+  /*
+    Initialize statistics image attributes.
+  */
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  width=GetOptimalKernelWidth2D(radius,0.5);
+  statistic_image=CloneImage(image,image->columns,image->rows,MagickTrue,
+    exception);
+  if (statistic_image == (Image *) NULL)
+    return((Image *) NULL);
+  if (SetImageStorageClass(statistic_image,DirectClass) == MagickFalse)
+    {
+      InheritException(exception,&statistic_image->exception);
+      statistic_image=DestroyImage(statistic_image);
+      return((Image *) NULL);
+    }
+  pixel_list=AcquirePixelListThreadSet(width);
+  if (pixel_list == (PixelList **) NULL)
+    {
+      statistic_image=DestroyImage(statistic_image);
+      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
+    }
+  /*
+    Reduce statistics image.
+  */
+  status=MagickTrue;
+  progress=0;
+  image_view=AcquireCacheView(image);
+  statistic_view=AcquireCacheView(statistic_image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+#endif
+  for (y=0; y < (ssize_t) statistic_image->rows; y++)
+  {
+    const int
+      id = GetOpenMPThreadId();
+
+    register const IndexPacket
+      *restrict indexes;
+
+    register const PixelPacket
+      *restrict p;
+
+    register IndexPacket
+      *restrict statistic_indexes;
+
+    register PixelPacket
+      *restrict q;
+
+    register ssize_t
+      x;
+
+    if (status == MagickFalse)
+      continue;
+    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
+      (width/2L),image->columns+width,width,exception);
+    q=QueueCacheViewAuthenticPixels(statistic_view,0,y,
+      statistic_image->columns,1,exception);
+    if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
+      {
+        status=MagickFalse;
+        continue;
+      }
+    indexes=GetCacheViewVirtualIndexQueue(image_view);
+    statistic_indexes=GetCacheViewAuthenticIndexQueue(statistic_view);
+    for (x=0; x < (ssize_t) statistic_image->columns; x++)
+    {
+      MagickPixelPacket
+        pixel;
+
+      register const PixelPacket
+        *restrict r;
+
+      register const IndexPacket
+        *restrict s;
+
+      register ssize_t
+        u,
+        v;
+
+      r=p;
+      s=indexes+x;
+      ResetPixelList(pixel_list[id]);
+      for (v=0; v < (ssize_t) width; v++)
+      {
+        for (u=0; u < (ssize_t) width; u++)
+          InsertPixelList(image,r+u,s+u,pixel_list[id]);
+        r+=image->columns+width;
+        s+=image->columns+width;
+      }
+      switch (type)
+      {
+        case ModeStatistic: pixel=GetModePixelList(pixel_list[id]);
+        default: break;
+      }
+      if ((channel & RedChannel) != 0)
+        q->red=ClampToQuantum(pixel.red);
+      if ((channel & GreenChannel) != 0)
+        q->green=ClampToQuantum(pixel.green);
+      if ((channel & BlueChannel) != 0)
+        q->blue=ClampToQuantum(pixel.blue);
+      if ((image->matte != MagickFalse) && ((channel & OpacityChannel) != 0))
+        q->opacity=ClampToQuantum(pixel.opacity);
+      if (((channel & IndexChannel) != 0) &&
+          (image->colorspace == CMYKColorspace))
+        statistic_indexes[x]=(IndexPacket) ClampToQuantum(pixel.index);
+      p++;
+      q++;
+    }
+    if (SyncCacheViewAuthenticPixels(statistic_view,exception) == MagickFalse)
+      status=MagickFalse;
+    if (image->progress_monitor != (MagickProgressMonitor) NULL)
+      {
+        MagickBooleanType
+          proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp critical (MagickCore_StatisticImage)
+#endif
+        proceed=SetImageProgress(image,StatisticImageTag,progress++,
+          image->rows);
+        if (proceed == MagickFalse)
+          status=MagickFalse;
+      }
+  }
+  statistic_view=DestroyCacheView(statistic_view);
+  image_view=DestroyCacheView(image_view);
+  pixel_list=DestroyPixelListThreadSet(pixel_list);
+  return(statistic_image);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %     U n s h a r p M a s k I m a g e                                         %
 %                                                                             %
 %                                                                             %