From ca5ba780a7885bcde34d7f3b60c01d38d4da8d9d Mon Sep 17 00:00:00 2001 From: Cristy Date: Sat, 22 Feb 2020 08:17:19 -0500 Subject: [PATCH] Framework to support -color-threshold option --- MagickCore/geometry.c | 10 ++++--- MagickCore/threshold.c | 46 ++++++-------------------------- MagickCore/threshold.h | 3 ++- MagickWand/magick-image.c | 46 ++++++++++++++++++++++++++++++++ MagickWand/magick-image.h | 1 + MagickWand/mogrify.c | 7 ++++- MagickWand/operation.c | 7 ++++- PerlMagick/Magick.xs | 22 ++++++++++----- PerlMagick/quantum/quantum.xs.in | 26 ++++++++++++------ 9 files changed, 109 insertions(+), 59 deletions(-) diff --git a/MagickCore/geometry.c b/MagickCore/geometry.c index c422d99710..1a88d6e18a 100644 --- a/MagickCore/geometry.c +++ b/MagickCore/geometry.c @@ -1528,14 +1528,16 @@ MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x, (void) ParseGeometry(geometry,&geometry_info); area=geometry_info.rho+sqrt(MagickEpsilon); distance=sqrt((double) former_width*former_height); - scale.x=(double) former_width*PerceptibleReciprocal(distance/sqrt(area)); - scale.y=(double) former_height*PerceptibleReciprocal(distance/sqrt(area)); + scale.x=(double) former_width*PerceptibleReciprocal(distance* + PerceptibleReciprocal(sqrt(area))); + scale.y=(double) former_height*PerceptibleReciprocal(distance* + PerceptibleReciprocal(sqrt(area))); if ((scale.x < (double) *width) || (scale.y < (double) *height)) { *width=(unsigned long) (former_width*PerceptibleReciprocal( - distance/sqrt(area))); + distance*PerceptibleReciprocal(sqrt(area)))); *height=(unsigned long) (former_height*PerceptibleReciprocal( - distance/sqrt(area))); + distance*PerceptibleReciprocal(sqrt(area)))); } former_width=(*width); former_height=(*height); diff --git a/MagickCore/threshold.c b/MagickCore/threshold.c index e0fbc682af..5f95cc9258 100644 --- a/MagickCore/threshold.c +++ b/MagickCore/threshold.c @@ -1200,28 +1200,29 @@ MagickExport MagickBooleanType ClampImage(Image *image,ExceptionInfo *exception) % The format of the ColorThresholdImage method is: % % MagickBooleanType ColorThresholdImage(Image *image, -% const char *threshold,ExceptionInfo *exception) +% const PixelInfo *start_color,const PixelInfo *stop_color, +% ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % -% o threshold: define the threshold value. +% o start_color: start color of the thresholding. +% +% o stop_color: stop color of the thresholding. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType ColorThresholdImage(Image *image, - const char *thresholds,ExceptionInfo *exception) + const PixelInfo *start_color,const PixelInfo *stop_color, + ExceptionInfo *exception) { #define ThresholdImageTag "Threshold/Image" CacheView *image_view; - GeometryInfo - geometry_info; - MagickBooleanType status; @@ -1231,9 +1232,6 @@ MagickExport MagickBooleanType ColorThresholdImage(Image *image, PixelInfo threshold; - MagickStatusType - flags; - ssize_t y; @@ -1241,40 +1239,12 @@ MagickExport MagickBooleanType ColorThresholdImage(Image *image, assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - if (thresholds == (const char *) NULL) - return(MagickTrue); if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) return(MagickFalse); if (IsGrayColorspace(image->colorspace) != MagickFalse) (void) SetImageColorspace(image,sRGBColorspace,exception); GetPixelInfo(image,&threshold); - flags=ParseGeometry(thresholds,&geometry_info); - threshold.red=geometry_info.rho; - threshold.green=geometry_info.rho; - threshold.blue=geometry_info.rho; - threshold.black=geometry_info.rho; - threshold.alpha=100.0; - if ((flags & SigmaValue) != 0) - threshold.green=geometry_info.sigma; - if ((flags & XiValue) != 0) - threshold.blue=geometry_info.xi; - if ((flags & PsiValue) != 0) - threshold.alpha=geometry_info.psi; - if (threshold.colorspace == CMYKColorspace) - { - if ((flags & PsiValue) != 0) - threshold.black=geometry_info.psi; - if ((flags & ChiValue) != 0) - threshold.alpha=geometry_info.chi; - } - if ((flags & PercentValue) != 0) - { - threshold.red*=(MagickRealType) (QuantumRange/100.0); - threshold.green*=(MagickRealType) (QuantumRange/100.0); - threshold.blue*=(MagickRealType) (QuantumRange/100.0); - threshold.black*=(MagickRealType) (QuantumRange/100.0); - threshold.alpha*=(MagickRealType) (QuantumRange/100.0); - } + threshold=(*start_color); /* White threshold image. */ diff --git a/MagickCore/threshold.h b/MagickCore/threshold.h index 1f5f6e91f6..12688884b6 100644 --- a/MagickCore/threshold.h +++ b/MagickCore/threshold.h @@ -46,7 +46,8 @@ extern MagickExport MagickBooleanType BilevelImage(Image *,const double,ExceptionInfo *), BlackThresholdImage(Image *,const char *,ExceptionInfo *), ClampImage(Image *,ExceptionInfo *), - ColorThresholdImage(Image *,const char *,ExceptionInfo *), + ColorThresholdImage(Image *,const PixelInfo *,const PixelInfo *, + ExceptionInfo *), ListThresholdMaps(FILE *,ExceptionInfo *), OrderedDitherImage(Image *,const char *,ExceptionInfo *), PerceptibleImage(Image *,const double,ExceptionInfo *), diff --git a/MagickWand/magick-image.c b/MagickWand/magick-image.c index 5eac17a567..6f48466b86 100644 --- a/MagickWand/magick-image.c +++ b/MagickWand/magick-image.c @@ -1785,6 +1785,52 @@ WandExport MagickBooleanType MagickColorMatrixImage(MagickWand *wand, % % % % % % +% M a g i c k C o l o r T h r e s h o l d I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MagickColorThresholdImage() forces all pixels in the color range to white +% otherwise black. +% +% The format of the MagickWhiteThresholdImage method is: +% +% MagickBooleanType MagickWhiteThresholdImage(MagickWand *wand, +% const PixelWand *start_color,const PixelWand *stop_color) +% +% A description of each parameter follows: +% +% o wand: the magick wand. +% +% o start-color: the start color pixel wand. +% +% o stop-color: the stop color pixel wand. +% +*/ +WandExport MagickBooleanType MagickColorThresholdImage(MagickWand *wand, + const PixelWand *start_color,const PixelWand *stop_color) +{ + PixelInfo + start, + stop; + + assert(wand != (MagickWand *) NULL); + assert(wand->signature == MagickWandSignature); + if (wand->debug != MagickFalse) + (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name); + if (wand->images == (Image *) NULL) + ThrowWandException(WandError,"ContainsNoImages",wand->name); + PixelGetMagickColor(start_color,&start); + PixelGetMagickColor(stop_color,&stop); + return(ColorThresholdImage(wand->images,&start,&stop,wand->exception)); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % M a g i c k C o m b i n e I m a g e s % % % % % diff --git a/MagickWand/magick-image.h b/MagickWand/magick-image.h index 7b2024fbd2..9d31ef5903 100644 --- a/MagickWand/magick-image.h +++ b/MagickWand/magick-image.h @@ -113,6 +113,7 @@ extern WandExport MagickBooleanType MagickColorDecisionListImage(MagickWand *,const char *), MagickColorizeImage(MagickWand *,const PixelWand *,const PixelWand *), MagickColorMatrixImage(MagickWand *,const KernelInfo *), + MagickColorThresholdImage(MagickWand *,const PixelWand *,const PixelWand *), MagickCommentImage(MagickWand *,const char *), MagickCompositeImage(MagickWand *,const MagickWand *,const CompositeOperator, const MagickBooleanType,const ssize_t,const ssize_t), diff --git a/MagickWand/mogrify.c b/MagickWand/mogrify.c index 7530825840..306d053e32 100644 --- a/MagickWand/mogrify.c +++ b/MagickWand/mogrify.c @@ -1195,11 +1195,16 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc, } if (LocaleCompare("color-threshold",option+1) == 0) { + PixelInfo + start_color, + stop_color; + /* Color threshold image. */ (void) SyncImageSettings(mogrify_info,*image,exception); - (void) ColorThresholdImage(*image,argv[i+1],exception); + (void) ColorThresholdImage(*image,&start_color,&stop_color, + exception); break; } if (LocaleCompare("compose",option+1) == 0) diff --git a/MagickWand/operation.c b/MagickWand/operation.c index 8d56a5de0f..bab76e735e 100644 --- a/MagickWand/operation.c +++ b/MagickWand/operation.c @@ -2067,9 +2067,14 @@ static MagickBooleanType CLISimpleOperatorImage(MagickCLI *cli_wand, } if (LocaleCompare("color-threshold",option+1) == 0) { + PixelInfo + start_color, + stop_color; + if (IsGeometry(arg1) == MagickFalse) CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); - (void) ColorThresholdImage(_image,arg1,_exception); + (void) ColorThresholdImage(_image,&start_color,&stop_color, + _exception); break; } if (LocaleCompare("connected-components",option+1) == 0) diff --git a/PerlMagick/Magick.xs b/PerlMagick/Magick.xs index 52030e88fd..f5e72324b1 100644 --- a/PerlMagick/Magick.xs +++ b/PerlMagick/Magick.xs @@ -577,8 +577,8 @@ static struct {"clip-limit", RealReference} } }, { "Kmeans", { {"geometry", StringReference}, {"colors", IntegerReference}, {"iterations", IntegerReference}, {"tolerance", RealReference} } }, - { "ColorThreshold", { {"threshold", StringReference}, - {"channel", MagickChannelOptions} } }, + { "ColorThreshold", { {"start-color", StringReference}, + {"stop-color", StringReference}, {"channel", MagickChannelOptions} } }, }; static SplayTreeInfo @@ -11543,10 +11543,20 @@ Mogrify(ref,...) } case 151: /* ColorThreshold */ { - if (attribute_flag[0] == 0) - argument_list[0].string_reference="50%"; - if (attribute_flag[2] != 0) - channel=(ChannelType) argument_list[2].integer_reference; + PixelInfo + start_color, + stop_color; + + (void) QueryColorCompliance("black",AllCompliance,&start_color, + exception); + (void) QueryColorCompliance("white",AllCompliance,&stop_color, + exception); + if (attribute_flag[0] != 0) + (void) QueryColorCompliance(argument_list[0].string_reference, + AllCompliance,&start_color,exception); + if (attribute_flag[1] != 0) + (void) QueryColorCompliance(argument_list[1].string_reference, + AllCompliance,&stop_color,exception); channel_mask=SetImageChannelMask(image,channel); (void) ColorThresholdImage(image,argument_list[0].string_reference, exception); diff --git a/PerlMagick/quantum/quantum.xs.in b/PerlMagick/quantum/quantum.xs.in index f1d44b4070..be1af3bf8c 100644 --- a/PerlMagick/quantum/quantum.xs.in +++ b/PerlMagick/quantum/quantum.xs.in @@ -577,8 +577,8 @@ static struct {"clip-limit", RealReference} } }, { "Kmeans", { {"geometry", StringReference}, {"colors", IntegerReference}, {"iterations", IntegerReference}, {"tolerance", RealReference} } }, - { "ColorThreshold", { {"threshold", StringReference}, - {"channel", MagickChannelOptions} } }, + { "ColorThreshold", { {"start-color", StringReference}, + {"stop-color", StringReference}, {"channel", MagickChannelOptions} } }, }; static SplayTreeInfo @@ -11547,14 +11547,24 @@ Mogrify(ref,...) geometry_info.xi,exception); break; } - case 151: /* WhiteThreshold */ + case 151: /* ColorThreshold */ { - if (attribute_flag[0] == 0) - argument_list[0].string_reference="50%"; - if (attribute_flag[2] != 0) - channel=(ChannelType) argument_list[2].integer_reference; + PixelInfo + start_color, + stop_color; + + (void) QueryColorCompliance("black",AllCompliance,&start_color, + exception); + (void) QueryColorCompliance("white",AllCompliance,&stop_color, + exception); + if (attribute_flag[0] != 0) + (void) QueryColorCompliance(argument_list[0].string_reference, + AllCompliance,&start_color,exception); + if (attribute_flag[1] != 0) + (void) QueryColorCompliance(argument_list[1].string_reference, + AllCompliance,&stop_color,exception); channel_mask=SetImageChannelMask(image,channel); - (void) WhiteThresholdImage(image,argument_list[0].string_reference, + (void) ColorThresholdImage(image,argument_list[0].string_reference, exception); (void) SetImageChannelMask(image,channel_mask); break;