]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Mon, 11 Jan 2010 20:03:47 +0000 (20:03 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Mon, 11 Jan 2010 20:03:47 +0000 (20:03 +0000)
ChangeLog
PerlMagick/Magick.xs
magick/enhance.c
magick/enhance.h
magick/option.c
wand/convert.c
wand/magick-image.c
wand/magick-image.h
wand/mogrify.c

index 7fbe13d69e18d7c3d1a39d59a48fb43ad4f8cf60..65d1d035d76445b89e565aca40871a4eef204f76 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@
   * Support heterogeneous distributed processing, see
     http://www.imagemagick.org/script/architecture.php#distributed.
   * Fix semaphore assertion when reading a corrupt image with Magick++.
+  * Add support for -brightness-contrast option.
 
 2010-01-05  6.5.9-0 Stephan Menzel  <stephan.menzel@gmail...>
   * Add support for the BGRA raw image format.
index 569897f8d79b0b3a72063597cbbc5ff8242adbc5..57d5e648a8566f9d70f704907edb9497eb8e5f85 100644 (file)
@@ -90,9 +90,6 @@ extern "C" {
 #define PerlIO_importFILE(f, fl)  (f)
 #define PerlIO_findFILE(f)  NULL
 #endif
-#define RoundToQuantum(value)  ((Quantum) ((value) < 0.0 ? 0.0 : \
-  ((value) > (MagickRealType) QuantumRange) ? (MagickRealType) \
-  QuantumRange : (value)+0.5))
 #ifndef sv_undef
 #define sv_undef  PL_sv_undef
 #endif
@@ -524,6 +521,9 @@ static struct
     { "Clamp", { {"channel", MagickChannelOptions} } },
     { "Filter", { {"kernel", StringReference},
       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
+    { "BrightnessContrast", { {"levels", StringReference},
+      {"brightness", RealReference},{"contrast", RealReference},
+      {"channel", MagickChannelOptions} } },
   };
 
 static SplayTreeInfo
@@ -1243,9 +1243,9 @@ static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
                 pixel.red=geometry_info.rho;
                 pixel.green=geometry_info.sigma;
                 pixel.blue=geometry_info.xi;
-                color->red=RoundToQuantum(pixel.red);
-                color->green=RoundToQuantum(pixel.green);
-                color->blue=RoundToQuantum(pixel.blue);
+                color->red=ClampToQuantum(pixel.red);
+                color->green=ClampToQuantum(pixel.green);
+                color->blue=ClampToQuantum(pixel.blue);
               }
           }
           break;
@@ -1817,14 +1817,14 @@ static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
                     if ((flags & ChiValue) != 0)
                       pixel.index=geometry_info.chi;
                   }
-                p->red=RoundToQuantum(pixel.red);
-                p->green=RoundToQuantum(pixel.green);
-                p->blue=RoundToQuantum(pixel.blue);
-                p->opacity=RoundToQuantum(pixel.opacity);
+                p->red=ClampToQuantum(pixel.red);
+                p->green=ClampToQuantum(pixel.green);
+                p->blue=ClampToQuantum(pixel.blue);
+                p->opacity=ClampToQuantum(pixel.opacity);
                 if (((image->colorspace == CMYKColorspace) ||
                      (image->storage_class == PseudoClass)) &&
                     (indexes != (IndexPacket *) NULL))
-                  *indexes=RoundToQuantum(pixel.index);
+                  *indexes=ClampToQuantum(pixel.index);
                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
               }
             image_view=DestroyCacheView(image_view);
@@ -6838,6 +6838,8 @@ Mogrify(ref,...)
     ClampImage         = 260
     Filter             = 261
     FilterImage        = 262
+    BrightnessContrast = 263
+    BrightnessContrastImage = 264
     MogrifyRegion      = 666
   PPCODE:
   {
@@ -7843,7 +7845,7 @@ Mogrify(ref,...)
                     for (x=0; x < (long) composite_image->columns; x++)
                     {
                       if (q->opacity == OpaqueOpacity)
-                        q->opacity=RoundToQuantum(opacity);
+                        q->opacity=ClampToQuantum(opacity);
                       q++;
                     }
                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
@@ -8586,7 +8588,7 @@ Mogrify(ref,...)
           invert=MagickFalse;
           if (attribute_flag[3] != 0)
             invert=(MagickBooleanType) argument_list[3].long_reference;
-          (void) TransparentPaintImage(image,&target,RoundToQuantum(opacity),
+          (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
             invert);
           break;
         }
@@ -8862,8 +8864,8 @@ Mogrify(ref,...)
             geometry_info.xi=argument_list[3].real_reference;
           if (attribute_flag[4] != 0)
             channel=(ChannelType) argument_list[4].long_reference;
-          image=MotionBlurImageChannel(image,channel,geometry_info.rho,geometry_info.sigma,
-            geometry_info.xi,exception);
+          image=MotionBlurImageChannel(image,channel,geometry_info.rho,
+            geometry_info.sigma,geometry_info.xi,exception);
           break;
         }
         case 71:  /* OrderedDither */
