%
% The format of the AutoGammaImage method is:
%
-% MagickBooleanType AutoGammaImage(Image *image)
+% MagickBooleanType AutoGammaImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: The image to auto-level
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-MagickExport MagickBooleanType AutoGammaImage(Image *image)
+MagickExport MagickBooleanType AutoGammaImage(Image *image,
+ ExceptionInfo *exception)
{
- MagickStatusType
- status;
-
double
gamma,
log_mean,
mean,
sans;
+ MagickStatusType
+ status;
+
+ register ssize_t
+ i;
+
log_mean=log(0.5);
if (image->sync != MagickFalse)
{
/*
- Apply gamma correction equally accross all given channels
+ Apply gamma correction equally across all given channels.
*/
- (void) GetImageMean(image,&mean,&sans,&image->exception);
+ (void) GetImageMean(image,&mean,&sans,exception);
gamma=log(mean*QuantumScale)/log_mean;
- return(LevelImage(image,0.0,(double) QuantumRange,gamma));
+ return(LevelImage(image,0.0,(double) QuantumRange,gamma,exception));
}
/*
Auto-gamma each channel separately.
*/
status=MagickTrue;
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- {
- PushPixelChannelMap(image,RedChannel);
- (void) GetImageMean(image,&mean,&sans,&image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImage(image,0.0,(double) QuantumRange,gamma);
- PopPixelChannelMap(image);
- }
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- {
- PushPixelChannelMap(image,GreenChannel);
- (void) GetImageMean(image,&mean,&sans,&image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImage(image,0.0,(double) QuantumRange,gamma);
- PopPixelChannelMap(image);
- }
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- {
- PushPixelChannelMap(image,BlueChannel);
- (void) GetImageMean(image,&mean,&sans,&image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImage(image,0.0,(double) QuantumRange,gamma);
- PopPixelChannelMap(image);
- }
- if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- {
- PushPixelChannelMap(image,BlackChannel);
- (void) GetImageMean(image,&mean,&sans,&image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImage(image,0.0,(double) QuantumRange,gamma);
- PopPixelChannelMap(image);
- }
- if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
- (image->matte == MagickTrue))
- {
- PushPixelChannelMap(image,AlphaChannel);
- (void) GetImageMean(image,&mean,&sans,&image->exception);
- gamma=log(mean*QuantumScale)/log_mean;
- status=status && LevelImage(image,0.0,(double) QuantumRange,gamma);
- PopPixelChannelMap(image);
- }
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ ChannelType
+ channel_mask;
+
+ PixelTrait
+ traits;
+
+ traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ channel_mask=SetPixelChannelMask(image,(ChannelType) 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 AutoLevelImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: The image to auto-level
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-MagickExport MagickBooleanType AutoLevelImage(Image *image)
+MagickExport MagickBooleanType AutoLevelImage(Image *image,
+ ExceptionInfo *exception)
{
- return(MinMaxStretchImage(image,0.0,0.0));
+ return(MinMaxStretchImage(image,0.0,0.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)
+% const double brightness,const double contrast,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% 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)
+ 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=FunctionImage(image,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,
+% 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 channel: the channel.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image,
+ ExceptionInfo *exception)
+{
+#define ClutImageTag "Clut/Image"
+
+ CacheView
+ *clut_view,
+ *image_view;
+
+ double
+ *clut_map;
+
+ MagickBooleanType
+ status;
+
+ MagickOffsetType
+ progress;
+
+ register ssize_t
+ x;
+
+ 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);
+ clut_map=(double *) AcquireQuantumMemory(MaxMap+1UL,GetPixelChannels(image)*
+ sizeof(*clut_map));
+ if (clut_map == (double *) NULL)
+ ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+ image->filename);
+ /*
+ Clut image.
+ */
+ status=MagickTrue;
+ progress=0;
+ adjust=(ssize_t) (clut_image->interpolate == IntegerInterpolatePixel ? 0 : 1);
+ clut_view=AcquireCacheView(clut_image);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(dynamic,4)
+#endif
+ for (x=0; x <= (ssize_t) MaxMap; x++)
+ {
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(clut_image); i++)
+ (void) InterpolatePixelChannel(clut_image,clut_view,(PixelChannel) i,
+ UndefinedInterpolatePixel,QuantumScale*x*(clut_image->columns-adjust),
+ QuantumScale*x*(clut_image->rows-adjust),clut_map+x*
+ GetPixelChannels(clut_image)+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++)
+ {
+ 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;
+ }
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(clut_image); i++)
+ {
+ PixelChannel
+ channel;
+
+ PixelTrait
+ clut_traits,
+ traits;
+
+ clut_traits=GetPixelChannelMapTraits(clut_image,(PixelChannel) i);
+ if (clut_traits == UndefinedPixelTrait)
+ continue;
+ channel=GetPixelChannelMapChannel(clut_image,(PixelChannel) i);
+ traits=GetPixelChannelMapTraits(clut_image,channel);
+ if (traits == UndefinedPixelTrait)
+ continue;
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ q[channel]=ClampToQuantum(clut_map[ScaleQuantumToMap(q[channel])*
+ GetPixelChannels(clut_image)+channel]);
+ }
+ 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=(double *) 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;
(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");
#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+
+ 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+
+ 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+
+ cdl_map[i].blue=ClampToQuantum((MagickRealType) ScaleMapToQuantum(
+ (MagickRealType) (MaxMap*(pow(color_correction.blue.slope*i/MaxMap+
color_correction.blue.offset,color_correction.blue.power)))));
}
if (image->storage_class == PseudoClass)
for (i=0; i < (ssize_t) image->colors; i++)
{
double
- luma;
-
- 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);
- }
- }
- /*
- Apply transfer function to image.
- */
- status=MagickTrue;
- progress=0;
- exception=(&image->exception);
- 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++)
- {
- double
- luma;
-
- 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;
- }
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- luma=0.2126*GetPixelRed(image,q)+0.7152*GetPixelGreen(image,q)+0.0722*
- GetPixelBlue(image,q);
- SetPixelRed(image,ClampToQuantum(luma+color_correction.saturation*
- (cdl_map[ScaleQuantumToMap(GetPixelRed(image,q))].red-luma)),q);
- SetPixelGreen(image,ClampToQuantum(luma+color_correction.saturation*
- (cdl_map[ScaleQuantumToMap(GetPixelGreen(image,q))].green-luma)),q);
- SetPixelBlue(image,ClampToQuantum(luma+color_correction.saturation*
- (cdl_map[ScaleQuantumToMap(GetPixelBlue(image,q))].blue-luma)),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_ColorDecisionListImageChannel)
-#endif
- proceed=SetImageProgress(image,ColorDecisionListCorrectImageTag,
- progress++,image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- image_view=DestroyCacheView(image_view);
- cdl_map=(PixelPacket *) RelinquishMagickMemory(cdl_map);
- 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)
-%
-% 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 channel: the channel.
-%
-*/
-MagickExport MagickBooleanType ClutImage(Image *image,const Image *clut_image)
-{
-#define ClampAlphaPixelChannel(pixel) ClampToQuantum((pixel)->alpha)
-#define ClampBlackPixelChannel(pixel) ClampToQuantum((pixel)->black)
-#define ClampBluePixelChannel(pixel) ClampToQuantum((pixel)->blue)
-#define ClampGreenPixelChannel(pixel) ClampToQuantum((pixel)->green)
-#define ClampRedPixelChannel(pixel) ClampToQuantum((pixel)->red)
-#define ClutImageTag "Clut/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);
+ luma;
+
+ 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);
+ }
+ }
/*
- Clut image.
+ Apply transfer function to 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;
+ double
+ luma;
register Quantum
*restrict q;
status=MagickFalse;
continue;
}
- GetPixelInfo(image,&pixel);
for (x=0; x < (ssize_t) image->columns; x++)
{
- SetPixelInfo(image,q,&pixel);
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- SetPixelRed(image,ClampRedPixelChannel(clut_map+
- ScaleQuantumToMap(GetPixelRed(image,q))),q);
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- SetPixelGreen(image,ClampGreenPixelChannel(clut_map+
- ScaleQuantumToMap(GetPixelGreen(image,q))),q);
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- SetPixelBlue(image,ClampBluePixelChannel(clut_map+
- ScaleQuantumToMap(GetPixelBlue(image,q))),q);
- if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- SetPixelBlack(image,ClampBlackPixelChannel(clut_map+
- ScaleQuantumToMap(GetPixelBlack(image,q))),q);
- if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
- {
- if (clut_image->matte == MagickFalse)
- SetPixelAlpha(image,GetPixelInfoIntensity(clut_map+
- ScaleQuantumToMap((Quantum) GetPixelAlpha(image,q))),q);
- else
- if (image->matte == MagickFalse)
- SetPixelAlpha(image,ClampAlphaPixelChannel(clut_map+
- ScaleQuantumToMap((Quantum) GetPixelInfoIntensity(&pixel))),q);
- else
- SetPixelAlpha(image,ClampAlphaPixelChannel(clut_map+
- ScaleQuantumToMap(GetPixelAlpha(image,q))),q);
- }
+ luma=0.2126*GetPixelRed(image,q)+0.7152*GetPixelGreen(image,q)+0.0722*
+ GetPixelBlue(image,q);
+ SetPixelRed(image,ClampToQuantum(luma+color_correction.saturation*
+ (cdl_map[ScaleQuantumToMap(GetPixelRed(image,q))].red-luma)),q);
+ SetPixelGreen(image,ClampToQuantum(luma+color_correction.saturation*
+ (cdl_map[ScaleQuantumToMap(GetPixelGreen(image,q))].green-luma)),q);
+ SetPixelBlue(image,ClampToQuantum(luma+color_correction.saturation*
+ (cdl_map[ScaleQuantumToMap(GetPixelBlue(image,q))].blue-luma)),q);
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_ClutImage)
+ #pragma omp critical (MagickCore_ColorDecisionListImageChannel)
#endif
- proceed=SetImageProgress(image,ClutImageTag,progress++,image->rows);
+ proceed=SetImageProgress(image,ColorDecisionListCorrectImageTag,
+ 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);
+ cdl_map=(PixelPacket *) RelinquishMagickMemory(cdl_map);
return(status);
}
\f
% The format of the ContrastImage method is:
%
% MagickBooleanType ContrastImage(Image *image,
-% const MagickBooleanType sharpen)
+% const MagickBooleanType sharpen,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o sharpen: Increase or decrease image contrast.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
static void Contrast(const int sign,Quantum *red,Quantum *green,Quantum *blue)
}
MagickExport MagickBooleanType ContrastImage(Image *image,
- const MagickBooleanType sharpen)
+ const MagickBooleanType sharpen,ExceptionInfo *exception)
{
#define ContrastImageTag "Contrast/Image"
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
int
sign;
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
image_view=AcquireCacheView(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% 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)
+% const char *levels,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% 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 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;
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- histogram=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
- sizeof(*histogram));
- stretch_map=(PixelInfo *) AcquireQuantumMemory(MaxMap+1UL,
- sizeof(*stretch_map));
- if ((histogram == (PixelInfo *) NULL) ||
- (stretch_map == (PixelInfo *) NULL))
- ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
- image->filename);
+ 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=(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));
+ (void) ResetMagickMemory(histogram,0,(MaxMap+1)*GetPixelChannels(image)*
+ sizeof(*histogram));
image_view=AcquireCacheView(image);
for (y=0; y < (ssize_t) image->rows; y++)
{
status=MagickFalse;
continue;
}
- if (image->sync != MagickFalse)
- 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++)
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelRed(image,p))].red++;
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelGreen(image,p))].green++;
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelBlue(image,p))].blue++;
- if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- histogram[ScaleQuantumToMap(GetPixelBlack(image,p))].black++;
- if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
- histogram[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha++;
- p+=GetPixelChannels(image);
+ PixelTrait
+ traits;
+
+ traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ histogram[GetPixelChannels(image)*ScaleQuantumToMap(p[i])+i]++;
}
+ p+=GetPixelChannels(image);
+ }
}
/*
Find the histogram boundaries by locating the black/white levels.
*/
- black.red=0.0;
- white.red=MaxRange(QuantumRange);
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 0)
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+#endif
+ for (i=0; i < (ssize_t) GetPixelChannels(image); 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) & UpdatePixelTrait) != 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));
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
#endif
- for (i=0; i <= (ssize_t) MaxMap; i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 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) & UpdatePixelTrait) != 0) || (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 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)
#endif
- for (i=0; i < (ssize_t) image->colors; i++)
+ for (j=0; j < (ssize_t) image->colors; j++)
{
if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
{
- if (black.red != white.red)
+ i=GetPixelChannelMapChannel(image,RedPixelChannel);
+ if (black[i] != white[i])
image->colormap[i].red=ClampToQuantum(stretch_map[
- ScaleQuantumToMap(image->colormap[i].red)].red);
+ GetPixelChannels(image)*ScaleQuantumToMap(
+ image->colormap[i].red)]+i);
}
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[i].red=ClampToQuantum(stretch_map[
+ GetPixelChannels(image)*ScaleQuantumToMap(
+ image->colormap[i].red)]+i);
}
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[i].red=ClampToQuantum(stretch_map[
+ GetPixelChannels(image)*ScaleQuantumToMap(
+ image->colormap[i].red)]+i);
}
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[i].red=ClampToQuantum(stretch_map[
+ GetPixelChannels(image)*ScaleQuantumToMap(
+ image->colormap[i].red)]+i);
}
}
}
/*
- Stretch image.
+ Stretch-contrast image.
*/
status=MagickTrue;
progress=0;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- {
- if (black.red != white.red)
- SetPixelRed(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelRed(image,q))].red),q);
- }
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- {
- if (black.green != white.green)
- SetPixelGreen(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelGreen(image,q))].green),q);
- }
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- {
- if (black.blue != white.blue)
- SetPixelBlue(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelBlue(image,q))].blue),q);
- }
- if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
- (image->colorspace == CMYKColorspace))
- {
- if (black.black != white.black)
- SetPixelBlack(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelBlack(image,q))].black),q);
- }
- if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
- {
- if (black.alpha != white.alpha)
- SetPixelAlpha(image,ClampToQuantum(stretch_map[ScaleQuantumToMap(
- GetPixelAlpha(image,q))].alpha),q);
- }
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelTrait
+ traits;
+
+ traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ if ((traits & UpdatePixelTrait) == 0)
+ continue;
+ if (black[i] != white[i])
+ q[i]=ClampToQuantum(stretch_map[GetPixelChannels(image)*
+ ScaleQuantumToMap(q[i])+i]);
+ }
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
}
}
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
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);
}
%
% The format of the GammaImage method is:
%
-% MagickBooleanType GammaImage(Image *image,const double gamma)
+% MagickBooleanType GammaImage(Image *image,const double gamma,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o gamma: the image gamma.
%
*/
-MagickExport MagickBooleanType GammaImage(Image *image,const double 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((
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
image_view=AcquireCacheView(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (image->sync != MagickFalse)
- {
- 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
- {
- if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- SetPixelRed(image,gamma_map[ScaleQuantumToMap(
- GetPixelRed(image,q))],q);
- if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- SetPixelGreen(image,gamma_map[
- ScaleQuantumToMap(GetPixelGreen(image,q))],q);
- if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- SetPixelBlue(image,gamma_map[
- ScaleQuantumToMap(GetPixelBlue(image,q))],q);
- if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
- {
- if (image->matte == MagickFalse)
- SetPixelAlpha(image,gamma_map[
- ScaleQuantumToMap(GetPixelAlpha(image,q))],q);
- else
- SetPixelAlpha(image,gamma_map[
- ScaleQuantumToMap(GetPixelAlpha(image,q))],q);
- }
- }
+ register ssize_t
+ i;
+
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+ {
+ PixelTrait
+ traits;
+
+ traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
+ if ((traits & UpdatePixelTrait) != 0)
+ q[i]=gamma_map[ScaleQuantumToMap(q[i])];
+ }
q+=GetPixelChannels(image);
}
- if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 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)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(hald_image != (Image *) NULL);
assert(hald_image->signature == MagickSignature);
- if (SetImageStorageClass(image,DirectClass) == MagickFalse)
+ exception=(&image->exception);
+ if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
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);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
%
% 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 double black_point,const double white_point,const double gamma)
+ const double black_point,const double white_point,const double gamma,
+ ExceptionInfo *exception)
{
#define LevelImageTag "Level/Image"
#define LevelQuantum(x) (ClampToQuantum((MagickRealType) QuantumRange* \
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
image_view=AcquireCacheView(image);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
for (x=0; x < (ssize_t) image->columns; x++)
{
if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
- SetPixelRed(image,LevelQuantum(
- GetPixelRed(image,q)),q);
+ SetPixelRed(image,LevelQuantum(GetPixelRed(image,q)),q);
if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
- SetPixelGreen(image,
- LevelQuantum(GetPixelGreen(image,q)),q);
+ SetPixelGreen(image,LevelQuantum(GetPixelGreen(image,q)),q);
if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
- SetPixelBlue(image,
- LevelQuantum(GetPixelBlue(image,q)),q);
+ SetPixelBlue(image,LevelQuantum(GetPixelBlue(image,q)),q);
if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
(image->matte == MagickTrue))
- SetPixelAlpha(image,
- LevelQuantum(GetPixelAlpha(image,q)),q);
+ SetPixelAlpha(image,LevelQuantum(GetPixelAlpha(image,q)),q);
if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
(image->colorspace == CMYKColorspace))
- SetPixelBlack(image,
- LevelQuantum(GetPixelBlack(image,q)),q);
+ SetPixelBlack(image,LevelQuantum(GetPixelBlack(image,q)),q);
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
%
% 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.
%
const PixelInfo *black_color,const PixelInfo *white_color,
const MagickBooleanType invert)
{
+ ChannelType
+ channel_mask;
+
MagickStatusType
status;
{
if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
{
- PushPixelChannelMap(image,RedChannel);
- status|=LevelImage(image,black_color->red,white_color->red,1.0);
- PopPixelChannelMap(image);
+ channel_mask=SetPixelChannelMask(image,RedChannel);
+ status|=LevelImage(image,black_color->red,white_color->red,1.0,
+ &image->exception);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
{
- PushPixelChannelMap(image,GreenChannel);
- status|=LevelImage(image,black_color->green,white_color->green,1.0);
- PopPixelChannelMap(image);
+ channel_mask=SetPixelChannelMask(image,GreenChannel);
+ status|=LevelImage(image,black_color->green,white_color->green,1.0,
+ &image->exception);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
{
- PushPixelChannelMap(image,BlueChannel);
- status|=LevelImage(image,black_color->blue,white_color->blue,1.0);
- PopPixelChannelMap(image);
+ channel_mask=SetPixelChannelMask(image,BlueChannel);
+ status|=LevelImage(image,black_color->blue,white_color->blue,1.0,
+ &image->exception);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
(image->colorspace == CMYKColorspace))
{
- PushPixelChannelMap(image,BlackChannel);
- status|=LevelImage(image,black_color->black,white_color->black,1.0);
- PopPixelChannelMap(image);
+ channel_mask=SetPixelChannelMask(image,BlackChannel);
+ status|=LevelImage(image,black_color->black,white_color->black,1.0,
+ &image->exception);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
(image->matte == MagickTrue))
{
- PushPixelChannelMap(image,AlphaChannel);
- status|=LevelImage(image,black_color->alpha,white_color->alpha,1.0);
- PopPixelChannelMap(image);
+ channel_mask=SetPixelChannelMask(image,AlphaChannel);
+ status|=LevelImage(image,black_color->alpha,white_color->alpha,1.0,
+ &image->exception);
+ (void) SetPixelChannelMask(image,channel_mask);
}
}
else
{
if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
{
- PushPixelChannelMap(image,RedChannel);
+ channel_mask=SetPixelChannelMask(image,RedChannel);
status|=LevelizeImage(image,black_color->red,white_color->red,1.0);
- PopPixelChannelMap(image);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
{
- PushPixelChannelMap(image,GreenChannel);
+ channel_mask=SetPixelChannelMask(image,GreenChannel);
status|=LevelizeImage(image,black_color->green,white_color->green,
1.0);
- PopPixelChannelMap(image);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
{
- PushPixelChannelMap(image,BlueChannel);
+ channel_mask=SetPixelChannelMask(image,BlueChannel);
status|=LevelizeImage(image,black_color->blue,white_color->blue,1.0);
- PopPixelChannelMap(image);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
(image->colorspace == CMYKColorspace))
{
- PushPixelChannelMap(image,BlackChannel);
+ channel_mask=SetPixelChannelMask(image,BlackChannel);
status|=LevelizeImage(image,black_color->black,white_color->black,
1.0);
- PopPixelChannelMap(image);
+ (void) SetPixelChannelMask(image,channel_mask);
}
if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
(image->matte == MagickTrue))
{
- PushPixelChannelMap(image,AlphaChannel);
+ channel_mask=SetPixelChannelMask(image,AlphaChannel);
status|=LevelizeImage(image,black_color->alpha,white_color->alpha,
1.0);
- PopPixelChannelMap(image);
+ (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:
%
break;
}
histogram=(MagickRealType *) RelinquishMagickMemory(histogram);
- status=LevelImage(image,(double) black,(double) white,1.0);
+ status=LevelImage(image,(double) black,(double) white,1.0,&image->exception);
return(status);
}
\f
% The format of the NegateImage method is:
%
% MagickBooleanType NegateImage(Image *image,
-% const MagickBooleanType grayscale)
+% const MagickBooleanType grayscale,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% 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)
+ const MagickBooleanType grayscale,ExceptionInfo *exception)
{
#define NegateImageTag "Negate/Image"
CacheView
*image_view;
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
ssize_t
y;
- size_t
- channels;
-
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
*/
status=MagickTrue;
progress=0;
- exception=(&image->exception);
image_view=AcquireCacheView(image);
- channels=GetPixelChannels(image);
if (grayscale != MagickFalse)
{
#if defined(MAGICKCORE_OPENMP_SUPPORT)
register ssize_t
i;
- if ((GetPixelRed(image,q) != GetPixelGreen(image,q)) ||
- (GetPixelGreen(image,q) != GetPixelBlue(image,q)))
+ if (IsPixelGray(image,q) != MagickFalse)
{
- q+=channels;
+ q+=GetPixelChannels(image);
continue;
}
- for (i=0; i < (ssize_t) channels; i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelTrait
traits;
if ((traits & UpdatePixelTrait) != 0)
q[i]=QuantumRange-q[i];
}
- q+=channels;
+ q+=GetPixelChannels(image);
}
sync=SyncCacheViewAuthenticPixels(image_view,exception);
if (sync == MagickFalse)
register ssize_t
i;
- for (i=0; i < (ssize_t) channels; i++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelTrait
traits;
if ((traits & UpdatePixelTrait) != 0)
q[i]=QuantumRange-q[i];
}
- q+=channels;
+ q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
status=MagickFalse;
%
% The format of the NormalizeImage method is:
%
-% MagickBooleanType NormalizeImage(Image *image)
+% MagickBooleanType NormalizeImage(Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-MagickExport MagickBooleanType NormalizeImage(Image *image)
+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(ContrastStretchImage(image,black_point,white_point));
+ return(ContrastStretchImage(image,black_point,white_point,exception));
}
\f
/*