% July 1992 %
% %
% %
-% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2015 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/cache.h"
#include "MagickCore/cache-private.h"
#include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
#include "MagickCore/client.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
% CannyEdgeImage() uses a multi-stage algorithm to detect a wide range of
% edges in images.
%
-% The format of the EdgeImage method is:
+% The format of the CannyEdgeImage method is:
%
% Image *CannyEdgeImage(const Image *image,const double radius,
% const double sigma,const double lower_percent,
const double sigma,const double lower_percent,const double upper_percent,
ExceptionInfo *exception)
{
+#define CannyEdgeImageTag "CannyEdge/Image"
+
CacheView
*edge_view;
pixel;
char
- geometry[MaxTextExtent];
+ geometry[MagickPathExtent];
double
lower_threshold,
MagickBooleanType
status;
+ MagickOffsetType
+ progress;
+
MatrixInfo
*canny_cache;
y;
assert(image != (const Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
/*
Filter out noise.
*/
- (void) FormatLocaleString(geometry,MaxTextExtent,
+ (void) FormatLocaleString(geometry,MagickPathExtent,
"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma);
- kernel_info=AcquireKernelInfo(geometry);
+ kernel_info=AcquireKernelInfo(geometry,exception);
if (kernel_info == (KernelInfo *) NULL)
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
edge_image=MorphologyApply(image,ConvolveMorphology,1,kernel_info,
edge_image=DestroyImage(edge_image);
return((Image *) NULL);
}
+ (void) SetImageAlphaChannel(edge_image,OffAlphaChannel,exception);
/*
Find the intensity gradient of the image.
*/
Non-maxima suppression, remove pixels that are not considered to be part
of an edge.
*/
+ progress=0;
(void) GetMatrixElement(canny_cache,0,0,&pixel);
max=pixel.intensity;
min=pixel.intensity;
status=TraceEdges(edge_image,edge_view,canny_cache,x,y,lower_threshold,
exception);
}
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_CannyEdgeImage)
+#endif
+ proceed=SetImageProgress(image,CannyEdgeImageTag,progress++,
+ image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
}
edge_view=DestroyCacheView(edge_view);
/*
%
*/
-static inline ssize_t MagickAbsoluteValue(const ssize_t x)
-{
- if (x < 0)
- return(-x);
- return(x);
-}
-
static inline double MagickLog10(const double x)
{
#define Log10Epsilon (1.0e-11)
number_grays;
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
if ((image->columns < (distance+1)) || (image->rows < (distance+1)))
if (image->colorspace == CMYKColorspace)
grays[ScaleQuantumToMap(GetPixelBlack(image,p))].black=
ScaleQuantumToMap(GetPixelBlack(image,p));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
grays[ScaleQuantumToMap(GetPixelAlpha(image,p))].alpha=
ScaleQuantumToMap(GetPixelAlpha(image,p));
p+=GetPixelChannels(image);
if (image->colorspace == CMYKColorspace)
if (grays[i].black != ~0U)
grays[gray.black++].black=grays[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
if (grays[i].alpha != ~0U)
grays[gray.alpha++].alpha=grays[i].alpha;
}
if (image->colorspace == CMYKColorspace)
if (gray.black > number_grays)
number_grays=gray.black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
if (gray.alpha > number_grays)
number_grays=gray.alpha;
cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays,
cooccurrence[u][v].direction[i].black++;
cooccurrence[v][u].direction[i].black++;
}
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
{
u=0;
v=0;
cooccurrence[x][y].direction[i].blue*=normalize;
if (image->colorspace == CMYKColorspace)
cooccurrence[x][y].direction[i].black*=normalize;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
cooccurrence[x][y].direction[i].alpha*=normalize;
}
}
channel_features[BlackPixelChannel].angular_second_moment[i]+=
cooccurrence[x][y].direction[i].black*
cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].angular_second_moment[i]+=
cooccurrence[x][y].direction[i].alpha*
cooccurrence[x][y].direction[i].alpha;
sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
if (image->colorspace == CMYKColorspace)
sum[y].direction[i].black+=cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
sum[y].direction[i].alpha+=cooccurrence[x][y].direction[i].alpha;
correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red;
correlation.direction[i].green+=x*y*
if (image->colorspace == CMYKColorspace)
correlation.direction[i].black+=x*y*
cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
correlation.direction[i].alpha+=x*y*
cooccurrence[x][y].direction[i].alpha;
/*
if (image->colorspace == CMYKColorspace)
channel_features[BlackPixelChannel].inverse_difference_moment[i]+=
cooccurrence[x][y].direction[i].black/((y-x)*(y-x)+1);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].inverse_difference_moment[i]+=
cooccurrence[x][y].direction[i].alpha/((y-x)*(y-x)+1);
/*
if (image->colorspace == CMYKColorspace)
density_xy[y+x+2].direction[i].black+=
cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
density_xy[y+x+2].direction[i].alpha+=
cooccurrence[x][y].direction[i].alpha;
/*
channel_features[BlackPixelChannel].entropy[i]-=
cooccurrence[x][y].direction[i].black*
MagickLog10(cooccurrence[x][y].direction[i].black);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].entropy[i]-=
cooccurrence[x][y].direction[i].alpha*
MagickLog10(cooccurrence[x][y].direction[i].alpha);
density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red;
density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green;
density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
density_x[x].direction[i].alpha+=
cooccurrence[x][y].direction[i].alpha;
if (image->colorspace == CMYKColorspace)
if (image->colorspace == CMYKColorspace)
density_y[y].direction[i].black+=
cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
density_y[y].direction[i].alpha+=
cooccurrence[x][y].direction[i].alpha;
}
mean.direction[i].black+=y*sum[y].direction[i].black;
sum_squares.direction[i].black+=y*y*sum[y].direction[i].black;
}
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
{
mean.direction[i].alpha+=y*sum[y].direction[i].alpha;
sum_squares.direction[i].alpha+=y*y*sum[y].direction[i].alpha;
(mean.direction[i].black*mean.direction[i].black))*sqrt(
sum_squares.direction[i].black-(mean.direction[i].black*
mean.direction[i].black)));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].correlation[i]=
(correlation.direction[i].alpha-mean.direction[i].alpha*
mean.direction[i].alpha)/(sqrt(sum_squares.direction[i].alpha-
if (image->colorspace == CMYKColorspace)
channel_features[BlackPixelChannel].sum_average[i]+=
x*density_xy[x].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].sum_average[i]+=
x*density_xy[x].direction[i].alpha;
/*
channel_features[BlackPixelChannel].sum_entropy[i]-=
density_xy[x].direction[i].black*
MagickLog10(density_xy[x].direction[i].black);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].sum_entropy[i]-=
density_xy[x].direction[i].alpha*
MagickLog10(density_xy[x].direction[i].alpha);
(x-channel_features[BlackPixelChannel].sum_entropy[i])*
(x-channel_features[BlackPixelChannel].sum_entropy[i])*
density_xy[x].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].sum_variance[i]+=
(x-channel_features[AlphaPixelChannel].sum_entropy[i])*
(x-channel_features[AlphaPixelChannel].sum_entropy[i])*
if (image->colorspace == CMYKColorspace)
variance.direction[i].black+=(y-mean.direction[i].black+1)*
(y-mean.direction[i].black+1)*cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
variance.direction[i].alpha+=(y-mean.direction[i].alpha+1)*
(y-mean.direction[i].alpha+1)*
cooccurrence[x][y].direction[i].alpha;
if (image->colorspace == CMYKColorspace)
density_xy[MagickAbsoluteValue(y-x)].direction[i].black+=
cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
density_xy[MagickAbsoluteValue(y-x)].direction[i].alpha+=
cooccurrence[x][y].direction[i].alpha;
/*
if (image->colorspace == CMYKColorspace)
entropy_xy.direction[i].black-=cooccurrence[x][y].direction[i].black*
MagickLog10(cooccurrence[x][y].direction[i].black);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
entropy_xy.direction[i].alpha-=
cooccurrence[x][y].direction[i].alpha*MagickLog10(
cooccurrence[x][y].direction[i].alpha);
entropy_xy1.direction[i].black-=(
cooccurrence[x][y].direction[i].black*MagickLog10(
density_x[x].direction[i].black*density_y[y].direction[i].black));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
entropy_xy1.direction[i].alpha-=(
cooccurrence[x][y].direction[i].alpha*MagickLog10(
density_x[x].direction[i].alpha*density_y[y].direction[i].alpha));
entropy_xy2.direction[i].black-=(density_x[x].direction[i].black*
density_y[y].direction[i].black*MagickLog10(
density_x[x].direction[i].black*density_y[y].direction[i].black));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
entropy_xy2.direction[i].alpha-=(density_x[x].direction[i].alpha*
density_y[y].direction[i].alpha*MagickLog10(
density_x[x].direction[i].alpha*density_y[y].direction[i].alpha));
if (image->colorspace == CMYKColorspace)
channel_features[BlackPixelChannel].variance_sum_of_squares[i]=
variance.direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].variance_sum_of_squares[i]=
variance.direction[i].alpha;
}
variance.direction[i].blue+=density_xy[x].direction[i].blue;
if (image->colorspace == CMYKColorspace)
variance.direction[i].black+=density_xy[x].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
variance.direction[i].alpha+=density_xy[x].direction[i].alpha;
sum_squares.direction[i].red+=density_xy[x].direction[i].red*
density_xy[x].direction[i].red;
if (image->colorspace == CMYKColorspace)
sum_squares.direction[i].black+=density_xy[x].direction[i].black*
density_xy[x].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
sum_squares.direction[i].alpha+=density_xy[x].direction[i].alpha*
density_xy[x].direction[i].alpha;
/*
channel_features[BlackPixelChannel].difference_entropy[i]-=
density_xy[x].direction[i].black*
MagickLog10(density_xy[x].direction[i].black);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].difference_entropy[i]-=
density_xy[x].direction[i].alpha*
MagickLog10(density_xy[x].direction[i].alpha);
if (image->colorspace == CMYKColorspace)
entropy_x.direction[i].black-=(density_x[x].direction[i].black*
MagickLog10(density_x[x].direction[i].black));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
entropy_x.direction[i].alpha-=(density_x[x].direction[i].alpha*
MagickLog10(density_x[x].direction[i].alpha));
entropy_y.direction[i].red-=(density_y[x].direction[i].red*
if (image->colorspace == CMYKColorspace)
entropy_y.direction[i].black-=(density_y[x].direction[i].black*
MagickLog10(density_y[x].direction[i].black));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
entropy_y.direction[i].alpha-=(density_y[x].direction[i].alpha*
MagickLog10(density_y[x].direction[i].alpha));
}
(((double) number_grays*number_grays*sum_squares.direction[i].black)-
(variance.direction[i].black*variance.direction[i].black))/
((double) number_grays*number_grays*number_grays*number_grays);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].difference_variance[i]=
(((double) number_grays*number_grays*sum_squares.direction[i].alpha)-
(variance.direction[i].alpha*variance.direction[i].alpha))/
(entropy_xy.direction[i].black-entropy_xy1.direction[i].black)/
(entropy_x.direction[i].black > entropy_y.direction[i].black ?
entropy_x.direction[i].black : entropy_y.direction[i].black);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].measure_of_correlation_1[i]=
(entropy_xy.direction[i].alpha-entropy_xy1.direction[i].alpha)/
(entropy_x.direction[i].alpha > entropy_y.direction[i].alpha ?
entropy_x.direction[i].alpha : entropy_y.direction[i].alpha);
channel_features[RedPixelChannel].measure_of_correlation_2[i]=
- (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].red-
+ (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].red-
entropy_xy.direction[i].red)))));
channel_features[GreenPixelChannel].measure_of_correlation_2[i]=
- (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].green-
+ (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].green-
entropy_xy.direction[i].green)))));
channel_features[BluePixelChannel].measure_of_correlation_2[i]=
- (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].blue-
+ (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].blue-
entropy_xy.direction[i].blue)))));
if (image->colorspace == CMYKColorspace)
channel_features[BlackPixelChannel].measure_of_correlation_2[i]=
- (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].black-
+ (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].black-
entropy_xy.direction[i].black)))));
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].measure_of_correlation_2[i]=
- (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].alpha-
+ (sqrt(fabs(1.0-exp(-2.0*(double) (entropy_xy2.direction[i].alpha-
entropy_xy.direction[i].alpha)))));
}
/*
pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue;
if (image->colorspace == CMYKColorspace)
pixel.direction[i].black+=cooccurrence[x][y].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
pixel.direction[i].alpha+=
cooccurrence[x][y].direction[i].alpha;
}
Q[z][y].direction[i].black+=cooccurrence[z][x].direction[i].black*
cooccurrence[y][x].direction[i].black/
density_x[z].direction[i].black/density_y[x].direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
Q[z][y].direction[i].alpha+=
cooccurrence[z][x].direction[i].alpha*
cooccurrence[y][x].direction[i].alpha/
if (image->colorspace == CMYKColorspace)
channel_features[BlackPixelChannel].contrast[i]+=z*z*
pixel.direction[i].black;
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].contrast[i]+=z*z*
pixel.direction[i].alpha;
}
if (image->colorspace == CMYKColorspace)
channel_features[BlackPixelChannel].maximum_correlation_coefficient[i]=
sqrt((double) -1.0);
- if (image->alpha_trait == BlendPixelTrait)
+ if (image->alpha_trait != UndefinedPixelTrait)
channel_features[AlphaPixelChannel].maximum_correlation_coefficient[i]=
sqrt((double) -1.0);
}
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% HoughLineImage() identifies lines in the image.
+% Use HoughLineImage() in conjunction with any binary edge extracted image (we
+% recommand Canny) to identify lines in the image. The algorithm accumulates
+% counts for every white pixel for every possible orientation (for angles from
+% 0 to 179 in 1 degree increments) and distance from the center of the image to
+% the corner (in 1 px increments) and stores the counts in an accumulator matrix
+% of angle vs distance. The size of the accumulator is 180x(diagonal/2). Next
+% it searches this space for peaks in counts and converts the locations of the
+% peaks to slope and intercept in the normal x,y input image space. Use the
+% slope/intercepts to find the endpoints clipped to the bounds of the image. The
+% lines are then drawn. The counts are a measure of the length of the lines
%
% The format of the HoughLineImage method is:
%
MagickExport Image *HoughLineImage(const Image *image,const size_t width,
const size_t height,const size_t threshold,ExceptionInfo *exception)
{
+#define HoughLineImageTag "HoughLine/Image"
+
CacheView
*image_view;
char
- message[MaxTextExtent],
- path[MaxTextExtent];
+ message[MagickPathExtent],
+ path[MagickPathExtent];
const char
*artifact;
MagickBooleanType
status;
+ MagickOffsetType
+ progress;
+
MatrixInfo
*accumulator;
Create the accumulator.
*/
assert(image != (const Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
accumulator_width=180;
hough_height=((sqrt(2.0)*(double) (image->rows > image->columns ?
image->rows : image->columns))/2.0);
Populate the accumulator.
*/
status=MagickTrue;
+ progress=0;
center.x=(double) image->columns/2.0;
center.y=(double) image->rows/2.0;
image_view=AcquireVirtualCacheView(image,exception);
}
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (GetPixelIntensity(image,p) > (QuantumRange/2))
+ if (GetPixelIntensity(image,p) > (QuantumRange/2.0))
{
register ssize_t
i;
}
p+=GetPixelChannels(image);
}
+ if (image->progress_monitor != (MagickProgressMonitor) NULL)
+ {
+ MagickBooleanType
+ proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+ #pragma omp critical (MagickCore_CannyEdgeImage)
+#endif
+ proceed=SetImageProgress(image,CannyEdgeImageTag,progress++,
+ image->rows);
+ if (proceed == MagickFalse)
+ status=MagickFalse;
+ }
}
image_view=DestroyCacheView(image_view);
if (status == MagickFalse)
accumulator=DestroyMatrixInfo(accumulator);
return((Image *) NULL);
}
- (void) FormatLocaleString(message,MaxTextExtent,
+ (void) FormatLocaleString(message,MagickPathExtent,
"# Hough line transform: %.20gx%.20g%+.20g\n",(double) width,
(double) height,(double) threshold);
- (void) write(file,message,strlen(message));
- (void) FormatLocaleString(message,MaxTextExtent,"viewbox 0 0 %.20g %.20g\n",
+ if (write(file,message,strlen(message)) != (ssize_t) strlen(message))
+ status=MagickFalse;
+ (void) FormatLocaleString(message,MagickPathExtent,"viewbox 0 0 %.20g %.20g\n",
(double) image->columns,(double) image->rows);
- (void) write(file,message,strlen(message));
+ if (write(file,message,strlen(message)) != (ssize_t) strlen(message))
+ status=MagickFalse;
line_count=image->columns > image->rows ? image->columns/4 : image->rows/4;
if (threshold != 0)
line_count=threshold;
(image->rows/2.0))*sin(DegreesToRadians((double) x))))/
cos(DegreesToRadians((double) x))+(image->columns/2.0);
}
- (void) FormatLocaleString(message,MaxTextExtent,
+ (void) FormatLocaleString(message,MagickPathExtent,
"line %g,%g %g,%g # %g\n",line.x1,line.y1,line.x2,line.y2,maxima);
- (void) write(file,message,strlen(message));
+ if (write(file,message,strlen(message)) != (ssize_t) strlen(message))
+ status=MagickFalse;
}
}
}
*/
image_info=AcquireImageInfo();
image_info->background_color=image->background_color;
- (void) FormatLocaleString(image_info->filename,MaxTextExtent,"mvg:%s",path);
+ (void) FormatLocaleString(image_info->filename,MagickPathExtent,"mvg:%s",path);
artifact=GetImageArtifact(image,"background");
if (artifact != (const char *) NULL)
(void) SetImageOption(image_info,"background",artifact);
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% MeanShiftImage() delineate arbitrarily shaped clusters in the image.
+% MeanShiftImage() delineate arbitrarily shaped clusters in the image. For
+% each pixel, it visits all the pixels in the neighborhood specified by
+% the window centered at the pixel and excludes those that are outside the
+% radius=(window-1)/2 surrounding the pixel. From those pixels, it finds those
+% that are within the specified color distance from the current mean, and
+% computes a new x,y centroid from those coordinates and a new mean. This new
+% x,y centroid is used as the center for a new window. This process iterates
+% until it converges and the final mean is replaces the (original window
+% center) pixel value. It repeats this process for the next pixel, etc.,
+% until it processes all pixels in the image. Results are typically better with
+% colorspaces other than sRGB. We recommend YIQ, YUV or YCbCr.
%
% The format of the MeanShiftImage method is:
%
y;
assert(image != (const Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
mean_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
if (mean_image == (Image *) NULL)
return((Image *) NULL);