% July 1992 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
#include "MagickCore/composite-private.h"
#include "MagickCore/enhance.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/fx.h"
#include "MagickCore/gem.h"
+#include "MagickCore/gem-private.h"
#include "MagickCore/geometry.h"
#include "MagickCore/histogram.h"
#include "MagickCore/image.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/option.h"
+#include "MagickCore/pixel.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/quantum.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/thread-private.h"
#include "MagickCore/token.h"
#include "MagickCore/xml-tree.h"
+#include "MagickCore/xml-tree-private.h"
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The format of the AutoGammaImage method is:
%
-% MagickBooleanType AutoGammaImage(Image *image)
-% MagickBooleanType AutoGammaImageChannel(Image *image,
-% const ChannelType channel)
+% MagickBooleanType AutoGammaImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: The image to auto-level
%
-% o channel: The channels to auto-level. If the special 'SyncChannels'
-% flag is set all given channels is adjusted in the same way using the
-% mean average of those channels.
+% o exception: return any errors or warnings in this structure.
%
*/
-
-MagickExport MagickBooleanType AutoGammaImage(Image *image)
-{
- return(AutoGammaImageChannel(image,DefaultChannels));
-}
-
-MagickExport MagickBooleanType AutoGammaImageChannel(Image *image,
- const ChannelType channel)
+MagickExport MagickBooleanType AutoGammaImage(Image *image,
+ ExceptionInfo *exception)
{
- MagickStatusType
- status;
-
double
gamma,
log_mean,
mean,
sans;
- log_mean=log(0.5);
+ MagickStatusType
+ status;
+
+ register ssize_t
+ i;
- if ((channel & SyncChannels) != 0 )
+ log_mean=log(0.5);
+ if (image->channel_mask == DefaultChannels)
{
/*
- Apply gamma correction equally accross all given channels
+ Apply gamma correction equally across all given channels.
*/
- (void) GetImageChannelMean(image,channel,&mean,&sans,&image->exception);
+ (void) GetImageMean(image,&mean,&sans,exception);
gamma=log(mean*QuantumScale)/log_mean;
- return(LevelImageChannel(image,channel,0.0,(double)QuantumRange,gamma));
+ return(LevelImage(image,0.0,(double) QuantumRange,gamma,exception));
}
-
/*
Auto-gamma each channel separately.
*/
status=MagickTrue;
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- {
- (void) GetImageChannelMean(image,RedChannel,&mean,&sans,
- &image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImageChannel(image,RedChannel,0.0,(double)
- QuantumRange, gamma);
- }
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- {
- (void) GetImageChannelMean(image,GreenChannel,&mean,&sans,
- &image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImageChannel(image,GreenChannel,0.0,(double)
- QuantumRange,gamma);
- }
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- {
- (void) GetImageChannelMean(image,BlueChannel,&mean,&sans,
- &image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImageChannel(image,BlueChannel,0.0,(double)
- QuantumRange,gamma);
- }
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- {
- (void) GetImageChannelMean(image,BlackChannel,&mean,&sans,
- &image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImageChannel(image,BlackChannel,0.0,(double)
- QuantumRange,gamma);
- }
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
- (image->matte == MagickTrue))
- {
- (void) GetImageChannelMean(image,OpacityChannel,&mean,&sans,
- &image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImageChannel(image,OpacityChannel,0.0,(double)
- QuantumRange,gamma);
- }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ ChannelType
+ channel_mask;
+
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ channel_mask=SetPixelChannelMask(image,(ChannelType) (1 << i));
+ status=GetImageMean(image,&mean,&sans,exception);
+ gamma=log(mean*QuantumScale)/log_mean;
+ status&=LevelImage(image,0.0,(double) QuantumRange,gamma,exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ if (status == MagickFalse)
+ break;
+ }
return(status != 0 ? MagickTrue : MagickFalse);
}
\f
%
% The format of the LevelImage method is:
%
-% MagickBooleanType AutoLevelImage(Image *image)
-% MagickBooleanType AutoLevelImageChannel(Image *image,
-% const ChannelType channel)
+% MagickBooleanType AutoLevelImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: The image to auto-level
%
-% o channel: The channels to auto-level. If the special 'SyncChannels'
-% flag is set the min/max/mean value of all given channels is used for
-% all given channels, to all channels in the same way.
+% o exception: return any errors or warnings in this structure.
%
*/
-
-MagickExport MagickBooleanType AutoLevelImage(Image *image)
-{
- return(AutoLevelImageChannel(image,DefaultChannels));
-}
-
-MagickExport MagickBooleanType AutoLevelImageChannel(Image *image,
- const ChannelType channel)
+MagickExport MagickBooleanType AutoLevelImage(Image *image,
+ ExceptionInfo *exception)
{
- /*
- This is simply a convenience function around a Min/Max Histogram Stretch
- */
- return MinMaxStretchImage(image, channel, 0.0, 0.0);
+ return(MinMaxStretchImage(image,0.0,0.0,1.0,exception));
}
\f
/*
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% 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.
+% BrightnessContrastImage() changes 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)
+% const double brightness,const double contrast,ExceptionInfo *exception)
%
% 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).
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-
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)
+ const double brightness,const double contrast,ExceptionInfo *exception)
{
#define BrightnessContastImageTag "BrightnessContast/Image"
double
alpha,
- intercept,
coefficients[2],
+ intercept,
slope;
MagickBooleanType
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);
+ status=FunctionImage(image,PolynomialFunction,2,coefficients,exception);
+ return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C l u t I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ClutImage() replaces each color value in the given image, by using it as an
+% index to lookup a replacement color value in a Color Look UP Table in the
+% form of an image. The values are extracted along a diagonal of the CLUT
+% image so either a horizontal or vertial gradient image can be used.
+%
+% Typically this is used to either re-color a gray-scale image according to a
+% color gradient in the CLUT image, or to perform a freeform histogram
+% (level) adjustment according to the (typically gray-scale) gradient in the
+% CLUT image.
+%
+% When the 'channel' mask includes the matte/alpha transparency channel but
+% one image has no such channel it is assumed that that image is a simple
+% gray-scale image that will effect the alpha channel values, either for
+% gray-scale coloring (with transparent or semi-transparent colors), or
+% a histogram adjustment of existing alpha channel values. If both images
+% have matte channels, direct and normal indexing is applied, which is rarely
+% used.
+%
+% The format of the ClutImage method is:
+%
+% MagickBooleanType ClutImage(Image *image,Image *clut_image,
+% const PixelInterpolateMethod method,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image, which is replaced by indexed CLUT values
+%
+% o clut_image: the color lookup table image for replacement color values.
+%
+% o method: the pixel interpolation method.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
+ const PixelInterpolateMethod method,ExceptionInfo *exception)
+{
+#define ClutImageTag "Clut/Image"
+
+ CacheView
+ *clut_view,
+ *image_view;
+
+ MagickBooleanType
+ status;
+
+ MagickOffsetType
+ progress;
+
+ PixelInfo
+ *clut_map;
+
+ register ssize_t
+ i;
+
+ ssize_t adjust,
+ y;
+
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(clut_image != (Image *) NULL);
+ assert(clut_image->signature == MagickSignature);
+ if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
+ return(MagickFalse);
+ if (IsGrayColorspace(image->colorspace) != MagickFalse)
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ clut_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*clut_map));
+ if (clut_map == (PixelInfo *) NULL)
+ ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+ image->filename);
+ /*
+ Clut image.
+ */
+ status=MagickTrue;
+ progress=0;
+ adjust=(ssize_t) (clut_image->interpolate == IntegerInterpolatePixel ? 0 : 1);
+ clut_view=AcquireVirtualCacheView(clut_image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4)
+#endif
+ for (i=0; i <= (ssize_t) MaxMap; i++)
+ {
+ GetPixelInfo(clut_image,clut_map+i);
+ (void) InterpolatePixelInfo(clut_image,clut_view,method,
+ QuantumScale*i*(clut_image->columns-adjust),QuantumScale*i*
+ (clut_image->rows-adjust),clut_map+i,exception);
+ }
+ clut_view=DestroyCacheView(clut_view);
+ image_view=AcquireAuthenticCacheView(image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
+#endif
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ PixelInfo
+ pixel;
+
+ register Quantum
+ *restrict q;
+
+ register ssize_t
+ x;
+
+ if (status == MagickFalse)
+ continue;
+ q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
+ if (q == (Quantum *) NULL)
+ {
+ status=MagickFalse;
+ continue;
+ }
+ GetPixelInfo(image,&pixel);
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ if (GetPixelMask(image,q) != 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ GetPixelInfoPixel(image,q,&pixel);
+ pixel.red=clut_map[ScaleQuantumToMap(pixel.red)].red;
+ pixel.green=clut_map[ScaleQuantumToMap(pixel.green)].green;
+ pixel.blue=clut_map[ScaleQuantumToMap(pixel.blue)].blue;
+ pixel.black=clut_map[ScaleQuantumToMap(pixel.black)].black;
+ pixel.alpha=clut_map[ScaleQuantumToMap(pixel.alpha)].alpha;
+ SetPixelInfoPixel(image,&pixel,q);
+ q+=GetPixelChannels(image);
+ }
+ if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
+ status=MagickFalse;
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_ClutImage)
+#endif
+ proceed=SetImageProgress(image,ClutImageTag,progress++,image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
+ }
+ image_view=DestroyCacheView(image_view);
+ clut_map=(PixelInfo *) RelinquishMagickMemory(clut_map);
+ if ((clut_image->matte != MagickFalse) &&
+ ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0))
+ (void) SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
return(status);
}
\f
% The format of the ColorDecisionListImage method is:
%
% MagickBooleanType ColorDecisionListImage(Image *image,
-% const char *color_correction_collection)
+% const char *color_correction_collection,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o color_correction_collection: the color correction collection in XML.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
MagickExport MagickBooleanType ColorDecisionListImage(Image *image,
- const char *color_correction_collection)
+ const char *color_correction_collection,ExceptionInfo *exception)
{
#define ColorDecisionListCorrectImageTag "ColorDecisionList/Image"
*content,
*p;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
MagickOffsetType
progress;
- PixelPacket
+ PixelInfo
*cdl_map;
register ssize_t
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (color_correction_collection == (const char *) NULL)
return(MagickFalse);
- ccc=NewXMLTree((const char *) color_correction_collection,&image->exception);
+ ccc=NewXMLTree((const char *) color_correction_collection,exception);
if (ccc == (XMLTreeInfo *) NULL)
return(MagickFalse);
cc=GetXMLTreeChild(ccc,"ColorCorrection");
{
case 0:
{
- color_correction.red.slope=InterpretLocaleValue(token,
- (char **) NULL);
+ color_correction.red.slope=StringToDouble(token,(char **) NULL);
break;
}
case 1:
{
- color_correction.green.slope=InterpretLocaleValue(token,
+ color_correction.green.slope=StringToDouble(token,
(char **) NULL);
break;
}
case 2:
{
- color_correction.blue.slope=InterpretLocaleValue(token,
+ color_correction.blue.slope=StringToDouble(token,
(char **) NULL);
break;
}
{
case 0:
{
- color_correction.red.offset=InterpretLocaleValue(token,
+ color_correction.red.offset=StringToDouble(token,
(char **) NULL);
break;
}
case 1:
{
- color_correction.green.offset=InterpretLocaleValue(token,
+ color_correction.green.offset=StringToDouble(token,
(char **) NULL);
break;
}
case 2:
{
- color_correction.blue.offset=InterpretLocaleValue(token,
+ color_correction.blue.offset=StringToDouble(token,
(char **) NULL);
break;
}
{
case 0:
{
- color_correction.red.power=InterpretLocaleValue(token,
- (char **) NULL);
+ color_correction.red.power=StringToDouble(token,(char **) NULL);
break;
}
case 1:
{
- color_correction.green.power=InterpretLocaleValue(token,
+ color_correction.green.power=StringToDouble(token,
(char **) NULL);
break;
}
case 2:
{
- color_correction.blue.power=InterpretLocaleValue(token,
+ color_correction.blue.power=StringToDouble(token,
(char **) NULL);
break;
}
content=GetXMLTreeContent(saturation);
p=(const char *) content;
GetMagickToken(p,&p,token);
- color_correction.saturation=InterpretLocaleValue(token,
- (char **) NULL);
+ color_correction.saturation=StringToDouble(token,(char **) NULL);
}
}
ccc=DestroyXMLTree(ccc);
(void) LogMagickEvent(TransformEvent,GetMagickModule(),
" color_correction.saturation: %g",color_correction.saturation);
}
- cdl_map=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*cdl_map));
- if (cdl_map == (PixelPacket *) NULL)
+ cdl_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*cdl_map));
+ if (cdl_map == (PixelInfo *) NULL)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4)
+ #pragma omp parallel for schedule(static,4)
#endif
for (i=0; i <= (ssize_t) MaxMap; i++)
{
- cdl_map[i].red=ClampToQuantum((MagickRealType) ScaleMapToQuantum((
- MagickRealType) (MaxMap*(pow(color_correction.red.slope*i/MaxMap+
- color_correction.red.offset,color_correction.red.power)))));
- cdl_map[i].green=ClampToQuantum((MagickRealType) ScaleMapToQuantum((
- MagickRealType) (MaxMap*(pow(color_correction.green.slope*i/MaxMap+
- color_correction.green.offset,color_correction.green.power)))));
- cdl_map[i].blue=ClampToQuantum((MagickRealType) ScaleMapToQuantum((
- MagickRealType) (MaxMap*(pow(color_correction.blue.slope*i/MaxMap+
- color_correction.blue.offset,color_correction.blue.power)))));
+ cdl_map[i].red=(MagickRealType) ScaleMapToQuantum((MagickRealType)
+ (MaxMap*(pow(color_correction.red.slope*i/MaxMap+
+ color_correction.red.offset,color_correction.red.power))));
+ cdl_map[i].green=(MagickRealType) ScaleMapToQuantum((MagickRealType)
+ (MaxMap*(pow(color_correction.green.slope*i/MaxMap+
+ color_correction.green.offset,color_correction.green.power))));
+ cdl_map[i].blue=(MagickRealType) ScaleMapToQuantum((MagickRealType)
+ (MaxMap*(pow(color_correction.blue.slope*i/MaxMap+
+ color_correction.blue.offset,color_correction.blue.power))));
}
if (image->storage_class == PseudoClass)
{
Apply transfer function to colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
luma=0.2126*image->colormap[i].red+0.7152*image->colormap[i].green+
0.0722*image->colormap[i].blue;
- image->colormap[i].red=ClampToQuantum(luma+color_correction.saturation*
- cdl_map[ScaleQuantumToMap(image->colormap[i].red)].red-luma);
- image->colormap[i].green=ClampToQuantum(luma+
- color_correction.saturation*cdl_map[ScaleQuantumToMap(
- image->colormap[i].green)].green-luma);
- image->colormap[i].blue=ClampToQuantum(luma+color_correction.saturation*
- cdl_map[ScaleQuantumToMap(image->colormap[i].blue)].blue-luma);
+ image->colormap[i].red=luma+color_correction.saturation*cdl_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red))].red-
+ luma;
+ image->colormap[i].green=luma+color_correction.saturation*cdl_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green))].green-
+ luma;
+ image->colormap[i].blue=luma+color_correction.saturation*cdl_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue))].blue-
+ luma;
}
}
/*
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_ColorDecisionListImageChannel)
+ #pragma omp critical (MagickCore_ColorDecisionListImageChannel)
#endif
proceed=SetImageProgress(image,ColorDecisionListCorrectImageTag,
progress++,image->rows);
}
}
image_view=DestroyCacheView(image_view);
- cdl_map=(PixelPacket *) RelinquishMagickMemory(cdl_map);
+ cdl_map=(PixelInfo *) RelinquishMagickMemory(cdl_map);
return(status);
}
\f
% %
% %
% %
-% C l u t I m a g e %
+% C o n t r a s t I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% ClutImage() replaces each color value in the given image, by using it as an
-% index to lookup a replacement color value in a Color Look UP Table in the
-% form of an image. The values are extracted along a diagonal of the CLUT
-% image so either a horizontal or vertial gradient image can be used.
-%
-% Typically this is used to either re-color a gray-scale image according to a
-% color gradient in the CLUT image, or to perform a freeform histogram
-% (level) adjustment according to the (typically gray-scale) gradient in the
-% CLUT image.
-%
-% When the 'channel' mask includes the matte/alpha transparency channel but
-% one image has no such channel it is assumed that that image is a simple
-% gray-scale image that will effect the alpha channel values, either for
-% gray-scale coloring (with transparent or semi-transparent colors), or
-% a histogram adjustment of existing alpha channel values. If both images
-% have matte channels, direct and normal indexing is applied, which is rarely
-% used.
+% ContrastImage() enhances the intensity differences between the lighter and
+% darker elements of the image. Set sharpen to a MagickTrue to increase the
+% image contrast otherwise the contrast is reduced.
%
-% The format of the ClutImage method is:
+% The format of the ContrastImage method is:
%
-% MagickBooleanType ClutImage(Image *image,Image *clut_image)
-% MagickBooleanType ClutImageChannel(Image *image,
-% const ChannelType channel,Image *clut_image)
+% MagickBooleanType ContrastImage(Image *image,
+% const MagickBooleanType sharpen,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
-% o image: the image, which is replaced by indexed CLUT values
+% o image: the image.
%
-% o clut_image: the color lookup table image for replacement color values.
+% o sharpen: Increase or decrease image contrast.
%
-% o channel: the channel.
+% o exception: return any errors or warnings in this structure.
%
*/
-MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image)
+static void Contrast(const int sign,double *red,double *green,double *blue)
{
- return(ClutImageChannel(image,DefaultChannels,clut_image));
+ double
+ brightness,
+ hue,
+ saturation;
+
+ /*
+ Enhance contrast: dark color become darker, light color become lighter.
+ */
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
+ hue=0.0;
+ saturation=0.0;
+ brightness=0.0;
+ ConvertRGBToHSB(*red,*green,*blue,&hue,&saturation,&brightness);
+ brightness+=0.5*sign*(0.5*(sin((double) (MagickPI*(brightness-0.5)))+1.0)-
+ brightness);
+ if (brightness > 1.0)
+ brightness=1.0;
+ else
+ if (brightness < 0.0)
+ brightness=0.0;
+ ConvertHSBToRGB(hue,saturation,brightness,red,green,blue);
}
-MagickExport MagickBooleanType ClutImageChannel(Image *image,
- const ChannelType channel,const Image *clut_image)
+MagickExport MagickBooleanType ContrastImage(Image *image,
+ const MagickBooleanType sharpen,ExceptionInfo *exception)
{
-#define ClampAlphaPixelComponent(pixel) ClampToQuantum((pixel)->alpha)
-#define ClampBlackPixelComponent(pixel) ClampToQuantum((pixel)->black)
-#define ClampBluePixelComponent(pixel) ClampToQuantum((pixel)->blue)
-#define ClampGreenPixelComponent(pixel) ClampToQuantum((pixel)->green)
-#define ClampRedPixelComponent(pixel) ClampToQuantum((pixel)->red)
-#define ClutImageTag "Clut/Image"
+#define ContrastImageTag "Contrast/Image"
CacheView
- *clut_view,
*image_view;
- ExceptionInfo
- *exception;
-
- MagickBooleanType
- status;
-
- MagickOffsetType
- progress;
-
- PixelInfo
- *clut_map;
-
- register ssize_t
- i;
-
- ssize_t
- adjust,
- y;
-
- assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- assert(clut_image != (Image *) NULL);
- assert(clut_image->signature == MagickSignature);
- if (SetImageStorageClass(image,DirectClass) == MagickFalse)
- return(MagickFalse);
- clut_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
- sizeof(*clut_map));
- if (clut_map == (PixelInfo *) NULL)
- ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
- image->filename);
- /*
- Clut image.
- */
- status=MagickTrue;
- progress=0;
- adjust=(ssize_t) (clut_image->interpolate == IntegerInterpolatePixel ? 0 : 1);
- exception=(&image->exception);
- clut_view=AcquireCacheView(clut_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4)
-#endif
- for (i=0; i <= (ssize_t) MaxMap; i++)
- {
- GetPixelInfo(clut_image,clut_map+i);
- (void) InterpolatePixelInfo(clut_image,clut_view,
- UndefinedInterpolatePixel,QuantumScale*i*(clut_image->columns-adjust),
- QuantumScale*i*(clut_image->rows-adjust),clut_map+i,exception);
- }
- clut_view=DestroyCacheView(clut_view);
- image_view=AcquireCacheView(image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
-#endif
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- PixelInfo
- pixel;
-
- register Quantum
- *restrict q;
-
- register ssize_t
- x;
-
- if (status == MagickFalse)
- continue;
- q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
- {
- status=MagickFalse;
- continue;
- }
- GetPixelInfo(image,&pixel);
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- SetPixelInfo(image,q,&pixel);
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,ClampRedPixelComponent(clut_map+
- ScaleQuantumToMap(GetPixelRed(image,q))),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,ClampGreenPixelComponent(clut_map+
- ScaleQuantumToMap(GetPixelGreen(image,q))),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,ClampBluePixelComponent(clut_map+
- ScaleQuantumToMap(GetPixelBlue(image,q))),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,ClampBlackPixelComponent(clut_map+
- ScaleQuantumToMap(GetPixelBlack(image,q))),q);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- {
- if (clut_image->matte == MagickFalse)
- SetPixelAlpha(image,GetPixelInfoIntensity(clut_map+
- ScaleQuantumToMap((Quantum) GetPixelAlpha(image,q))),q);
- else
- if (image->matte == MagickFalse)
- SetPixelAlpha(image,ClampAlphaPixelComponent(clut_map+
- ScaleQuantumToMap((Quantum) GetPixelInfoIntensity(&pixel))),q);
- else
- SetPixelAlpha(image,ClampAlphaPixelComponent(clut_map+
- ScaleQuantumToMap(GetPixelAlpha(image,q))),q);
- }
- q+=GetPixelChannels(image);
- }
- if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_ClutImageChannel)
-#endif
- proceed=SetImageProgress(image,ClutImageTag,progress++,image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- image_view=DestroyCacheView(image_view);
- clut_map=(PixelInfo *) RelinquishMagickMemory(clut_map);
- if ((clut_image->matte != MagickFalse) &&
- ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0))
- (void) SetImageAlphaChannel(image,ActivateAlphaChannel);
- return(status);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% C o n t r a s t I m a g e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% ContrastImage() enhances the intensity differences between the lighter and
-% darker elements of the image. Set sharpen to a MagickTrue to increase the
-% image contrast otherwise the contrast is reduced.
-%
-% The format of the ContrastImage method is:
-%
-% MagickBooleanType ContrastImage(Image *image,
-% const MagickBooleanType sharpen)
-%
-% A description of each parameter follows:
-%
-% o image: the image.
-%
-% o sharpen: Increase or decrease image contrast.
-%
-*/
-
-static void Contrast(const int sign,Quantum *red,Quantum *green,Quantum *blue)
-{
- double
- brightness,
- hue,
- saturation;
-
- /*
- Enhance contrast: dark color become darker, light color become lighter.
- */
- assert(red != (Quantum *) NULL);
- assert(green != (Quantum *) NULL);
- assert(blue != (Quantum *) NULL);
- hue=0.0;
- saturation=0.0;
- brightness=0.0;
- ConvertRGBToHSB(*red,*green,*blue,&hue,&saturation,&brightness);
- brightness+=0.5*sign*(0.5*(sin((double) (MagickPI*(brightness-0.5)))+1.0)-
- brightness);
- if (brightness > 1.0)
- brightness=1.0;
- else
- if (brightness < 0.0)
- brightness=0.0;
- ConvertHSBToRGB(hue,saturation,brightness,red,green,blue);
-}
-
-MagickExport MagickBooleanType ContrastImage(Image *image,
- const MagickBooleanType sharpen)
-{
-#define ContrastImageTag "Contrast/Image"
-
- CacheView
- *image_view;
-
- ExceptionInfo
- *exception;
-
int
sign;
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
- Quantum
+ double
blue,
green,
red;
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- red=GetPixelRed(image,q);
- green=GetPixelGreen(image,q);
- blue=GetPixelBlue(image,q);
+ red=(double) GetPixelRed(image,q);
+ green=(double) GetPixelGreen(image,q);
+ blue=(double) GetPixelBlue(image,q);
Contrast(sign,&red,&green,&blue);
- SetPixelRed(image,red,q);
- SetPixelGreen(image,green,q);
- SetPixelBlue(image,blue,q);
+ SetPixelRed(image,ClampToQuantum(red),q);
+ SetPixelGreen(image,ClampToQuantum(green),q);
+ SetPixelBlue(image,ClampToQuantum(blue),q);
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_ContrastImage)
+ #pragma omp critical (MagickCore_ContrastImage)
#endif
proceed=SetImageProgress(image,ContrastImageTag,progress++,image->rows);
if (proceed == MagickFalse)
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% The ContrastStretchImage() is a simple image enhancement technique that
-% attempts to improve the contrast in an image by `stretching' the range of
-% intensity values it contains to span a desired range of values. It differs
-% from the more sophisticated histogram equalization in that it can only
-% apply % a linear scaling function to the image pixel values. As a result
-% the `enhancement' is less harsh.
+% ContrastStretchImage() is a simple image enhancement technique that attempts
+% to improve the contrast in an image by 'stretching' the range of intensity
+% values it contains to span a desired range of values. It differs from the
+% more sophisticated histogram equalization in that it can only apply a
+% linear scaling function to the image pixel values. As a result the
+% 'enhancement' is less harsh.
%
% The format of the ContrastStretchImage method is:
%
% MagickBooleanType ContrastStretchImage(Image *image,
-% const char *levels)
-% MagickBooleanType ContrastStretchImageChannel(Image *image,
-% const size_t channel,const double black_point,
-% const double white_point)
+% const char *levels,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
-%
% o black_point: the black point.
%
% o white_point: the white point.
% o levels: Specify the levels where the black and white points have the
% range of 0 to number-of-pixels (e.g. 1%, 10x90%, etc.).
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-
MagickExport MagickBooleanType ContrastStretchImage(Image *image,
- const char *levels)
-{
- double
- black_point,
- white_point;
-
- GeometryInfo
- geometry_info;
-
- MagickBooleanType
- status;
-
- MagickStatusType
- flags;
-
- /*
- Parse levels.
- */
- if (levels == (char *) NULL)
- return(MagickFalse);
- flags=ParseGeometry(levels,&geometry_info);
- black_point=geometry_info.rho;
- white_point=(double) image->columns*image->rows;
- if ((flags & SigmaValue) != 0)
- white_point=geometry_info.sigma;
- if ((flags & PercentValue) != 0)
- {
- black_point*=(double) QuantumRange/100.0;
- white_point*=(double) QuantumRange/100.0;
- }
- if ((flags & SigmaValue) == 0)
- white_point=(double) image->columns*image->rows-black_point;
- status=ContrastStretchImageChannel(image,DefaultChannels,black_point,
- white_point);
- return(status);
-}
-
-MagickExport MagickBooleanType ContrastStretchImageChannel(Image *image,
- const ChannelType channel,const double black_point,const double white_point)
+ const double black_point,const double white_point,ExceptionInfo *exception)
{
#define MaxRange(color) ((MagickRealType) ScaleQuantumToMap((Quantum) (color)))
#define ContrastStretchImageTag "ContrastStretch/Image"
CacheView
*image_view;
- double
- intensity;
-
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
MagickOffsetType
progress;
- PixelInfo
- black,
+ double
+ *black,
*histogram,
*stretch_map,
- white;
+ *white;
register ssize_t
i;
+ size_t
+ number_channels;
+
ssize_t
y;
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- histogram=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
+ black=(double *) AcquireQuantumMemory(GetPixelChannels(image),sizeof(*black));
+ white=(double *) AcquireQuantumMemory(GetPixelChannels(image),sizeof(*white));
+ histogram=(double *) AcquireQuantumMemory(MaxMap+1UL,GetPixelChannels(image)*
sizeof(*histogram));
- stretch_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
- sizeof(*stretch_map));
- if ((histogram == (PixelInfo *) NULL) ||
- (stretch_map == (PixelInfo *) NULL))
- ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
- image->filename);
+ stretch_map=(double *) AcquireQuantumMemory(MaxMap+1UL,
+ GetPixelChannels(image)*sizeof(*stretch_map));
+ if ((black == (double *) NULL) || (white == (double *) NULL) ||
+ (histogram == (double *) NULL) || (stretch_map == (double *) NULL))
+ {
+ if (stretch_map != (double *) NULL)
+ stretch_map=(double *) RelinquishMagickMemory(stretch_map);
+ if (histogram != (double *) NULL)
+ histogram=(double *) RelinquishMagickMemory(histogram);
+ if (white != (double *) NULL)
+ white=(double *) RelinquishMagickMemory(white);
+ if (black != (double *) NULL)
+ black=(double *) RelinquishMagickMemory(black);
+ ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+ image->filename);
+ }
/*
Form histogram.
*/
status=MagickTrue;
- exception=(&image->exception);
- (void) ResetMagickMemory(histogram,0,(MaxMap+1)*sizeof(*histogram));
- image_view=AcquireCacheView(image);
+ (void) ResetMagickMemory(histogram,0,(MaxMap+1)*GetPixelChannels(image)*
+ sizeof(*histogram));
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
register const Quantum
status=MagickFalse;
continue;
}
- if (channel == DefaultChannels)
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- Quantum
- intensity;
-
- intensity=GetPixelIntensity(image,p);
- histogram[ScaleQuantumToMap(intensity)].red++;
- histogram[ScaleQuantumToMap(intensity)].green++;
- histogram[ScaleQuantumToMap(intensity)].blue++;
- histogram[ScaleQuantumToMap(intensity)].black++;
- p+=GetPixelChannels(image);
- }
- else
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelRed(image,p))].red++;
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelGreen(image,p))].green++;
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelBlue(image,p))].blue++;
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- histogram[ScaleQuantumToMap(GetPixelBlack(image,p))].black++;
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha++;
- p+=GetPixelChannels(image);
- }
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ histogram[GetPixelChannels(image)*ScaleQuantumToMap(p[i])+i]++;
+ p+=GetPixelChannels(image);
+ }
}
+ image_view=DestroyCacheView(image_view);
/*
Find the histogram boundaries by locating the black/white levels.
*/
- black.red=0.0;
- white.red=MaxRange(QuantumRange);
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- {
- intensity=0.0;
- for (i=0; i <= (ssize_t) MaxMap; i++)
- {
- intensity+=histogram[i].red;
- if (intensity > black_point)
- break;
- }
- black.red=(MagickRealType) i;
- intensity=0.0;
- for (i=(ssize_t) MaxMap; i != 0; i--)
- {
- intensity+=histogram[i].red;
- if (intensity > ((double) image->columns*image->rows-white_point))
- break;
- }
- white.red=(MagickRealType) i;
- }
- black.green=0.0;
- white.green=MaxRange(QuantumRange);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- {
- intensity=0.0;
- for (i=0; i <= (ssize_t) MaxMap; i++)
- {
- intensity+=histogram[i].green;
- if (intensity > black_point)
- break;
- }
- black.green=(MagickRealType) i;
- intensity=0.0;
- for (i=(ssize_t) MaxMap; i != 0; i--)
- {
- intensity+=histogram[i].green;
- if (intensity > ((double) image->columns*image->rows-white_point))
- break;
- }
- white.green=(MagickRealType) i;
- }
- black.blue=0.0;
- white.blue=MaxRange(QuantumRange);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- {
- intensity=0.0;
- for (i=0; i <= (ssize_t) MaxMap; i++)
- {
- intensity+=histogram[i].blue;
- if (intensity > black_point)
- break;
- }
- black.blue=(MagickRealType) i;
- intensity=0.0;
- for (i=(ssize_t) MaxMap; i != 0; i--)
- {
- intensity+=histogram[i].blue;
- if (intensity > ((double) image->columns*image->rows-white_point))
- break;
- }
- white.blue=(MagickRealType) i;
- }
- black.alpha=0.0;
- white.alpha=MaxRange(QuantumRange);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
+ number_channels=GetPixelChannels(image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
+#endif
+ for (i=0; i < (ssize_t) number_channels; i++)
+ {
+ double
+ intensity;
+
+ register ssize_t
+ j;
+
+ black[i]=0.0;
+ white[i]=MaxRange(QuantumRange);
+ intensity=0.0;
+ for (j=0; j <= (ssize_t) MaxMap; j++)
{
- intensity=0.0;
- for (i=0; i <= (ssize_t) MaxMap; i++)
- {
- intensity+=histogram[i].alpha;
- if (intensity > black_point)
- break;
- }
- black.alpha=(MagickRealType) i;
- intensity=0.0;
- for (i=(ssize_t) MaxMap; i != 0; i--)
- {
- intensity+=histogram[i].alpha;
- if (intensity > ((double) image->columns*image->rows-white_point))
- break;
- }
- white.alpha=(MagickRealType) i;
+ intensity+=histogram[GetPixelChannels(image)*j+i];
+ if (intensity > black_point)
+ break;
}
- black.black=0.0;
- white.black=MaxRange(QuantumRange);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) && (image->colorspace == CMYKColorspace))
+ black[i]=(MagickRealType) j;
+ intensity=0.0;
+ for (j=(ssize_t) MaxMap; j != 0; j--)
{
- intensity=0.0;
- for (i=0; i <= (ssize_t) MaxMap; i++)
- {
- intensity+=histogram[i].black;
- if (intensity > black_point)
- break;
- }
- black.black=(MagickRealType) i;
- intensity=0.0;
- for (i=(ssize_t) MaxMap; i != 0; i--)
- {
- intensity+=histogram[i].black;
- if (intensity > ((double) image->columns*image->rows-white_point))
- break;
- }
- white.black=(MagickRealType) i;
+ intensity+=histogram[GetPixelChannels(image)*j+i];
+ if (intensity > ((double) image->columns*image->rows-white_point))
+ break;
}
- histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
+ white[i]=(MagickRealType) j;
+ }
+ histogram=(double *) RelinquishMagickMemory(histogram);
/*
Stretch the histogram to create the stretched image mapping.
*/
- (void) ResetMagickMemory(stretch_map,0,(MaxMap+1)*sizeof(*stretch_map));
+ (void) ResetMagickMemory(stretch_map,0,(MaxMap+1)*GetPixelChannels(image)*
+ sizeof(*stretch_map));
+ number_channels=GetPixelChannels(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
- for (i=0; i <= (ssize_t) MaxMap; i++)
+ for (i=0; i < (ssize_t) number_channels; i++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- {
- if (i < (ssize_t) black.red)
- stretch_map[i].red=0.0;
- else
- if (i > (ssize_t) white.red)
- stretch_map[i].red=(MagickRealType) QuantumRange;
- else
- if (black.red != white.red)
- stretch_map[i].red=(MagickRealType) ScaleMapToQuantum(
- (MagickRealType) (MaxMap*(i-black.red)/(white.red-black.red)));
- }
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- {
- if (i < (ssize_t) black.green)
- stretch_map[i].green=0.0;
- else
- if (i > (ssize_t) white.green)
- stretch_map[i].green=(MagickRealType) QuantumRange;
- else
- if (black.green != white.green)
- stretch_map[i].green=(MagickRealType) ScaleMapToQuantum(
- (MagickRealType) (MaxMap*(i-black.green)/(white.green-
- black.green)));
- }
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- {
- if (i < (ssize_t) black.blue)
- stretch_map[i].blue=0.0;
- else
- if (i > (ssize_t) white.blue)
- stretch_map[i].blue=(MagickRealType) QuantumRange;
- else
- if (black.blue != white.blue)
- stretch_map[i].blue=(MagickRealType) ScaleMapToQuantum(
- (MagickRealType) (MaxMap*(i-black.blue)/(white.blue-
- black.blue)));
- }
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- {
- if (i < (ssize_t) black.alpha)
- stretch_map[i].alpha=0.0;
- else
- if (i > (ssize_t) white.alpha)
- stretch_map[i].alpha=(MagickRealType) QuantumRange;
- else
- if (black.alpha != white.alpha)
- stretch_map[i].alpha=(MagickRealType) ScaleMapToQuantum(
- (MagickRealType) (MaxMap*(i-black.alpha)/(white.alpha-
- black.alpha)));
- }
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- {
- if (i < (ssize_t) black.black)
- stretch_map[i].black=0.0;
+ register ssize_t
+ j;
+
+ for (j=0; j <= (ssize_t) MaxMap; j++)
+ {
+ if (j < (ssize_t) black[i])
+ stretch_map[GetPixelChannels(image)*j+i]=0.0;
+ else
+ if (j > (ssize_t) white[i])
+ stretch_map[GetPixelChannels(image)*j+i]=(MagickRealType)
+ QuantumRange;
else
- if (i > (ssize_t) white.black)
- stretch_map[i].black=(MagickRealType) QuantumRange;
- else
- if (black.black != white.black)
- stretch_map[i].black=(MagickRealType) ScaleMapToQuantum(
- (MagickRealType) (MaxMap*(i-black.black)/(white.black-
- black.black)));
- }
+ if (black[i] != white[i])
+ stretch_map[GetPixelChannels(image)*j+i]=(MagickRealType)
+ ScaleMapToQuantum((MagickRealType) (MaxMap*(j-black[i])/
+ (white[i]-black[i])));
+ }
}
- /*
- Stretch the image.
- */
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) || (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace)))
- image->storage_class=DirectClass;
if (image->storage_class == PseudoClass)
{
+ register ssize_t
+ j;
+
/*
- Stretch colormap.
+ Stretch-contrast colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
- for (i=0; i < (ssize_t) image->colors; i++)
+ for (j=0; j < (ssize_t) image->colors; j++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
{
- if (black.red != white.red)
- image->colormap[i].red=ClampToQuantum(stretch_map[
- ScaleQuantumToMap(image->colormap[i].red)].red);
+ i=GetPixelChannelMapChannel(image,RedPixelChannel);
+ if (black[i] != white[i])
+ image->colormap[j].red=stretch_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].red))]+i;
}
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
{
- if (black.green != white.green)
- image->colormap[i].green=ClampToQuantum(stretch_map[
- ScaleQuantumToMap(image->colormap[i].green)].green);
+ i=GetPixelChannelMapChannel(image,GreenPixelChannel);
+ if (black[i] != white[i])
+ image->colormap[j].green=stretch_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].green))]+i;
}
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
{
- if (black.blue != white.blue)
- image->colormap[i].blue=ClampToQuantum(stretch_map[
- ScaleQuantumToMap(image->colormap[i].blue)].blue);
+ i=GetPixelChannelMapChannel(image,BluePixelChannel);
+ if (black[i] != white[i])
+ image->colormap[j].blue=stretch_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].blue))]+i;
}
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
{
- if (black.alpha != white.alpha)
- image->colormap[i].alpha=ClampToQuantum(stretch_map[
- ScaleQuantumToMap(image->colormap[i].alpha)].alpha);
+ i=GetPixelChannelMapChannel(image,AlphaPixelChannel);
+ if (black[i] != white[i])
+ image->colormap[j].alpha=stretch_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].alpha))]+i;
}
}
}
/*
- Stretch image.
+ Stretch-contrast image.
*/
status=MagickTrue;
progress=0;
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- {
- if (black.red != white.red)
- SetPixelRed(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelRed(image,q))].red),q);
- }
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- {
- if (black.green != white.green)
- SetPixelGreen(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelGreen(image,q))].green),q);
- }
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- {
- if (black.blue != white.blue)
- SetPixelBlue(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelBlue(image,q))].blue),q);
- }
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- {
- if (black.black != white.black)
- SetPixelBlack(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelBlack(image,q))].black),q);
- }
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
{
- if (black.alpha != white.alpha)
- SetPixelAlpha(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelAlpha(image,q))].alpha),q);
+ q+=GetPixelChannels(image);
+ continue;
}
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if (((traits & UpdatePixelTrait) == 0) || (black[i] == white[i]))
+ continue;
+ q[i]=ClampToQuantum(stretch_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(q[i])+i]);
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_ContrastStretchImageChannel)
+ #pragma omp critical (MagickCore_ContrastStretchImage)
#endif
proceed=SetImageProgress(image,ContrastStretchImageTag,progress++,
image->rows);
}
}
image_view=DestroyCacheView(image_view);
- stretch_map=(PixelInfo *) RelinquishMagickMemory(stretch_map);
+ stretch_map=(double *) RelinquishMagickMemory(stretch_map);
+ white=(double *) RelinquishMagickMemory(white);
+ black=(double *) RelinquishMagickMemory(black);
return(status);
}
\f
*/
MagickExport Image *EnhanceImage(const Image *image,ExceptionInfo *exception)
{
-#define Enhance(weight) \
- mean=((MagickRealType) GetPixelRed(image,r)+pixel.red)/2; \
- distance=(MagickRealType) GetPixelRed(image,r)-(MagickRealType) pixel.red; \
+#define EnhancePixel(weight) \
+ mean=((MagickRealType) r[i]+GetPixelChannel(enhance_image,channel,q))/2.0; \
+ distance=(MagickRealType) r[i]-(MagickRealType) GetPixelChannel( \
+ enhance_image,channel,q); \
distance_squared=QuantumScale*(2.0*((MagickRealType) QuantumRange+1.0)+ \
- mean)*distance*distance; \
- mean=((MagickRealType) GetPixelGreen(image,r)+pixel.green)/2; \
- distance=(MagickRealType) GetPixelGreen(image,r)- \
- (MagickRealType) pixel.green; \
- distance_squared+=4.0*distance*distance; \
- mean=((MagickRealType) GetPixelBlue(image,r)+pixel.blue)/2; \
- distance=(MagickRealType) GetPixelBlue(image,r)- \
- (MagickRealType) pixel.blue; \
- distance_squared+=QuantumScale*(3.0*((MagickRealType) \
- QuantumRange+1.0)-1.0-mean)*distance*distance; \
- mean=((MagickRealType) GetPixelAlpha(image,r)+pixel.alpha)/2; \
- distance=(MagickRealType) GetPixelAlpha(image,r)-(MagickRealType) pixel.alpha; \
- distance_squared+=QuantumScale*(3.0*((MagickRealType) \
- QuantumRange+1.0)-1.0-mean)*distance*distance; \
+ mean)*distance*distance; \
if (distance_squared < ((MagickRealType) QuantumRange*(MagickRealType) \
QuantumRange/25.0f)) \
{ \
- aggregate.red+=(weight)*GetPixelRed(image,r); \
- aggregate.green+=(weight)*GetPixelGreen(image,r); \
- aggregate.blue+=(weight)*GetPixelBlue(image,r); \
- aggregate.alpha+=(weight)*GetPixelAlpha(image,r); \
+ aggregate+=(weight)*r[i]; \
total_weight+=(weight); \
} \
- r++;
+ r+=GetPixelChannels(image);
#define EnhanceImageTag "Enhance/Image"
CacheView
MagickOffsetType
progress;
- PixelInfo
- zero;
-
ssize_t
y;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
- if ((image->columns < 5) || (image->rows < 5))
- return((Image *) NULL);
enhance_image=CloneImage(image,image->columns,image->rows,MagickTrue,
exception);
if (enhance_image == (Image *) NULL)
return((Image *) NULL);
- if (SetImageStorageClass(enhance_image,DirectClass) == MagickFalse)
+ if (SetImageStorageClass(enhance_image,DirectClass,exception) == MagickFalse)
{
- InheritException(exception,&enhance_image->exception);
enhance_image=DestroyImage(enhance_image);
return((Image *) NULL);
}
*/
status=MagickTrue;
progress=0;
- (void) ResetMagickMemory(&zero,0,sizeof(zero));
- image_view=AcquireCacheView(image);
- enhance_view=AcquireCacheView(enhance_image);
+ image_view=AcquireVirtualCacheView(image,exception);
+ enhance_view=AcquireAuthenticCacheView(enhance_image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
register ssize_t
x;
- /*
- Read another scan line.
- */
+ ssize_t
+ center;
+
if (status == MagickFalse)
continue;
p=GetCacheViewVirtualPixels(image_view,-2,y-2,image->columns+4,5,exception);
status=MagickFalse;
continue;
}
+ center=(ssize_t) GetPixelChannels(image)*(2*(image->columns+4)+2);
for (x=0; x < (ssize_t) image->columns; x++)
{
- PixelInfo
- aggregate;
-
- MagickRealType
- distance,
- distance_squared,
- mean,
- total_weight;
-
- PixelPacket
- pixel;
+ register ssize_t
+ i;
- register const Quantum
- *restrict r;
-
- /*
- Compute weighted average of target pixel color components.
- */
- aggregate=zero;
- total_weight=0.0;
- r=p+2*(image->columns+4)+2;
- GetPixelPacket(image,r,&pixel);
- r=p;
- Enhance(5.0); Enhance(8.0); Enhance(10.0); Enhance(8.0); Enhance(5.0);
- r=p+(image->columns+4);
- Enhance(8.0); Enhance(20.0); Enhance(40.0); Enhance(20.0); Enhance(8.0);
- r=p+2*(image->columns+4);
- Enhance(10.0); Enhance(40.0); Enhance(80.0); Enhance(40.0); Enhance(10.0);
- r=p+3*(image->columns+4);
- Enhance(8.0); Enhance(20.0); Enhance(40.0); Enhance(20.0); Enhance(8.0);
- r=p+4*(image->columns+4);
- Enhance(5.0); Enhance(8.0); Enhance(10.0); Enhance(8.0); Enhance(5.0);
- SetPixelRed(enhance_image,(Quantum) ((aggregate.red+
- (total_weight/2)-1)/total_weight),q);
- SetPixelGreen(enhance_image,(Quantum) ((aggregate.green+
- (total_weight/2)-1)/total_weight),q);
- SetPixelBlue(enhance_image,(Quantum) ((aggregate.blue+
- (total_weight/2)-1)/total_weight),q);
- SetPixelAlpha(enhance_image,(Quantum) ((aggregate.alpha+
- (total_weight/2)-1)/total_weight),q);
+ if (GetPixelMask(image,p) != 0)
+ {
+ p+=GetPixelChannels(image);
+ q+=GetPixelChannels(enhance_image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ MagickRealType
+ aggregate,
+ distance,
+ distance_squared,
+ mean,
+ total_weight;
+
+ PixelChannel
+ channel;
+
+ PixelTrait
+ enhance_traits,
+ traits;
+
+ register const Quantum
+ *restrict r;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ enhance_traits=GetPixelChannelMapTraits(enhance_image,channel);
+ if ((traits == UndefinedPixelTrait) ||
+ (enhance_traits == UndefinedPixelTrait))
+ continue;
+ SetPixelChannel(enhance_image,channel,p[center+i],q);
+ if ((enhance_traits & CopyPixelTrait) != 0)
+ continue;
+ /*
+ Compute weighted average of target pixel color components.
+ */
+ aggregate=0.0;
+ total_weight=0.0;
+ r=p;
+ EnhancePixel(5.0); EnhancePixel(8.0); EnhancePixel(10.0);
+ EnhancePixel(8.0); EnhancePixel(5.0);
+ r=p+1*GetPixelChannels(image)*(image->columns+4);
+ EnhancePixel(8.0); EnhancePixel(20.0); EnhancePixel(40.0);
+ EnhancePixel(20.0); EnhancePixel(8.0);
+ r=p+2*GetPixelChannels(image)*(image->columns+4);
+ EnhancePixel(10.0); EnhancePixel(40.0); EnhancePixel(80.0);
+ EnhancePixel(40.0); EnhancePixel(10.0);
+ r=p+3*GetPixelChannels(image)*(image->columns+4);
+ EnhancePixel(8.0); EnhancePixel(20.0); EnhancePixel(40.0);
+ EnhancePixel(20.0); EnhancePixel(8.0);
+ r=p+4*GetPixelChannels(image)*(image->columns+4);
+ EnhancePixel(5.0); EnhancePixel(8.0); EnhancePixel(10.0);
+ EnhancePixel(8.0); EnhancePixel(5.0);
+ SetPixelChannel(enhance_image,channel,ClampToQuantum(aggregate/
+ total_weight),q);
+ }
p+=GetPixelChannels(image);
q+=GetPixelChannels(enhance_image);
}
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_EnhanceImage)
+ #pragma omp critical (MagickCore_EnhanceImage)
#endif
proceed=SetImageProgress(image,EnhanceImageTag,progress++,image->rows);
if (proceed == MagickFalse)
%
% The format of the EqualizeImage method is:
%
-% MagickBooleanType EqualizeImage(Image *image)
-% MagickBooleanType EqualizeImageChannel(Image *image,
-% const ChannelType channel)
+% MagickBooleanType EqualizeImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
+% o exception: return any errors or warnings in this structure.
%
*/
-
-MagickExport MagickBooleanType EqualizeImage(Image *image)
-{
- return(EqualizeImageChannel(image,DefaultChannels));
-}
-
-MagickExport MagickBooleanType EqualizeImageChannel(Image *image,
- const ChannelType channel)
+MagickExport MagickBooleanType EqualizeImage(Image *image,
+ ExceptionInfo *exception)
{
#define EqualizeImageTag "Equalize/Image"
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
MagickOffsetType
progress;
- PixelInfo
- black,
+ MagickRealType
+ black[CompositePixelChannel],
*equalize_map,
*histogram,
- intensity,
*map,
- white;
+ white[CompositePixelChannel];
register ssize_t
i;
+ size_t
+ number_channels;
+
ssize_t
y;
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- equalize_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
- sizeof(*equalize_map));
- histogram=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
- sizeof(*histogram));
- map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*map));
- if ((equalize_map == (PixelInfo *) NULL) ||
- (histogram == (PixelInfo *) NULL) ||
- (map == (PixelInfo *) NULL))
+ equalize_map=(MagickRealType *) AcquireQuantumMemory(MaxMap+1UL,
+ GetPixelChannels(image)*sizeof(*equalize_map));
+ histogram=(MagickRealType *) AcquireQuantumMemory(MaxMap+1UL,
+ GetPixelChannels(image)*sizeof(*histogram));
+ map=(MagickRealType *) AcquireQuantumMemory(MaxMap+1UL,
+ GetPixelChannels(image)*sizeof(*map));
+ if ((equalize_map == (MagickRealType *) NULL) ||
+ (histogram == (MagickRealType *) NULL) ||
+ (map == (MagickRealType *) NULL))
{
- if (map != (PixelInfo *) NULL)
- map=(PixelInfo *) RelinquishMagickMemory(map);
- if (histogram != (PixelInfo *) NULL)
- histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
- if (equalize_map != (PixelInfo *) NULL)
- equalize_map=(PixelInfo *) RelinquishMagickMemory(equalize_map);
+ if (map != (MagickRealType *) NULL)
+ map=(MagickRealType *) RelinquishMagickMemory(map);
+ if (histogram != (MagickRealType *) NULL)
+ histogram=(MagickRealType *) RelinquishMagickMemory(histogram);
+ if (equalize_map != (MagickRealType *) NULL)
+ equalize_map=(MagickRealType *) RelinquishMagickMemory(equalize_map);
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
}
/*
Form histogram.
*/
- (void) ResetMagickMemory(histogram,0,(MaxMap+1)*sizeof(*histogram));
- exception=(&image->exception);
+ status=MagickTrue;
+ (void) ResetMagickMemory(histogram,0,(MaxMap+1)*GetPixelChannels(image)*
+ sizeof(*histogram));
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
register const Quantum
register ssize_t
x;
- p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+ if (status == MagickFalse)
+ continue;
+ p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
- break;
+ {
+ status=MagickFalse;
+ continue;
+ }
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelRed(image,p))].red++;
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelGreen(image,p))].green++;
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelBlue(image,p))].blue++;
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- histogram[ScaleQuantumToMap(GetPixelBlack(image,p))].black++;
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha++;
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ histogram[GetPixelChannels(image)*ScaleQuantumToMap(p[i])+i]++;
p+=GetPixelChannels(image);
}
}
+ image_view=DestroyCacheView(image_view);
/*
Integrate the histogram to get the equalization map.
*/
- (void) ResetMagickMemory(&intensity,0,sizeof(intensity));
- for (i=0; i <= (ssize_t) MaxMap; i++)
+ number_channels=GetPixelChannels(image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
+#endif
+ for (i=0; i < (ssize_t) number_channels; i++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- intensity.red+=histogram[i].red;
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- intensity.green+=histogram[i].green;
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- intensity.blue+=histogram[i].blue;
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- intensity.black+=histogram[i].black;
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- intensity.alpha+=histogram[i].alpha;
- map[i]=intensity;
+ MagickRealType
+ intensity;
+
+ register ssize_t
+ j;
+
+ intensity=0.0;
+ for (j=0; j <= (ssize_t) MaxMap; j++)
+ {
+ intensity+=histogram[GetPixelChannels(image)*j+i];
+ map[GetPixelChannels(image)*j+i]=intensity;
+ }
}
- black=map[0];
- white=map[(int) MaxMap];
- (void) ResetMagickMemory(equalize_map,0,(MaxMap+1)*sizeof(*equalize_map));
+ (void) ResetMagickMemory(equalize_map,0,(MaxMap+1)*GetPixelChannels(image)*
+ sizeof(*equalize_map));
+ number_channels=GetPixelChannels(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
- for (i=0; i <= (ssize_t) MaxMap; i++)
+ for (i=0; i < (ssize_t) number_channels; i++)
{
- if (((GetPixelRedTraits(image) & ActivePixelTrait) != 0) &&
- (white.red != black.red))
- equalize_map[i].red=(MagickRealType) ScaleMapToQuantum((MagickRealType)
- ((MaxMap*(map[i].red-black.red))/(white.red-black.red)));
- if (((GetPixelGreenTraits(image) & ActivePixelTrait) != 0) &&
- (white.green != black.green))
- equalize_map[i].green=(MagickRealType) ScaleMapToQuantum((MagickRealType)
- ((MaxMap*(map[i].green-black.green))/(white.green-black.green)));
- if (((GetPixelBlueTraits(image) & ActivePixelTrait) != 0) &&
- (white.blue != black.blue))
- equalize_map[i].blue=(MagickRealType) ScaleMapToQuantum((MagickRealType)
- ((MaxMap*(map[i].blue-black.blue))/(white.blue-black.blue)));
- if ((((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace)) &&
- (white.black != black.black))
- equalize_map[i].black=(MagickRealType) ScaleMapToQuantum((MagickRealType)
- ((MaxMap*(map[i].black-black.black))/(white.black-black.black)));
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
- (white.alpha != black.alpha))
- equalize_map[i].alpha=(MagickRealType) ScaleMapToQuantum(
- (MagickRealType) ((MaxMap*(map[i].alpha-black.alpha))/
- (white.alpha-black.alpha)));
+ register ssize_t
+ j;
+
+ black[i]=map[i];
+ white[i]=map[GetPixelChannels(image)*MaxMap+i];
+ if (black[i] != white[i])
+ for (j=0; j <= (ssize_t) MaxMap; j++)
+ equalize_map[GetPixelChannels(image)*j+i]=(MagickRealType)
+ ScaleMapToQuantum((MagickRealType) ((MaxMap*(map[
+ GetPixelChannels(image)*j+i]-black[i]))/(white[i]-black[i])));
}
- histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
- map=(PixelInfo *) RelinquishMagickMemory(map);
+ histogram=(MagickRealType *) RelinquishMagickMemory(histogram);
+ map=(MagickRealType *) RelinquishMagickMemory(map);
if (image->storage_class == PseudoClass)
{
+ PixelChannel
+ channel;
+
+ register ssize_t
+ j;
+
/*
Equalize colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
- for (i=0; i < (ssize_t) image->colors; i++)
+ for (j=0; j < (ssize_t) image->colors; j++)
{
- if (((GetPixelRedTraits(image) & ActivePixelTrait) != 0) &&
- (white.red != black.red))
- image->colormap[i].red=ClampToQuantum(equalize_map[
- ScaleQuantumToMap(image->colormap[i].red)].red);
- if (((GetPixelGreenTraits(image) & ActivePixelTrait) != 0) &&
- (white.green != black.green))
- image->colormap[i].green=ClampToQuantum(equalize_map[
- ScaleQuantumToMap(image->colormap[i].green)].green);
- if (((GetPixelBlueTraits(image) & ActivePixelTrait) != 0) &&
- (white.blue != black.blue))
- image->colormap[i].blue=ClampToQuantum(equalize_map[
- ScaleQuantumToMap(image->colormap[i].blue)].blue);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
- (white.alpha != black.alpha))
- image->colormap[i].alpha=ClampToQuantum(equalize_map[
- ScaleQuantumToMap(image->colormap[i].alpha)].alpha);
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel=GetPixelChannelMapChannel(image,RedPixelChannel);
+ if (black[channel] != white[channel])
+ image->colormap[j].red=equalize_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].red))]+
+ channel;
+ }
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel=GetPixelChannelMapChannel(image,GreenPixelChannel);
+ if (black[channel] != white[channel])
+ image->colormap[j].green=equalize_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].green))]+
+ channel;
+ }
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel=GetPixelChannelMapChannel(image,BluePixelChannel);
+ if (black[channel] != white[channel])
+ image->colormap[j].blue=equalize_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].blue))]+
+ channel;
+ }
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel=GetPixelChannelMapChannel(image,AlphaPixelChannel);
+ if (black[channel] != white[channel])
+ image->colormap[j].alpha=equalize_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[j].alpha))]+
+ channel;
+ }
}
}
/*
Equalize image.
*/
- status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (((GetPixelRedTraits(image) & ActivePixelTrait) != 0) &&
- (white.red != black.red))
- SetPixelRed(image,ClampToQuantum(equalize_map[
- ScaleQuantumToMap(GetPixelRed(image,q))].red),q);
- if (((GetPixelGreenTraits(image) & ActivePixelTrait) != 0) &&
- (white.green != black.green))
- SetPixelGreen(image,ClampToQuantum(equalize_map[
- ScaleQuantumToMap(GetPixelGreen(image,q))].green),q);
- if (((GetPixelBlueTraits(image) & ActivePixelTrait) != 0) &&
- (white.blue != black.blue))
- SetPixelBlue(image,ClampToQuantum(equalize_map[
- ScaleQuantumToMap(GetPixelBlue(image,q))].blue),q);
- if ((((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace)) &&
- (white.black != black.black))
- SetPixelBlack(image,ClampToQuantum(equalize_map[
- ScaleQuantumToMap(GetPixelBlack(image,q))].black),q);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
- (white.alpha != black.alpha))
- SetPixelAlpha(image,ClampToQuantum(equalize_map[
- ScaleQuantumToMap(GetPixelAlpha(image,q))].alpha),q);
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if (((traits & UpdatePixelTrait) == 0) || (black[i] == white[i]))
+ continue;
+ q[i]=ClampToQuantum(equalize_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(q[i])+i]);
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_EqualizeImageChannel)
+ #pragma omp critical (MagickCore_EqualizeImage)
#endif
proceed=SetImageProgress(image,EqualizeImageTag,progress++,image->rows);
if (proceed == MagickFalse)
}
}
image_view=DestroyCacheView(image_view);
- equalize_map=(PixelInfo *) RelinquishMagickMemory(equalize_map);
+ equalize_map=(MagickRealType *) RelinquishMagickMemory(equalize_map);
return(status);
}
\f
%
% You can also reduce the influence of a particular channel with a gamma
% value of 0.
-%
-% The format of the GammaImage method is:
-%
-% MagickBooleanType GammaImage(Image *image,const char *level)
-% MagickBooleanType GammaImageChannel(Image *image,
-% const ChannelType channel,const double gamma)
-%
-% A description of each parameter follows:
-%
-% o image: the image.
-%
-% o channel: the channel.
-%
-% o level: the image gamma as a string (e.g. 1.6,1.2,1.0).
-%
-% o gamma: the image gamma.
-%
-*/
-MagickExport MagickBooleanType GammaImage(Image *image,const char *level)
-{
- GeometryInfo
- geometry_info;
-
- PixelInfo
- gamma;
-
- MagickStatusType
- flags,
- status;
-
- assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- if (level == (char *) NULL)
- return(MagickFalse);
- flags=ParseGeometry(level,&geometry_info);
- gamma.red=geometry_info.rho;
- gamma.green=geometry_info.sigma;
- if ((flags & SigmaValue) == 0)
- gamma.green=gamma.red;
- gamma.blue=geometry_info.xi;
- if ((flags & XiValue) == 0)
- gamma.blue=gamma.red;
- if ((gamma.red == 1.0) && (gamma.green == 1.0) && (gamma.blue == 1.0))
- return(MagickTrue);
- if ((gamma.red == gamma.green) && (gamma.green == gamma.blue))
- status=GammaImageChannel(image,(const ChannelType) (RedChannel |
- GreenChannel | BlueChannel),(double) gamma.red);
- else
- {
- status=GammaImageChannel(image,RedChannel,(double) gamma.red);
- status|=GammaImageChannel(image,GreenChannel,(double) gamma.green);
- status|=GammaImageChannel(image,BlueChannel,(double) gamma.blue);
- }
- return(status != 0 ? MagickTrue : MagickFalse);
-}
-
-MagickExport MagickBooleanType GammaImageChannel(Image *image,
- const ChannelType channel,const double gamma)
+%
+% The format of the GammaImage method is:
+%
+% MagickBooleanType GammaImage(Image *image,const double gamma,
+% ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o level: the image gamma as a string (e.g. 1.6,1.2,1.0).
+%
+% o gamma: the image gamma.
+%
+*/
+MagickExport MagickBooleanType GammaImage(Image *image,const double gamma,
+ ExceptionInfo *exception)
{
#define GammaCorrectImageTag "GammaCorrect/Image"
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
image->filename);
(void) ResetMagickMemory(gamma_map,0,(MaxMap+1)*sizeof(*gamma_map));
if (gamma != 0.0)
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4)
+#if defined(MAGICKCORE_OPENMP_SUPPORT) && (MaxMap > 256)
+ #pragma omp parallel for
#endif
for (i=0; i <= (ssize_t) MaxMap; i++)
- gamma_map[i]=ClampToQuantum((MagickRealType) ScaleMapToQuantum((
- MagickRealType) (MaxMap*pow((double) i/MaxMap,1.0/gamma))));
+ gamma_map[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*pow((double) i/
+ MaxMap,1.0/gamma)));
if (image->storage_class == PseudoClass)
{
/*
Gamma-correct colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].red=gamma_map[
- ScaleQuantumToMap(image->colormap[i].red)];
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].green=gamma_map[
- ScaleQuantumToMap(image->colormap[i].green)];
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].blue=gamma_map[
- ScaleQuantumToMap(image->colormap[i].blue)];
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].alpha=gamma_map[
- ScaleQuantumToMap(image->colormap[i].alpha)];
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].red=(MagickRealType) gamma_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red))];
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].green=(MagickRealType) gamma_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green))];
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].blue=(MagickRealType) gamma_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue))];
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].alpha=(MagickRealType) gamma_map[
+ ScaleQuantumToMap(ClampToQuantum(image->colormap[i].alpha))];
}
}
/*
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (channel == DefaultChannels)
- {
- SetPixelRed(image,gamma_map[
- ScaleQuantumToMap(GetPixelRed(image,q))],q);
- SetPixelGreen(image,gamma_map[
- ScaleQuantumToMap(GetPixelGreen(image,q))],q);
- SetPixelBlue(image,gamma_map[ScaleQuantumToMap(
- GetPixelBlue(image,q))],q);
- }
- else
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,gamma_map[ScaleQuantumToMap(
- GetPixelRed(image,q))],q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,gamma_map[
- ScaleQuantumToMap(GetPixelGreen(image,q))],q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,gamma_map[
- ScaleQuantumToMap(GetPixelBlue(image,q))],q);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- {
- if (image->matte == MagickFalse)
- SetPixelAlpha(image,gamma_map[
- ScaleQuantumToMap(GetPixelAlpha(image,q))],q);
- else
- SetPixelAlpha(image,gamma_map[
- ScaleQuantumToMap(GetPixelAlpha(image,q))],q);
- }
+ q+=GetPixelChannels(image);
+ continue;
}
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=gamma_map[ScaleQuantumToMap(q[i])];
+ }
q+=GetPixelChannels(image);
}
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- for (x=0; x < (ssize_t) image->columns; x++)
- SetPixelBlack(image,gamma_map[ScaleQuantumToMap(
- GetPixelBlack(image,q))],q);
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_GammaImageChannel)
+ #pragma omp critical (MagickCore_GammaImage)
#endif
proceed=SetImageProgress(image,GammaCorrectImageTag,progress++,
image->rows);
%
% The format of the HaldClutImage method is:
%
-% MagickBooleanType HaldClutImage(Image *image,Image *hald_image)
-% MagickBooleanType HaldClutImageChannel(Image *image,
-% const ChannelType channel,Image *hald_image)
+% MagickBooleanType HaldClutImage(Image *image,Image *hald_image,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o hald_image: the color lookup table image for replacement color values.
%
-% o channel: the channel.
+% o exception: return any errors or warnings in this structure.
%
*/
}
MagickExport MagickBooleanType HaldClutImage(Image *image,
- const Image *hald_image)
-{
- return(HaldClutImageChannel(image,DefaultChannels,hald_image));
-}
-
-MagickExport MagickBooleanType HaldClutImageChannel(Image *image,
- const ChannelType channel,const Image *hald_image)
+ const Image *hald_image,ExceptionInfo *exception)
{
#define HaldClutImageTag "Clut/Image"
double
width;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(hald_image != (Image *) NULL);
assert(hald_image->signature == MagickSignature);
- if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+ if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
+ if (IsGrayColorspace(image->colorspace) != MagickFalse)
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
if (image->matte == MagickFalse)
- (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
+ (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
/*
Hald clut image.
*/
cube_size=level*level;
width=(double) hald_image->columns;
GetPixelInfo(hald_image,&zero);
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
- hald_view=AcquireCacheView(hald_image);
+ hald_view=AcquireVirtualCacheView(hald_image,exception);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
- double
- offset;
-
- HaldInfo
- point;
-
- PixelInfo
- pixel,
- pixel1,
- pixel2,
- pixel3,
- pixel4;
-
register Quantum
*restrict q;
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
- pixel=zero;
- pixel1=zero;
- pixel2=zero;
- pixel3=zero;
- pixel4=zero;
for (x=0; x < (ssize_t) image->columns; x++)
{
+ double
+ offset;
+
+ HaldInfo
+ point;
+
+ PixelInfo
+ pixel,
+ pixel1,
+ pixel2,
+ pixel3,
+ pixel4;
+
point.x=QuantumScale*(level-1.0)*GetPixelRed(image,q);
point.y=QuantumScale*(level-1.0)*GetPixelGreen(image,q);
point.z=QuantumScale*(level-1.0)*GetPixelBlue(image,q);
point.x-=floor(point.x);
point.y-=floor(point.y);
point.z-=floor(point.z);
- (void) InterpolatePixelInfo(image,hald_view,
- UndefinedInterpolatePixel,fmod(offset,width),floor(offset/width),
- &pixel1,exception);
- (void) InterpolatePixelInfo(image,hald_view,
- UndefinedInterpolatePixel,fmod(offset+level,width),floor((offset+level)/
- width),&pixel2,exception);
- CompositePixelInfoAreaBlend(&pixel1,pixel1.alpha,&pixel2,
- pixel2.alpha,point.y,&pixel3);
+ pixel1=zero;
+ (void) InterpolatePixelInfo(image,hald_view,image->interpolate,
+ fmod(offset,width),floor(offset/width),&pixel1,exception);
+ pixel2=zero;
+ (void) InterpolatePixelInfo(image,hald_view,image->interpolate,
+ fmod(offset+level,width),floor((offset+level)/width),&pixel2,exception);
+ pixel3=zero;
+ CompositePixelInfoAreaBlend(&pixel1,pixel1.alpha,&pixel2,pixel2.alpha,
+ point.y,&pixel3);
offset+=cube_size;
- (void) InterpolatePixelInfo(image,hald_view,
- UndefinedInterpolatePixel,fmod(offset,width),floor(offset/width),
- &pixel1,exception);
- (void) InterpolatePixelInfo(image,hald_view,
- UndefinedInterpolatePixel,fmod(offset+level,width),floor((offset+level)/
- width),&pixel2,exception);
- CompositePixelInfoAreaBlend(&pixel1,pixel1.alpha,&pixel2,
- pixel2.alpha,point.y,&pixel4);
- CompositePixelInfoAreaBlend(&pixel3,pixel3.alpha,&pixel4,
- pixel4.alpha,point.z,&pixel);
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,
- ClampToQuantum(pixel.red),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,
- ClampToQuantum(pixel.green),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,
- ClampToQuantum(pixel.blue),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
+ (void) InterpolatePixelInfo(image,hald_view,image->interpolate,
+ fmod(offset,width),floor(offset/width),&pixel1,exception);
+ (void) InterpolatePixelInfo(image,hald_view,image->interpolate,
+ fmod(offset+level,width),floor((offset+level)/width),&pixel2,exception);
+ pixel4=zero;
+ CompositePixelInfoAreaBlend(&pixel1,pixel1.alpha,&pixel2,pixel2.alpha,
+ point.y,&pixel4);
+ pixel=zero;
+ CompositePixelInfoAreaBlend(&pixel3,pixel3.alpha,&pixel4,pixel4.alpha,
+ point.z,&pixel);
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ SetPixelRed(image,ClampToQuantum(pixel.red),q);
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ SetPixelGreen(image,ClampToQuantum(pixel.green),q);
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
(image->colorspace == CMYKColorspace))
- SetPixelBlack(image,
- ClampToQuantum(pixel.black),q);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) && (image->matte != MagickFalse))
- SetPixelAlpha(image,
- ClampToQuantum(pixel.alpha),q);
+ SetPixelBlack(image,ClampToQuantum(pixel.black),q);
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+ (image->matte != MagickFalse))
+ SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_HaldClutImageChannel)
+ #pragma omp critical (MagickCore_HaldClutImage)
#endif
proceed=SetImageProgress(image,HaldClutImageTag,progress++,image->rows);
if (proceed == MagickFalse)
%
% If a '!' flag is given, map black and white colors to the given levels
% rather than mapping those levels to black and white. See
-% LevelizeImageChannel() and LevelizeImageChannel(), below.
+% LevelizeImage() below.
%
% Gamma specifies a gamma correction to apply to the image.
%
% The format of the LevelImage method is:
%
-% MagickBooleanType LevelImage(Image *image,const char *levels)
+% MagickBooleanType LevelImage(Image *image,const double black_point,
+% const double white_point,const double gamma,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o levels: Specify the levels where the black and white points have the
-% range of 0-QuantumRange, and gamma has the range 0-10 (e.g. 10x90%+2).
-% A '!' flag inverts the re-mapping.
+% o black_point: The level to map zero (black) to.
+%
+% o white_point: The level to map QuantumRange (white) to.
+%
+% o exception: return any errors or warnings in this structure.
%
*/
-MagickExport MagickBooleanType LevelImage(Image *image,const char *levels)
+static inline MagickRealType LevelPixel(const double black_point,
+ const double white_point,const double gamma,const MagickRealType pixel)
{
double
- black_point,
- gamma,
- white_point;
-
- GeometryInfo
- geometry_info;
-
- MagickBooleanType
- status;
-
- MagickStatusType
- flags;
+ level_pixel,
+ scale;
- /*
- Parse levels.
- */
- if (levels == (char *) NULL)
- return(MagickFalse);
- flags=ParseGeometry(levels,&geometry_info);
- black_point=geometry_info.rho;
- white_point=(double) QuantumRange;
- if ((flags & SigmaValue) != 0)
- white_point=geometry_info.sigma;
- gamma=1.0;
- if ((flags & XiValue) != 0)
- gamma=geometry_info.xi;
- if ((flags & PercentValue) != 0)
- {
- black_point*=(double) image->columns*image->rows/100.0;
- white_point*=(double) image->columns*image->rows/100.0;
- }
- if ((flags & SigmaValue) == 0)
- white_point=(double) QuantumRange-black_point;
- if ((flags & AspectValue ) == 0)
- status=LevelImageChannel(image,DefaultChannels,black_point,white_point,
- gamma);
- else
- status=LevelizeImage(image,black_point,white_point,gamma);
- return(status);
+ if (pixel < black_point)
+ return(0.0);
+ if (pixel > white_point)
+ return((MagickRealType) QuantumRange);
+ scale=(white_point != black_point) ? 1.0/(white_point-black_point) : 1.0;
+ level_pixel=(MagickRealType) QuantumRange*pow(scale*((double) pixel-
+ black_point),1.0/gamma);
+ return(level_pixel);
}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% L e v e l i z e I m a g e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% LevelizeImage() applies the normal level operation to the image, spreading
-% out the values between the black and white points over the entire range of
-% values. Gamma correction is also applied after the values has been mapped.
-%
-% It is typically used to improve image contrast, or to provide a controlled
-% linear threshold for the image. If the black and white points are set to
-% the minimum and maximum values found in the image, the image can be
-% normalized. or by swapping black and white values, negate the image.
-%
-% The format of the LevelizeImage method is:
-%
-% MagickBooleanType LevelizeImage(Image *image,const double black_point,
-% const double white_point,const double gamma)
-% MagickBooleanType LevelizeImageChannel(Image *image,
-% const ChannelType channel,const double black_point,
-% const double white_point,const double gamma)
-%
-% A description of each parameter follows:
-%
-% o image: the image.
-%
-% o channel: the channel.
-%
-% o black_point: The level which is to be mapped to zero (black)
-%
-% o white_point: The level which is to be mapped to QuantiumRange (white)
-%
-% o gamma: adjust gamma by this factor before mapping values.
-% use 1.0 for purely linear stretching of image color values
-%
-*/
-MagickExport MagickBooleanType LevelImageChannel(Image *image,
- const ChannelType channel,const double black_point,const double white_point,
- const double gamma)
+
+MagickExport MagickBooleanType LevelImage(Image *image,const double black_point,
+ const double white_point,const double gamma,ExceptionInfo *exception)
{
#define LevelImageTag "Level/Image"
-#define LevelQuantum(x) (ClampToQuantum((MagickRealType) QuantumRange* \
- pow(scale*((double) (x)-black_point),1.0/gamma)))
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
MagickOffsetType
progress;
- register double
- scale;
-
register ssize_t
i;
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- scale=(white_point != black_point) ? 1.0/(white_point-black_point) : 1.0;
if (image->storage_class == PseudoClass)
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
/*
Level colormap.
*/
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].red=LevelQuantum(image->colormap[i].red);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].green=LevelQuantum(image->colormap[i].green);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].blue=LevelQuantum(image->colormap[i].blue);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].alpha=LevelQuantum(image->colormap[i].alpha);
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].red=(double) ClampToQuantum(LevelPixel(black_point,
+ white_point,gamma,image->colormap[i].red));
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].green=(double) ClampToQuantum(LevelPixel(black_point,
+ white_point,gamma,image->colormap[i].green));
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].blue=(double) ClampToQuantum(LevelPixel(black_point,
+ white_point,gamma,image->colormap[i].blue));
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].alpha=(double) ClampToQuantum(LevelPixel(black_point,
+ white_point,gamma,image->colormap[i].alpha));
}
/*
Level image.
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,LevelQuantum(
- GetPixelRed(image,q)),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,
- LevelQuantum(GetPixelGreen(image,q)),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,
- LevelQuantum(GetPixelBlue(image,q)),q);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
- (image->matte == MagickTrue))
- SetPixelAlpha(image,
- LevelQuantum(GetPixelAlpha(image,q)),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,
- LevelQuantum(GetPixelBlack(image,q)),q);
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=ClampToQuantum(LevelPixel(black_point,white_point,gamma,
+ (MagickRealType) q[i]));
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_LevelImageChannel)
+ #pragma omp critical (MagickCore_LevelImage)
#endif
proceed=SetImageProgress(image,LevelImageTag,progress++,image->rows);
if (proceed == MagickFalse)
% %
% %
% %
-% L e v e l i z e I m a g e C h a n n e l %
+% L e v e l i z e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% LevelizeImageChannel() applies the reversed LevelImage() operation to just
+% LevelizeImage() applies the reversed LevelImage() operation to just
% the specific channels specified. It compresses the full range of color
% values, so that they lie between the given black and white points. Gamma is
% applied before the values are mapped.
%
-% LevelizeImageChannel() can be called with by using a +level command line
+% LevelizeImage() can be called with by using a +level command line
% API option, or using a '!' on a -level or LevelImage() geometry string.
%
-% It can be used for example de-contrast a greyscale image to the exact
-% levels specified. Or by using specific levels for each channel of an image
-% you can convert a gray-scale image to any linear color gradient, according
-% to those levels.
+% It can be used to de-contrast a greyscale image to the exact levels
+% specified. Or by using specific levels for each channel of an image you
+% can convert a gray-scale image to any linear color gradient, according to
+% those levels.
%
-% The format of the LevelizeImageChannel method is:
+% The format of the LevelizeImage method is:
%
-% MagickBooleanType LevelizeImageChannel(Image *image,
-% const ChannelType channel,const char *levels)
+% MagickBooleanType LevelizeImage(Image *image,const double black_point,
+% const double white_point,const double gamma,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
-%
% o black_point: The level to map zero (black) to.
%
-% o white_point: The level to map QuantiumRange (white) to.
+% o white_point: The level to map QuantumRange (white) to.
%
% o gamma: adjust gamma by this factor before mapping values.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-
MagickExport MagickBooleanType LevelizeImage(Image *image,
- const double black_point,const double white_point,const double gamma)
-{
- MagickBooleanType
- status;
-
- status=LevelizeImageChannel(image,DefaultChannels,black_point,white_point,
- gamma);
- return(status);
-}
-
-MagickExport MagickBooleanType LevelizeImageChannel(Image *image,
- const ChannelType channel,const double black_point,const double white_point,
- const double gamma)
+ const double black_point,const double white_point,const double gamma,
+ ExceptionInfo *exception)
{
#define LevelizeImageTag "Levelize/Image"
#define LevelizeValue(x) (ClampToQuantum(((MagickRealType) \
- pow((double)(QuantumScale*(x)),1.0/gamma))*(white_point-black_point)+ \
+ pow((double) (QuantumScale*(x)),1.0/gamma))*(white_point-black_point)+ \
black_point))
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if (image->storage_class == PseudoClass)
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
/*
Level colormap.
*/
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].red=LevelizeValue(image->colormap[i].red);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].green=LevelizeValue(image->colormap[i].green);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].blue=LevelizeValue(image->colormap[i].blue);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].alpha=LevelizeValue(image->colormap[i].alpha);
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].red=(double) LevelizeValue(
+ image->colormap[i].red);
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].green=(double) LevelizeValue(
+ image->colormap[i].green);
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].blue=(double) LevelizeValue(
+ image->colormap[i].blue);
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].alpha=(double) LevelizeValue(
+ image->colormap[i].alpha);
}
/*
Level image.
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,LevelizeValue(GetPixelRed(image,q)),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,LevelizeValue(GetPixelGreen(image,q)),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,LevelizeValue(GetPixelBlue(image,q)),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,LevelizeValue(GetPixelBlack(image,q)),q);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
- (image->matte == MagickTrue))
- SetPixelAlpha(image,LevelizeValue(GetPixelAlpha(image,q)),q);
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=LevelizeValue(q[i]);
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_LevelizeImageChannel)
+ #pragma omp critical (MagickCore_LevelizeImage)
#endif
proceed=SetImageProgress(image,LevelizeImageTag,progress++,image->rows);
if (proceed == MagickFalse)
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% LevelImageColor() maps the given color to "black" and "white" values,
+% LevelImageColors() maps the given color to "black" and "white" values,
% linearly spreading out the colors, and level values on a channel by channel
% bases, as per LevelImage(). The given colors allows you to specify
% different level ranges for each of the color channels separately.
% appropriatally. This effectivally maps a greyscale gradient into the given
% color gradient.
%
-% The format of the LevelColorsImageChannel method is:
+% The format of the LevelImageColors method is:
%
-% MagickBooleanType LevelColorsImage(Image *image,
-% const PixelInfo *black_color,
-% const PixelInfo *white_color,const MagickBooleanType invert)
-% MagickBooleanType LevelColorsImageChannel(Image *image,
-% const ChannelType channel,const PixelInfo *black_color,
-% const PixelInfo *white_color,const MagickBooleanType invert)
+% MagickBooleanType LevelImageColors(Image *image,
+% const PixelInfo *black_color,const PixelInfo *white_color,
+% const MagickBooleanType invert,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
-%
% o black_color: The color to map black to/from
%
% o white_point: The color to map white to/from
%
% o invert: if true map the colors (levelize), rather than from (level)
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-
-MagickExport MagickBooleanType LevelColorsImage(Image *image,
+MagickExport MagickBooleanType LevelImageColors(Image *image,
const PixelInfo *black_color,const PixelInfo *white_color,
- const MagickBooleanType invert)
+ const MagickBooleanType invert,ExceptionInfo *exception)
{
- MagickBooleanType
- status;
-
- status=LevelColorsImageChannel(image,DefaultChannels,black_color,white_color,
- invert);
- return(status);
-}
+ ChannelType
+ channel_mask;
-MagickExport MagickBooleanType LevelColorsImageChannel(Image *image,
- const ChannelType channel,const PixelInfo *black_color,
- const PixelInfo *white_color,const MagickBooleanType invert)
-{
MagickStatusType
status;
status=MagickFalse;
if (invert == MagickFalse)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- status|=LevelImageChannel(image,RedChannel,
- black_color->red,white_color->red,(double) 1.0);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- status|=LevelImageChannel(image,GreenChannel,
- black_color->green,white_color->green,(double) 1.0);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- status|=LevelImageChannel(image,BlueChannel,
- black_color->blue,white_color->blue,(double) 1.0);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel_mask=SetPixelChannelMask(image,RedChannel);
+ status|=LevelImage(image,black_color->red,white_color->red,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel_mask=SetPixelChannelMask(image,GreenChannel);
+ status|=LevelImage(image,black_color->green,white_color->green,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel_mask=SetPixelChannelMask(image,BlueChannel);
+ status|=LevelImage(image,black_color->blue,white_color->blue,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
(image->colorspace == CMYKColorspace))
- status|=LevelImageChannel(image,BlackChannel,
- black_color->black,white_color->black,(double) 1.0);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
+ {
+ channel_mask=SetPixelChannelMask(image,BlackChannel);
+ status|=LevelImage(image,black_color->black,white_color->black,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
(image->matte == MagickTrue))
- status|=LevelImageChannel(image,OpacityChannel,
- black_color->alpha,white_color->alpha,(double) 1.0);
+ {
+ channel_mask=SetPixelChannelMask(image,AlphaChannel);
+ status|=LevelImage(image,black_color->alpha,white_color->alpha,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
}
else
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- status|=LevelizeImageChannel(image,RedChannel,
- black_color->red,white_color->red,(double) 1.0);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- status|=LevelizeImageChannel(image,GreenChannel,
- black_color->green,white_color->green,(double) 1.0);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- status|=LevelizeImageChannel(image,BlueChannel,
- black_color->blue,white_color->blue,(double) 1.0);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel_mask=SetPixelChannelMask(image,RedChannel);
+ status|=LevelizeImage(image,black_color->red,white_color->red,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel_mask=SetPixelChannelMask(image,GreenChannel);
+ status|=LevelizeImage(image,black_color->green,white_color->green,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ {
+ channel_mask=SetPixelChannelMask(image,BlueChannel);
+ status|=LevelizeImage(image,black_color->blue,white_color->blue,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
(image->colorspace == CMYKColorspace))
- status|=LevelizeImageChannel(image,BlackChannel,
- black_color->black,white_color->black,(double) 1.0);
- if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
+ {
+ channel_mask=SetPixelChannelMask(image,BlackChannel);
+ status|=LevelizeImage(image,black_color->black,white_color->black,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
+ if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
(image->matte == MagickTrue))
- status|=LevelizeImageChannel(image,OpacityChannel,
- black_color->alpha,white_color->alpha,(double) 1.0);
+ {
+ channel_mask=SetPixelChannelMask(image,AlphaChannel);
+ status|=LevelizeImage(image,black_color->alpha,white_color->alpha,1.0,
+ exception);
+ (void) SetPixelChannelMask(image,channel_mask);
+ }
}
return(status == 0 ? MagickFalse : MagickTrue);
}
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% The LinearStretchImage() discards any pixels below the black point and
-% above the white point and levels the remaining pixels.
+% LinearStretchImage() discards any pixels below the black point and above
+% the white point and levels the remaining pixels.
%
% The format of the LinearStretchImage method is:
%
% MagickBooleanType LinearStretchImage(Image *image,
-% const double black_point,const double white_point)
+% const double black_point,const double white_point,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o white_point: the white point.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
MagickExport MagickBooleanType LinearStretchImage(Image *image,
- const double black_point,const double white_point)
+ const double black_point,const double white_point,ExceptionInfo *exception)
{
#define LinearStretchImageTag "LinearStretch/Image"
- ExceptionInfo
- *exception;
+ CacheView
+ *image_view;
MagickBooleanType
status;
Form histogram.
*/
(void) ResetMagickMemory(histogram,0,(MaxMap+1)*sizeof(*histogram));
- exception=(&image->exception);
+ image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (ssize_t) image->rows; y++)
{
register const Quantum
register ssize_t
x;
- p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+ p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
- for (x=(ssize_t) image->columns-1; x >= 0; x--)
+ for (x=0; x < (ssize_t) image->columns; x++)
{
histogram[ScaleQuantumToMap(GetPixelIntensity(image,p))]++;
p+=GetPixelChannels(image);
}
}
+ image_view=DestroyCacheView(image_view);
/*
Find the histogram boundaries by locating the black and white point levels.
*/
break;
}
histogram=(MagickRealType *) RelinquishMagickMemory(histogram);
- status=LevelImageChannel(image,DefaultChannels,(double) black,(double) white,
- 1.0);
+ status=LevelImage(image,(double) black,(double) white,1.0,exception);
return(status);
}
\f
%
% The format of the ModulateImage method is:
%
-% MagickBooleanType ModulateImage(Image *image,const char *modulate)
+% MagickBooleanType ModulateImage(Image *image,const char *modulate,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o modulate: Define the percent change in brightness, saturation, and
-% hue.
+% o modulate: Define the percent change in brightness, saturation, and hue.
+%
+% o exception: return any errors or warnings in this structure.
%
*/
static void ModulateHSB(const double percent_hue,
- const double percent_saturation,const double percent_brightness,
- Quantum *red,Quantum *green,Quantum *blue)
+ const double percent_saturation,const double percent_brightness,double *red,
+ double *green,double *blue)
{
double
brightness,
/*
Increase or decrease color brightness, saturation, or hue.
*/
- assert(red != (Quantum *) NULL);
- assert(green != (Quantum *) NULL);
- assert(blue != (Quantum *) NULL);
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
ConvertRGBToHSB(*red,*green,*blue,&hue,&saturation,&brightness);
hue+=0.5*(0.01*percent_hue-1.0);
while (hue < 0.0)
}
static void ModulateHSL(const double percent_hue,
- const double percent_saturation,const double percent_lightness,
- Quantum *red,Quantum *green,Quantum *blue)
+ const double percent_saturation,const double percent_lightness,double *red,
+ double *green,double *blue)
{
double
hue,
/*
Increase or decrease color lightness, saturation, or hue.
*/
- assert(red != (Quantum *) NULL);
- assert(green != (Quantum *) NULL);
- assert(blue != (Quantum *) NULL);
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
ConvertRGBToHSL(*red,*green,*blue,&hue,&saturation,&lightness);
hue+=0.5*(0.01*percent_hue-1.0);
while (hue < 0.0)
ConvertHSLToRGB(hue,saturation,lightness,red,green,blue);
}
-static void ModulateHWB(const double percent_hue,const double percent_whiteness, const double percent_blackness,Quantum *red,Quantum *green,Quantum *blue)
+static void ModulateHWB(const double percent_hue,const double percent_whiteness, const double percent_blackness,double *red,double *green,double *blue)
{
double
blackness,
/*
Increase or decrease color blackness, whiteness, or hue.
*/
- assert(red != (Quantum *) NULL);
- assert(green != (Quantum *) NULL);
- assert(blue != (Quantum *) NULL);
+ assert(red != (double *) NULL);
+ assert(green != (double *) NULL);
+ assert(blue != (double *) NULL);
ConvertRGBToHWB(*red,*green,*blue,&hue,&whiteness,&blackness);
hue+=0.5*(0.01*percent_hue-1.0);
while (hue < 0.0)
ConvertHWBToRGB(hue,whiteness,blackness,red,green,blue);
}
-MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate)
+MagickExport MagickBooleanType ModulateImage(Image *image,const char *modulate,
+ ExceptionInfo *exception)
{
#define ModulateImageTag "Modulate/Image"
percent_hue,
percent_saturation;
- ExceptionInfo
- *exception;
-
GeometryInfo
geometry_info;
Modulate colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
switch (colorspace)
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
- Quantum
+ double
blue,
green,
red;
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- red=GetPixelRed(image,q);
- green=GetPixelGreen(image,q);
- blue=GetPixelBlue(image,q);
+ red=(double) GetPixelRed(image,q);
+ green=(double) GetPixelGreen(image,q);
+ blue=(double) GetPixelBlue(image,q);
switch (colorspace)
{
case HSBColorspace:
break;
}
}
- SetPixelRed(image,red,q);
- SetPixelGreen(image,green,q);
- SetPixelBlue(image,blue,q);
+ SetPixelRed(image,ClampToQuantum(red),q);
+ SetPixelGreen(image,ClampToQuantum(green),q);
+ SetPixelBlue(image,ClampToQuantum(blue),q);
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_ModulateImage)
+ #pragma omp critical (MagickCore_ModulateImage)
#endif
proceed=SetImageProgress(image,ModulateImageTag,progress++,image->rows);
if (proceed == MagickFalse)
% NegateImage() negates the colors in the reference image. The grayscale
% option means that only grayscale values within the image are negated.
%
-% The format of the NegateImageChannel method is:
+% The format of the NegateImage method is:
%
% MagickBooleanType NegateImage(Image *image,
-% const MagickBooleanType grayscale)
-% MagickBooleanType NegateImageChannel(Image *image,
-% const ChannelType channel,const MagickBooleanType grayscale)
+% const MagickBooleanType grayscale,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
-%
% o grayscale: If MagickTrue, only negate grayscale pixels within the image.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-
MagickExport MagickBooleanType NegateImage(Image *image,
- const MagickBooleanType grayscale)
-{
- MagickBooleanType
- status;
-
- status=NegateImageChannel(image,DefaultChannels,grayscale);
- return(status);
-}
-
-MagickExport MagickBooleanType NegateImageChannel(Image *image,
- const ChannelType channel,const MagickBooleanType grayscale)
+ const MagickBooleanType grayscale,ExceptionInfo *exception)
{
#define NegateImageTag "Negate/Image"
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
Negate colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
if ((image->colormap[i].red != image->colormap[i].green) ||
(image->colormap[i].green != image->colormap[i].blue))
continue;
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].red=(Quantum) QuantumRange-
image->colormap[i].red;
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].green=(Quantum) QuantumRange-
image->colormap[i].green;
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].blue=(Quantum) QuantumRange-
image->colormap[i].blue;
}
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
if (grayscale != MagickFalse)
{
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRed(image,q) != GetPixelGreen(image,q)) ||
- (GetPixelGreen(image,q) != GetPixelBlue(image,q)))
+ register ssize_t
+ i;
+
+ if ((GetPixelMask(image,q) != 0) ||
+ (IsPixelGray(image,q) != MagickFalse))
{
q+=GetPixelChannels(image);
continue;
}
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,QuantumRange-GetPixelRed(image,q),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,QuantumRange-GetPixelGreen(image,q),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,QuantumRange-GetPixelBlue(image,q),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,QuantumRange-GetPixelBlack(image,q),q);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- SetPixelAlpha(image,QuantumRange-GetPixelAlpha(image,q),q);
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=QuantumRange-q[i];
+ }
q+=GetPixelChannels(image);
}
sync=SyncCacheViewAuthenticPixels(image_view,exception);
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_NegateImageChannel)
+ #pragma omp critical (MagickCore_NegateImage)
#endif
proceed=SetImageProgress(image,NegateImageTag,progress++,
image->rows);
Negate image.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,QuantumRange-GetPixelRed(image,q),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,QuantumRange-GetPixelGreen(image,q),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,QuantumRange-GetPixelBlue(image,q),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,QuantumRange-GetPixelBlack(image,q),q);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- SetPixelAlpha(image,QuantumRange-GetPixelAlpha(image,q),q);
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=QuantumRange-q[i];
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_NegateImageChannel)
+ #pragma omp critical (MagickCore_NegateImage)
#endif
proceed=SetImageProgress(image,NegateImageTag,progress++,image->rows);
if (proceed == MagickFalse)
%
% The format of the NormalizeImage method is:
%
-% MagickBooleanType NormalizeImage(Image *image)
-% MagickBooleanType NormalizeImageChannel(Image *image,
-% const ChannelType channel)
+% MagickBooleanType NormalizeImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
+% o exception: return any errors or warnings in this structure.
%
*/
-
-MagickExport MagickBooleanType NormalizeImage(Image *image)
-{
- MagickBooleanType
- status;
-
- status=NormalizeImageChannel(image,DefaultChannels);
- return(status);
-}
-
-MagickExport MagickBooleanType NormalizeImageChannel(Image *image,
- const ChannelType channel)
+MagickExport MagickBooleanType NormalizeImage(Image *image,
+ ExceptionInfo *exception)
{
double
black_point,
black_point=(double) image->columns*image->rows*0.0015;
white_point=(double) image->columns*image->rows*0.9995;
- return(ContrastStretchImageChannel(image,channel,black_point,white_point));
+ return(ContrastStretchImage(image,black_point,white_point,exception));
}
\f
/*
% The format of the SigmoidalContrastImage method is:
%
% MagickBooleanType SigmoidalContrastImage(Image *image,
-% const MagickBooleanType sharpen,const char *levels)
-% MagickBooleanType SigmoidalContrastImageChannel(Image *image,
-% const ChannelType channel,const MagickBooleanType sharpen,
-% const double contrast,const double midpoint)
+% const MagickBooleanType sharpen,const char *levels,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
-% o channel: the channel.
-%
% o sharpen: Increase or decrease image contrast.
%
% o alpha: strength of the contrast, the larger the number the more
%
% o beta: midpoint of the function as a color value 0 to QuantumRange.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-
MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
- const MagickBooleanType sharpen,const char *levels)
-{
- GeometryInfo
- geometry_info;
-
- MagickBooleanType
- status;
-
- MagickStatusType
- flags;
-
- flags=ParseGeometry(levels,&geometry_info);
- if ((flags & SigmaValue) == 0)
- geometry_info.sigma=1.0*QuantumRange/2.0;
- if ((flags & PercentValue) != 0)
- geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
- status=SigmoidalContrastImageChannel(image,DefaultChannels,sharpen,
- geometry_info.rho,geometry_info.sigma);
- return(status);
-}
-
-MagickExport MagickBooleanType SigmoidalContrastImageChannel(Image *image,
- const ChannelType channel,const MagickBooleanType sharpen,
- const double contrast,const double midpoint)
+ const MagickBooleanType sharpen,const double contrast,const double midpoint,
+ ExceptionInfo *exception)
{
#define SigmoidalContrastImageTag "SigmoidalContrast/Image"
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
image->filename);
(void) ResetMagickMemory(sigmoidal_map,0,(MaxMap+1)*sizeof(*sigmoidal_map));
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static) shared(progress,status)
#endif
for (i=0; i <= (ssize_t) MaxMap; i++)
{
if (sharpen != MagickFalse)
{
+#define sigmoidal(a,b,x) (1/(1+exp((a)*((b)-(x)))))
+#if 1
+ /* Simpilified function scaling,
+ * with better 'contrast=0' or 'flatline' handling (greyscale)
+ */
+ double
+ u0 = sigmoidal(contrast,QuantumScale*midpoint,0.0),
+ u1 = sigmoidal(contrast,QuantumScale*midpoint,1.0);
+ sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum(
+ (MagickRealType)(MaxMap*(
+ (sigmoidal(contrast,QuantumScale*midpoint,(double)i/MaxMap)
+ -(u0+u1)/2.0)/(u1-u0+MagickEpsilon)+0.5) ));
+#else
+ /* Scaled sigmoidal formula...
+ (1/(1+exp(a*(b-u))) - 1/(1+exp(a))) /
+ (1/(1+exp(a*(b-1)))/(1+exp(a)))) */
sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum((MagickRealType)
(MaxMap*((1.0/(1.0+exp(contrast*(midpoint/(double) QuantumRange-
(double) i/MaxMap))))-(1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange)))))/((1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange-1.0))))-(1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange)))))+0.5));
+#endif
continue;
}
+#if 1
+ {
+ /* Inverse -- See
+ http://osdir.com/ml/video.image-magick.devel/2005-04/msg00006.html
+ */
+ double
+ min = sigmoidal(contrast,1.0,0.0),
+ max = sigmoidal(contrast,QuantumScale*midpoint,1.0),
+ xi = min+(double)i/MaxMap*(max-min);
+ sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum(
+ (MagickRealType)(MaxMap*(
+ QuantumScale*midpoint-log((1-xi)/xi)/contrast) ));
+ }
+#else
+ /* expanded form of the above */
sigmoidal_map[i]=(MagickRealType) ScaleMapToQuantum((MagickRealType)
(MaxMap*(QuantumScale*midpoint-log((1.0-(1.0/(1.0+exp(midpoint/
(double) QuantumRange*contrast))+((double) i/MaxMap)*((1.0/
((double) i/MaxMap)*((1.0/(1.0+exp(contrast*(midpoint/
(double) QuantumRange-1.0))))-(1.0/(1.0+exp(midpoint/
(double) QuantumRange*contrast))))))/contrast)));
+#endif
}
if (image->storage_class == PseudoClass)
{
Sigmoidal-contrast enhance colormap.
*/
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (i=0; i < (ssize_t) image->colors; i++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].red=ClampToQuantum(sigmoidal_map[
- ScaleQuantumToMap(image->colormap[i].red)]);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].green=ClampToQuantum(sigmoidal_map[
- ScaleQuantumToMap(image->colormap[i].green)]);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].blue=ClampToQuantum(sigmoidal_map[
- ScaleQuantumToMap(image->colormap[i].blue)]);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- image->colormap[i].alpha=ClampToQuantum(sigmoidal_map[
- ScaleQuantumToMap(image->colormap[i].alpha)]);
+ if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].red=sigmoidal_map[ScaleQuantumToMap(
+ ClampToQuantum(image->colormap[i].red))];
+ if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].green=sigmoidal_map[ScaleQuantumToMap(
+ ClampToQuantum(image->colormap[i].green))];
+ if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].blue=sigmoidal_map[ScaleQuantumToMap(
+ ClampToQuantum(image->colormap[i].blue))];
+ if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
+ image->colormap[i].alpha=sigmoidal_map[ScaleQuantumToMap(
+ ClampToQuantum(image->colormap[i].alpha))];
}
}
/*
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
- image_view=AcquireCacheView(image);
+ image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+ #pragma omp parallel for schedule(static,4) shared(progress,status)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
- if (q == (const Quantum *) NULL)
+ if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
- SetPixelRed(image,ClampToQuantum(sigmoidal_map[ScaleQuantumToMap(
- GetPixelRed(image,q))]),q);
- if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
- SetPixelGreen(image,ClampToQuantum(sigmoidal_map[ScaleQuantumToMap(
- GetPixelGreen(image,q))]),q);
- if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
- SetPixelBlue(image,ClampToQuantum(sigmoidal_map[ScaleQuantumToMap(
- GetPixelBlue(image,q))]),q);
- if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,ClampToQuantum(sigmoidal_map[ScaleQuantumToMap(
- GetPixelBlack(image,q))]),q);
- if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
- SetPixelAlpha(image,ClampToQuantum(sigmoidal_map[ScaleQuantumToMap(
- GetPixelAlpha(image,q))]),q);
+ register ssize_t
+ i;
+
+ if (GetPixelMask(image,q) != 0)
+ {
+ q+=GetPixelChannels(image);
+ continue;
+ }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ traits;
+
+ channel=GetPixelChannelMapChannel(image,i);
+ traits=GetPixelChannelMapTraits(image,channel);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[i]=ClampToQuantum(sigmoidal_map[ScaleQuantumToMap(q[i])]);
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_SigmoidalContrastImageChannel)
+ #pragma omp critical (MagickCore_SigmoidalContrastImage)
#endif
proceed=SetImageProgress(image,SigmoidalContrastImageTag,progress++,
image->rows);