// the threshold in pixels needed to apply the diffence amount.
void Magick::Image::unsharpmask ( const double radius_,
const double sigma_,
- const double amount_,
- const double threshold_ )
+ const double gain_ )
{
ExceptionInfo exceptionInfo;
GetExceptionInfo( &exceptionInfo );
UnsharpMaskImage( image(),
radius_,
sigma_,
- amount_,
- threshold_,
+ gain_,
&exceptionInfo );
replaceImage( newImage );
throwException( exceptionInfo );
void Magick::Image::unsharpmaskChannel ( const ChannelType channel_,
const double radius_,
const double sigma_,
- const double amount_,
- const double threshold_ )
+ const double gain_ )
{
ExceptionInfo exceptionInfo;
GetExceptionInfo( &exceptionInfo );
UnsharpMaskImage( image(),
radius_,
sigma_,
- amount_,
- threshold_,
+ gain_,
&exceptionInfo );
(void) SetPixelChannelMask( image(), channel_mask );
replaceImage( newImage );
using MagickCore::UndefinedRegistryType;
using MagickCore::UnregisterMagickInfo;
using MagickCore::UnsharpMaskImage;
- using MagickCore::UnsharpMaskImage;
using MagickCore::CacheView;
using MagickCore::WaveImage;
using MagickCore::WidthValue;
% The format of the UnsharpMaskImage method is:
%
% Image *UnsharpMaskImage(const Image *image,const double radius,
-% const double sigma,const double gain,const double threshold,
-% ExceptionInfo *exception)
+% const double sigma,const double gain,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o gain: the percentage of the difference between the original and the
% blur image that is added back into the original.
%
-% o threshold: the threshold in pixels needed to apply the diffence gain.
-%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
- const double sigma,const double gain,const double threshold,
- ExceptionInfo *exception)
+ const double sigma,const double gain,ExceptionInfo *exception)
{
-#define SharpenImageTag "Sharpen/Image"
+ char
+ geometry[MaxTextExtent];
- CacheView
- *image_view,
- *unsharp_view;
+ KernelInfo
+ *kernel_info;
Image
*unsharp_image;
- MagickBooleanType
- status;
-
- MagickOffsetType
- progress;
-
- double
- quantum_threshold;
-
- ssize_t
- y;
-
assert(image != (const Image *) NULL);
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
- unsharp_image=BlurImage(image,radius,sigma,exception);
- if (unsharp_image == (Image *) NULL)
- return((Image *) NULL);
- quantum_threshold=(double) QuantumRange*threshold;
- /*
- Unsharp-mask image.
- */
- status=MagickTrue;
- progress=0;
- image_view=AcquireVirtualCacheView(image,exception);
- unsharp_view=AcquireAuthenticCacheView(unsharp_image,exception);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp parallel for schedule(static,4) shared(progress,status) \
- magick_threads(image,unsharp_image,image->rows,1)
-#endif
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- register const Quantum
- *restrict p;
-
- register Quantum
- *restrict q;
-
- register ssize_t
- x;
-
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
- q=QueueCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
- exception);
- if ((p == (const Quantum *) NULL) || (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(image); i++)
- {
- double
- pixel;
-
- PixelChannel
- channel;
-
- PixelTrait
- traits,
- unsharp_traits;
-
- channel=GetPixelChannelChannel(image,i);
- traits=GetPixelChannelTraits(image,channel);
- unsharp_traits=GetPixelChannelTraits(unsharp_image,channel);
- if ((traits == UndefinedPixelTrait) ||
- (unsharp_traits == UndefinedPixelTrait))
- continue;
- if (((unsharp_traits & CopyPixelTrait) != 0) ||
- (GetPixelMask(image,p) == 0))
- {
- SetPixelChannel(unsharp_image,channel,p[i],q);
- continue;
- }
- pixel=p[i]-(double) GetPixelChannel(unsharp_image,channel,q);
- if (fabs(2.0*pixel) < quantum_threshold)
- pixel=(double) p[i];
- else
- pixel=(double) p[i]+gain*pixel;
- SetPixelChannel(unsharp_image,channel,ClampToQuantum(pixel),q);
- }
- p+=GetPixelChannels(image);
- q+=GetPixelChannels(unsharp_image);
- }
- if (SyncCacheViewAuthenticPixels(unsharp_view,exception) == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_UnsharpMaskImage)
-#endif
- proceed=SetImageProgress(image,SharpenImageTag,progress++,image->rows);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- unsharp_image->type=image->type;
- unsharp_view=DestroyCacheView(unsharp_view);
- image_view=DestroyCacheView(image_view);
- if (status == MagickFalse)
- unsharp_image=DestroyImage(unsharp_image);
+ assert(exception->signature == MagickSignature);
+ (void) FormatLocaleString(geometry,MaxTextExtent,"Blur:%.20gx%.20g>",
+ radius,sigma);
+ kernel_info=AcquireKernelInfo(geometry);
+ if (kernel_info == (KernelInfo *) NULL)
+ ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
+ (void) FormatLocaleString(geometry,MaxTextExtent,"%.20g,%.20g%%",
+ -100.0+gain*100.0,200.0-gain*100.0);
+ ScaleGeometryKernelInfo(kernel_info,geometry);
+ unsharp_image=MorphologyImage(image,ConvolveMorphology,1,kernel_info,
+ exception);
+ kernel_info=DestroyKernelInfo(kernel_info);
return(unsharp_image);
}
*SpreadImage(const Image *,const double,const PixelInterpolateMethod,
ExceptionInfo *),
*UnsharpMaskImage(const Image *,const double,const double,const double,
- const double,ExceptionInfo *);
+ ExceptionInfo *);
#if defined(__cplusplus) || defined(c_plusplus)
}
% The format of the MagickUnsharpMaskImage method is:
%
% MagickBooleanType MagickUnsharpMaskImage(MagickWand *wand,
-% const double radius,const double sigma,const double amount,
-% const double threshold)
+% const double radius,const double sigma,const double gain)
%
% A description of each parameter follows:
%
%
% o sigma: the standard deviation of the Gaussian, in pixels.
%
-% o amount: the percentage of the difference between the original and the
+% o gain: the percentage of the difference between the original and the
% blur image that is added back into the original.
%
-% o threshold: the threshold in pixels needed to apply the diffence amount.
-%
*/
WandExport MagickBooleanType MagickUnsharpMaskImage(MagickWand *wand,
- const double radius,const double sigma,const double amount,
- const double threshold)
+ const double radius,const double sigma,const double gain)
{
Image
*unsharp_image;
(void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
if (wand->images == (Image *) NULL)
ThrowWandException(WandError,"ContainsNoImages",wand->name);
- unsharp_image=UnsharpMaskImage(wand->images,radius,sigma,amount,threshold,
+ unsharp_image=UnsharpMaskImage(wand->images,radius,sigma,amount,
wand->exception);
if (unsharp_image == (Image *) NULL)
return(MagickFalse);
MagickThumbnailImage(MagickWand *,const size_t,const size_t),
MagickTrimImage(MagickWand *,const double),
MagickUniqueImageColors(MagickWand *),
- MagickUnsharpMaskImage(MagickWand *,const double,const double,const double,
- const double),
+ MagickUnsharpMaskImage(MagickWand *,const double,const double,const double),
MagickVignetteImage(MagickWand *,const double,const double,const ssize_t,
const ssize_t),
MagickWaveImage(MagickWand *,const double,const double,
if ((flags & PsiValue) == 0)
geometry_info.psi=0.05;
mogrify_image=UnsharpMaskImage(*image,geometry_info.rho,
- geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
+ geometry_info.sigma,geometry_info.xi,exception);
break;
}
break;
if ((flags & PsiValue) == 0)
geometry_info.psi=0.05;
new_image=UnsharpMaskImage(_image,geometry_info.rho,
- geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
+ geometry_info.sigma,geometry_info.xi,_exception);
break;
}
CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
{ "black-point-compensation", MagickBooleanOptions} } },
{ "UnsharpMask", { {"geometry", StringReference},
{"radius", RealReference}, {"sigma", RealReference},
- {"amount", RealReference}, {"threshold", RealReference},
- {"channel", MagickChannelOptions} } },
+ {"gain", RealReference}, {"channel", MagickChannelOptions} } },
{ "MotionBlur", { {"geometry", StringReference},
{"radius", RealReference}, {"sigma", RealReference},
{"angle", RealReference}, {"channel", MagickChannelOptions} } },
if (attribute_flag[3] != 0)
geometry_info.xi=argument_list[3].real_reference;
if (attribute_flag[4] != 0)
- geometry_info.psi=argument_list[4].real_reference;
- if (attribute_flag[5] != 0)
- channel=(ChannelType) argument_list[5].integer_reference;
+ channel=(ChannelType) argument_list[4].integer_reference;
channel_mask=SetImageChannelMask(image,channel);
image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
- geometry_info.xi,geometry_info.psi,exception);
+ geometry_info.xi,exception);
if (image != (Image *) NULL)
(void) SetImageChannelMask(image,channel_mask);
break;