@@ -10071,6 +10073,32 @@ Mogrify(ref,...)
           kernel=DestroyKernel(kernel);
           break;
         }
+        case 132:  /* BrightnessContrast */
+        {
+          double
+            brightness,
+            contrast;
+
+          brightness=0.0;
+          contrast=0.0;
+          if (attribute_flag[0] != 0)
+            {
+              flags=ParseGeometry(argument_list[0].string_reference,
+                &geometry_info);
+              brightness=geometry_info.rho;
+              if ((flags & SigmaValue) == 0)
+                contrast=geometry_info.sigma;
+            }
+          if (attribute_flag[1] != 0)
+            brightness=argument_list[1].real_reference;
+          if (attribute_flag[2] != 0)
+            contrast=argument_list[2].real_reference;
+          if (attribute_flag[4] != 0)
+            channel=(ChannelType) argument_list[4].long_reference;
+          (void) BrightnessContrastImageChannel(image,channel,brightness,
+            contrast);
+          break;
+        }
       }
       if (next != (Image *) NULL)
         (void) CatchImageException(next);
@@ -12771,28 +12799,28 @@ SetPixel(ref,...)
           scale=QuantumRange;
         if (((channel & RedChannel) != 0) && (i <= av_len(av)))
           {
-            q->red=RoundToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
+            q->red=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
             i++;
           }
         if (((channel & GreenChannel) != 0) && (i <= av_len(av)))
           {
-            q->green=RoundToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
+            q->green=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
             i++;
           }
         if (((channel & BlueChannel) != 0) && (i <= av_len(av)))
           {
-            q->blue=RoundToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
+            q->blue=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
             i++;
           }
         if ((((channel & IndexChannel) != 0) &&
             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
           {
-            *indexes=RoundToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
+            *indexes=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
             i++;
           }
         if (((channel & OpacityChannel) != 0) && (i <= av_len(av)))
           {
-            q->opacity=RoundToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
+            q->opacity=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
             i++;
           }
         (void) SyncAuthenticPixels(image,exception);
index fc7eb578b4a2b3e0f20d2a883a05fff3f2ddf9ca..fa40fc895003b7dd03309ec3897efe1e9c3b887b 100644 (file)
@@ -51,6 +51,7 @@
 #include "magick/enhance.h"
 #include "magick/exception.h"
 #include "magick/exception-private.h"
+#include "magick/fx.h"
 #include "magick/gem.h"
 #include "magick/geometry.h"
 #include "magick/histogram.h"
@@ -232,6 +233,88 @@ MagickExport MagickBooleanType AutoLevelImageChannel(Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%     B r i g h t n e s s C o n t r a s t I m a g e                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  Use BrightnessContrastImage() to change the brightness and/or contrast of
+%  an image.  It converts the brightness and contrast parameters into slope
+%  and intercept and calls a polynomical function to apply to the image.
+%
+%  The format of the BrightnessContrastImage method is:
+%
+%      MagickBooleanType BrightnessContrastImage(Image *image,
+%        const double brightness,const double contrast)
+%      MagickBooleanType BrightnessContrastImageChannel(Image *image,
+%        const ChannelType channel,const double brightness,
+%        const double contrast)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o channel: the channel.
+%
+%    o brightness: the brightness percent (-100 .. 100).
+%
+%    o contrast: the contrast percent (-100 .. 100).
+%
+*/
+
+MagickExport MagickBooleanType BrightnessContrastImage(Image *image,
+  const double brightness,const double contrast)
+{
+  MagickBooleanType
+    status;
+
+  status=BrightnessContrastImageChannel(image,DefaultChannels,brightness,
+    contrast);
+  return(status);
+}
+
+MagickExport MagickBooleanType BrightnessContrastImageChannel(Image *image,
+  const ChannelType channel,const double brightness,const double contrast)
+{
+#define BrightnessContastImageTag  "BrightnessContast/Image"
+
+  double
+    alpha,
+    intercept,
+    coefficients[2],
+    slope;
+
+  MagickBooleanType
+    status;
+
+  /*
+    Compute slope and intercept.
+  */
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  alpha=contrast;
+  if ((100-contrast) <= 0.1)
+    alpha=99.0;
+  slope=1.0+atan(MagickPI*(((alpha*alpha)/20000.0)+(3.0*contrast/
+    200.0))/4.0);
+  if (slope < 0.0)
+    slope=0.0;
+  intercept=brightness/100.0+((100-brightness)/200.0)*(1.0-slope);
+  coefficients[0]=slope;
+  coefficients[1]=intercept;
+  status=FunctionImageChannel(image,channel,PolynomialFunction,2,coefficients,
+    &image->exception);
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %     C o l o r D e c i s i o n L i s t I m a g e                             %
 %                                                                             %
 %                                                                             %
index 9dbcf7ec53e0e6f6183255c8bc6a88816f1bf254..c2563d4a187f45c219a7d054e901629787ad61b2 100644 (file)
@@ -27,6 +27,9 @@ extern MagickExport MagickBooleanType
   AutoGammaImageChannel(Image *,const ChannelType),
   AutoLevelImage(Image *),
   AutoLevelImageChannel(Image *,const ChannelType),
+  BrightnessContrastImage(Image *,const double,const double),
+  BrightnessContrastImageChannel(Image *,const ChannelType,const double,
+    const double),
   ClutImage(Image *,const Image *),
   ClutImageChannel(Image *,const ChannelType,const Image *),
   ColorDecisionListImage(Image *,const char *),
index 260388a8096acebc2dcfdba6245e969b2a31822c..4884ef5b1a9705f7bf09597d20448ba1d1447bc9 100644 (file)
@@ -209,6 +209,8 @@ static const OptionInfo
     { "-borderwidth", 1L, MagickFalse },
     { "+box", 0L, MagickFalse },
     { "-box", 1L, MagickFalse },
+    { "+brightness-contrast", 0L, MagickFalse },
+    { "-brightness-contrast", 1L, MagickFalse },
     { "+cache", 0L, MagickFalse },
     { "-cache", 1L, MagickFalse },
     { "+cdl", 1L, MagickFalse },
index 60e6780d671428126b766d114396c36e4c78e479..a545431df70e6eb68ae2f0e53e66bf93fffc1fe4 100644 (file)
@@ -161,6 +161,8 @@ static MagickBooleanType ConvertUsage(void)
       "-blur geometry       reduce image noise and reduce detail levels",
       "-border geometry     surround image with a border of color",
       "-bordercolor color   border color",
+      "-brightness-contrast geometry",
+      "                     improve brightness / contrast of the image",
       "-cdl filename        color correct with a color decision list",
       "-charcoal radius     simulate a charcoal drawing",
       "-chop geometry       remove pixels from the image interior",
@@ -799,6 +801,15 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info,
               ThrowConvertException(OptionError,"MissingArgument",option);
             break;
           }
+        if (LocaleCompare("brightness-contrast",option+1) == 0)
+          {
+            i++;
+            if (i == (long) (argc-1))
+              ThrowConvertException(OptionError,"MissingArgument",option);
+            if (IsGeometry(argv[i]) == MagickFalse)
+              ThrowConvertInvalidArgumentException(option,argv[i]);
+            break;
+          }
         ThrowConvertException(OptionError,"UnrecognizedOption",option)
       }
       case 'c':
index f370fad905cf6a239c2b55dcef339cefa0af8593..e5e6b666c984244f489b46b7606bac17fbfebfdd 100644 (file)
@@ -1112,6 +1112,73 @@ WandExport MagickBooleanType MagickBorderImage(MagickWand *wand,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   M a g i c k B r i g h t n e s s C o n t r a s t S t r e t c h I m a g e   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  Use MagickBrightnessContrastImage() to change the brightness and/or contrast
+%  of an image.  It converts the brightness and contrast parameters into slope
+%  and intercept and calls a polynomical function to apply to the image.
+
+%
+%  The format of the MagickBrightnessContrastImage method is:
+%
+%      MagickBooleanType MagickBrightnessContrastImage(MagickWand *wand,
+%        const double brightness,const double contrast)
+%      MagickBooleanType MagickBrightnessContrastImageChannel(MagickWand *wand,
+%        const ChannelType channel,const double brightness,
+%        const double contrast)
+%
+%  A description of each parameter follows:
+%
+%    o wand: the magick wand.
+%
+%    o channel: the image channel(s).
+%
+%    o brightness: the brightness percent (-100 .. 100).
+%
+%    o contrast: the contrast percent (-100 .. 100).
+%
+*/
+
+WandExport MagickBooleanType MagickBrightnessContrastImage(MagickWand *wand,
+  const double brightness,const double contrast)
+{
+  MagickBooleanType
+    status;
+
+  status=MagickBrightnessContrastImageChannel(wand,DefaultChannels,brightness,
+    contrast);
+  return(status);
+}
+
+WandExport MagickBooleanType MagickBrightnessContrastImageChannel(
+  MagickWand *wand,const ChannelType channel,const double brightness,
+  const double contrast)
+{
+  MagickBooleanType
+    status;
+
+  assert(wand != (MagickWand *) NULL);
+  assert(wand->signature == WandSignature);
+  if (wand->debug != MagickFalse)
+    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+  if (wand->images == (Image *) NULL)
+    ThrowWandException(WandError,"ContainsNoImages",wand->name);
+  status=BrightnessContrastImageChannel(wand->images,channel,brightness,
+    contrast);
+  if (status == MagickFalse)
+    InheritException(wand->exception,&wand->images->exception);
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   M a g i c k C h a r c o a l I m a g e                                     %
 %                                                                             %
 %                                                                             %
index 34881582743f4133a476a875830fc72130a075bb..58a0e69a58ccb209841e248814d4397fb882ff10 100644 (file)
@@ -96,6 +96,9 @@ extern WandExport MagickBooleanType
     const double),
   MagickBorderImage(MagickWand *,const PixelWand *,const unsigned long,
     const unsigned long),
+  MagickBrightnessContrastImage(MagickWand *,const double,const double),
+  MagickBrightnessContrastImageChannel(MagickWand *,const ChannelType,
+    const double,const double),
   MagickCharcoalImage(MagickWand *,const double,const double),
   MagickChopImage(MagickWand *,const unsigned long,const unsigned long,
     const long,const long),
index 1ed4772ae3a49ee4532d96c0e8a1a868f549a306..950022d9800c569d0e0b1b0e22994185b48816c3 100644 (file)
@@ -952,6 +952,30 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc,
               exception);
             break;
           }
+        if (LocaleCompare("brightness-contrast",option+1) == 0)
+          {
+            double
+              brightness,
+              contrast;
+
+            GeometryInfo
+              geometry_info;
+
+            MagickStatusType
+              flags;
+
+            /*
+              Brightness / contrast image.
+            */
+            (void) SyncImageSettings(image_info,*image);
+            flags=ParseGeometry(argv[i+1],&geometry_info);
+            brightness=geometry_info.rho;
+            if ((flags & SigmaValue) != 0)
+              contrast=geometry_info.sigma;
+            (void) BrightnessImageChannel(*image,channel,brightness,contrast);
+            InheritException(exception,&(*image)->exception);
+            break;
+          }
         break;
       }
       case 'c':
@@ -3569,6 +3593,8 @@ static MagickBooleanType MogrifyUsage(void)
       "-blur geometry       reduce image noise and reduce detail levels",
       "-border geometry     surround image with a border of color",
       "-bordercolor color   border color",
+      "-brightness-contrast geometry",
+      "                     improve brightness / contrast of the image",
       "-cdl filename        color correct with a color decision list",
       "-charcoal radius     simulate a charcoal drawing",
       "-chop geometry       remove pixels from the image interior",
@@ -4242,6 +4268,15 @@ WandExport MagickBooleanType MogrifyImageCommand(ImageInfo *image_info,
               ThrowMogrifyException(OptionError,"MissingArgument",option);
             break;
           }
+        if (LocaleCompare("brightness-contrast",option+1) == 0)
+          {
+            i++;
+            if (i == (long) argc)
+              ThrowMogrifyException(OptionError,"MissingArgument",option);
+            if (IsGeometry(argv[i]) == MagickFalse)
+              ThrowMogrifyInvalidArgumentException(option,argv[i]);
+            break;
+          }
         ThrowMogrifyException(OptionError,"UnrecognizedOption",option)
       }
       case 'c':