mirror of
https://github.com/ImageMagick/ImageMagick.git
synced 2026-05-31 11:18:42 +02:00
This commit is contained in:
@@ -440,8 +440,8 @@ int main( int /*argc*/, char ** argv)
|
||||
cout << " unsharp mask ..." << endl;
|
||||
example = model;
|
||||
example.label( "Unsharp Mask" );
|
||||
// radius_, sigma_, gain_
|
||||
example.unsharpmask( 0.0, 1.0, 1.0);
|
||||
// radius_, sigma_, amount_, threshold_
|
||||
example.unsharpmask( 0.0, 1.0, 1.0, 0.05);
|
||||
images.push_back( example );
|
||||
|
||||
cout << " wave ..." << endl;
|
||||
|
||||
@@ -2282,7 +2282,8 @@ void Magick::Image::trim ( void )
|
||||
// the threshold in pixels needed to apply the diffence amount.
|
||||
void Magick::Image::unsharpmask ( const double radius_,
|
||||
const double sigma_,
|
||||
const double gain_ )
|
||||
const double amount_,
|
||||
const double threshold_ )
|
||||
{
|
||||
ExceptionInfo exceptionInfo;
|
||||
GetExceptionInfo( &exceptionInfo );
|
||||
@@ -2290,7 +2291,8 @@ void Magick::Image::unsharpmask ( const double radius_,
|
||||
UnsharpMaskImage( image(),
|
||||
radius_,
|
||||
sigma_,
|
||||
gain_,
|
||||
amount_,
|
||||
threshold_,
|
||||
&exceptionInfo );
|
||||
replaceImage( newImage );
|
||||
throwException( exceptionInfo );
|
||||
@@ -2300,7 +2302,8 @@ void Magick::Image::unsharpmask ( const double radius_,
|
||||
void Magick::Image::unsharpmaskChannel ( const ChannelType channel_,
|
||||
const double radius_,
|
||||
const double sigma_,
|
||||
const double gain_ )
|
||||
const double amount_,
|
||||
const double threshold_ )
|
||||
{
|
||||
ExceptionInfo exceptionInfo;
|
||||
GetExceptionInfo( &exceptionInfo );
|
||||
@@ -2309,7 +2312,8 @@ void Magick::Image::unsharpmaskChannel ( const ChannelType channel_,
|
||||
UnsharpMaskImage( image(),
|
||||
radius_,
|
||||
sigma_,
|
||||
gain_,
|
||||
amount_,
|
||||
threshold_,
|
||||
&exceptionInfo );
|
||||
(void) SetPixelChannelMask( image(), channel_mask );
|
||||
replaceImage( newImage );
|
||||
|
||||
@@ -259,7 +259,7 @@ namespace Magick
|
||||
void crop ( const Geometry &geometry_ );
|
||||
|
||||
// Cycle image colormap
|
||||
void cycleColormap ( const ::ssize_t gain_ );
|
||||
void cycleColormap ( const ::ssize_t amount_ );
|
||||
|
||||
// Despeckle image (reduce speckle noise)
|
||||
void despeckle ( void );
|
||||
@@ -640,7 +640,7 @@ namespace Magick
|
||||
void splice ( const Geometry &geometry_ );
|
||||
|
||||
// Spread pixels randomly within image by specified ammount
|
||||
void spread ( const size_t gain_ = 3 );
|
||||
void spread ( const size_t amount_ = 3 );
|
||||
|
||||
// Sparse color image, given a set of coordinates, interpolates the colors
|
||||
// found at those coordinates, across the whole image, using various
|
||||
@@ -700,18 +700,20 @@ namespace Magick
|
||||
// center pixel.
|
||||
// sigma_
|
||||
// the standard deviation of the Gaussian, in pixels.
|
||||
// gain_
|
||||
// amount_
|
||||
// the percentage of the difference between the original and
|
||||
// the blur image that is added back into the original.
|
||||
// threshold_
|
||||
// the threshold in pixels needed to apply the diffence amount.
|
||||
void unsharpmask ( const double radius_,
|
||||
const double sigma_,
|
||||
const double gain_ );
|
||||
const double amount_,
|
||||
const double threshold_ );
|
||||
void unsharpmaskChannel ( const ChannelType channel_,
|
||||
const double radius_,
|
||||
const double sigma_,
|
||||
const double gain_ );
|
||||
const double amount_,
|
||||
const double threshold_ );
|
||||
|
||||
// Map image pixels to a sine wave
|
||||
void wave ( const double amplitude_ = 25.0,
|
||||
|
||||
@@ -389,12 +389,13 @@ namespace Magick
|
||||
class MagickPPExport edgeImage : public std::unary_function<Image&,void>
|
||||
{
|
||||
public:
|
||||
edgeImage( const double radius_ = 0.0 );
|
||||
edgeImage( const double radius_ = 0.0, const double sigma_ = 0.5 );
|
||||
|
||||
void operator()( Image &image_ ) const;
|
||||
|
||||
private:
|
||||
double _radius;
|
||||
double _sigma;
|
||||
};
|
||||
|
||||
// Emboss image (hilight edges with 3D effect)
|
||||
|
||||
+117
-18
@@ -3325,7 +3325,8 @@ MagickExport Image *SpreadImage(const Image *image,const double radius,
|
||||
% The format of the UnsharpMaskImage method is:
|
||||
%
|
||||
% Image *UnsharpMaskImage(const Image *image,const double radius,
|
||||
% const double sigma,const double gain,ExceptionInfo *exception)
|
||||
% const double sigma,const double amount,const double threshold,
|
||||
% ExceptionInfo *exception)
|
||||
%
|
||||
% A description of each parameter follows:
|
||||
%
|
||||
@@ -3339,37 +3340,135 @@ MagickExport Image *SpreadImage(const Image *image,const double radius,
|
||||
% 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,ExceptionInfo *exception)
|
||||
const double sigma,const double gain,const double threshold,
|
||||
ExceptionInfo *exception)
|
||||
{
|
||||
char
|
||||
geometry[MaxTextExtent];
|
||||
#define SharpenImageTag "Sharpen/Image"
|
||||
|
||||
KernelInfo
|
||||
*kernel_info;
|
||||
CacheView
|
||||
*image_view,
|
||||
*unsharp_view;
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
return(unsharp_image);
|
||||
}
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ extern MagickExport Image
|
||||
*SpreadImage(const Image *,const double,const PixelInterpolateMethod,
|
||||
ExceptionInfo *),
|
||||
*UnsharpMaskImage(const Image *,const double,const double,const double,
|
||||
ExceptionInfo *);
|
||||
const double,ExceptionInfo *);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
|
||||
@@ -11925,7 +11925,8 @@ WandExport MagickBooleanType MagickUniqueImageColors(MagickWand *wand)
|
||||
% The format of the MagickUnsharpMaskImage method is:
|
||||
%
|
||||
% MagickBooleanType MagickUnsharpMaskImage(MagickWand *wand,
|
||||
% const double radius,const double sigma,const double gain)
|
||||
% const double radius,const double sigma,const double gain,
|
||||
% const double threshold)
|
||||
%
|
||||
% A description of each parameter follows:
|
||||
%
|
||||
@@ -11939,9 +11940,12 @@ WandExport MagickBooleanType MagickUniqueImageColors(MagickWand *wand)
|
||||
% 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.
|
||||
%
|
||||
*/
|
||||
WandExport MagickBooleanType MagickUnsharpMaskImage(MagickWand *wand,
|
||||
const double radius,const double sigma,const double gain)
|
||||
const double radius,const double sigma,const double gain,
|
||||
const double threshold)
|
||||
{
|
||||
Image
|
||||
*unsharp_image;
|
||||
@@ -11952,7 +11956,7 @@ WandExport MagickBooleanType MagickUnsharpMaskImage(MagickWand *wand,
|
||||
(void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
|
||||
if (wand->images == (Image *) NULL)
|
||||
ThrowWandException(WandError,"ContainsNoImages",wand->name);
|
||||
unsharp_image=UnsharpMaskImage(wand->images,radius,sigma,gain,
|
||||
unsharp_image=UnsharpMaskImage(wand->images,radius,sigma,gain,threshold,
|
||||
wand->exception);
|
||||
if (unsharp_image == (Image *) NULL)
|
||||
return(MagickFalse);
|
||||
|
||||
@@ -304,7 +304,8 @@ extern WandExport MagickBooleanType
|
||||
MagickThumbnailImage(MagickWand *,const size_t,const size_t),
|
||||
MagickTrimImage(MagickWand *,const double),
|
||||
MagickUniqueImageColors(MagickWand *),
|
||||
MagickUnsharpMaskImage(MagickWand *,const double,const double,const double),
|
||||
MagickUnsharpMaskImage(MagickWand *,const double,const double,const double,
|
||||
const double),
|
||||
MagickVignetteImage(MagickWand *,const double,const double,const ssize_t,
|
||||
const ssize_t),
|
||||
MagickWaveImage(MagickWand *,const double,const double,
|
||||
|
||||
@@ -3046,7 +3046,8 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc,
|
||||
if ((flags & PsiValue) == 0)
|
||||
geometry_info.psi=0.05;
|
||||
mogrify_image=UnsharpMaskImage(*image,geometry_info.rho,
|
||||
geometry_info.sigma,geometry_info.xi,exception);
|
||||
geometry_info.sigma,geometry_info.xi,geometry_info.psi,
|
||||
exception);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3336,7 +3336,7 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand,
|
||||
if ((flags & PsiValue) == 0)
|
||||
geometry_info.psi=0.05;
|
||||
new_image=UnsharpMaskImage(_image,geometry_info.rho,
|
||||
geometry_info.sigma,geometry_info.xi,_exception);
|
||||
geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
|
||||
break;
|
||||
}
|
||||
CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
|
||||
|
||||
@@ -390,7 +390,8 @@ static struct
|
||||
{ "black-point-compensation", MagickBooleanOptions} } },
|
||||
{ "UnsharpMask", { {"geometry", StringReference},
|
||||
{"radius", RealReference}, {"sigma", RealReference},
|
||||
{"gain", RealReference}, {"channel", MagickChannelOptions} } },
|
||||
{"gain", RealReference}, {"threshold", RealReference},
|
||||
{"channel", MagickChannelOptions} } },
|
||||
{ "MotionBlur", { {"geometry", StringReference},
|
||||
{"radius", RealReference}, {"sigma", RealReference},
|
||||
{"angle", RealReference}, {"channel", MagickChannelOptions} } },
|
||||
@@ -9487,10 +9488,12 @@ Mogrify(ref,...)
|
||||
if (attribute_flag[3] != 0)
|
||||
geometry_info.xi=argument_list[3].real_reference;
|
||||
if (attribute_flag[4] != 0)
|
||||
channel=(ChannelType) argument_list[4].integer_reference;
|
||||
geometry_info.psi=argument_list[4].real_reference;
|
||||
if (attribute_flag[5] != 0)
|
||||
channel=(ChannelType) argument_list[5].integer_reference;
|
||||
channel_mask=SetImageChannelMask(image,channel);
|
||||
image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
|
||||
geometry_info.xi,exception);
|
||||
geometry_info.xi,geometry_info.psi,exception);
|
||||
if (image != (Image *) NULL)
|
||||
(void) SetImageChannelMask(image,channel_mask);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user