* 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.
#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
{ "Clamp", { {"channel", MagickChannelOptions} } },
{ "Filter", { {"kernel", StringReference},
{"channel", MagickChannelOptions}, {"bias", StringReference} } },
+ { "BrightnessContrast", { {"levels", StringReference},
+ {"brightness", RealReference},{"contrast", RealReference},
+ {"channel", MagickChannelOptions} } },
};
static SplayTreeInfo
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;
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);
ClampImage = 260
Filter = 261
FilterImage = 262
+ BrightnessContrast = 263
+ BrightnessContrastImage = 264
MogrifyRegion = 666
PPCODE:
{
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);
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;
}
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 */
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);
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);
#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"
% %
% %
% %
+% 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 %
% %
% %
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 *),
{ "-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 },
"-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",
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':
% %
% %
% %
+% 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 %
% %
% %
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),
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':
"-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",
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':