From 2029ddc50e8860c787be44f997cbb57e457024ba Mon Sep 17 00:00:00 2001 From: anthony Date: Wed, 30 Mar 2011 12:13:27 +0000 Subject: [PATCH] Addition of a -distort Resize distortion (geomerty argument) --- ChangeLog | 4 ++ magick/distort.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++- magick/distort.h | 2 + magick/option.c | 1 + wand/mogrify.c | 15 ++++ 5 files changed, 201 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1e6726f88..f2de5b116 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-03-30 6.6.9-2 Anthony Thyssen + * Add a "Resize" distortion method (distort equivalent of -resize). + * Special CLI handling so -distort Resize takes a "geometry" argument. + 2011-03-29 6.6.9-2 Cristy * Expand PCL compressed pixel buffer to prevent delta compressed overrun. diff --git a/magick/distort.c b/magick/distort.c index fa8bfdfc8..80056ae43 100644 --- a/magick/distort.c +++ b/magick/distort.c @@ -67,6 +67,7 @@ #include "magick/string-private.h" #include "magick/thread-private.h" #include "magick/token.h" +#include "magick/transform.h" /* Numerous internal routines for image distortions. @@ -430,7 +431,6 @@ static double *GenerateCoefficients(const Image *image, case BarrelInverseDistortion: number_coeff=10; break; - case UndefinedDistortion: default: assert(! "Unknown Method Given"); /* just fail assertion */ } @@ -1318,6 +1318,165 @@ static double *GenerateCoefficients(const Image *image, % % % % % % ++ D i s t o r t R e s i z e I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DistortResizeImage() resize image using the equivelent but slower image +% distortion operator. The filter is applied using a EWA cylindrical +% resampling. But like resize the final image size is limited to whole pixels +% with no effects by virtual-pixels on the result. +% +% Note that images containing a transparency channel will be twice as slow to +% resize as images one without transparency. +% +% The format of the DistortResizeImage method is: +% +% Image *AdaptiveResizeImage(const Image *image,const size_t columns, +% const size_t rows,ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o image: the image. +% +% o columns: the number of columns in the resized image. +% +% o rows: the number of rows in the resized image. +% +% o exception: return any errors or warnings in this structure. +% +*/ +MagickExport Image *DistortResizeImage(const Image *image, + const size_t columns,const size_t rows,ExceptionInfo *exception) +{ +#define DistortResizeImageTag "Distort/Image" + + Image + *resize_image, + *tmp_image; + + RectangleInfo + crop_area; + + double + distort_args[12]; + + VirtualPixelMethod + vp_save; + + /* + Distort resize image. + */ + 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); + if ((columns == 0) || (rows == 0)) + return((Image *) NULL); + /* Do not short-circuit this resize if final image size is unchanged */ + + SetImageVirtualPixelMethod(image,TransparentVirtualPixelMethod); + + (void) ResetMagickMemory(distort_args,0,12*sizeof(double)); + distort_args[4]=image->columns; + distort_args[6]=columns; + distort_args[9]=image->rows; + distort_args[11]=rows; + + vp_save=GetImageVirtualPixelMethod(image); + + tmp_image=CloneImage(image,0,0,MagickTrue,exception); + if ( tmp_image == (Image *) NULL ) + return((Image *) NULL); + (void) SetImageVirtualPixelMethod(tmp_image,TransparentVirtualPixelMethod); + + if (image->matte == MagickFalse) + { + /* + Image has not transparency channel, so we free to use it + */ + (void) SetImageAlphaChannel(tmp_image,SetAlphaChannel); + resize_image=DistortImage(tmp_image,AffineDistortion,12,distort_args, + MagickTrue,exception), + + tmp_image=DestroyImage(tmp_image); + if ( resize_image == (Image *) NULL ) + return((Image *) NULL); + + (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel); + InheritException(exception,&image->exception); + } + else + { + /* + Image has transparency so handle colors and alpha separatly. + Basically we need to separate Virtual-Pixel alpha in the resized + image, so only the actual original images alpha channel is used. + */ + Image + *resize_alpha; + + /* distort alpha channel separatally */ + (void) SeparateImageChannel(tmp_image,TrueAlphaChannel); + (void) SetImageAlphaChannel(tmp_image,OpaqueAlphaChannel); + resize_alpha=DistortImage(tmp_image,AffineDistortion,12,distort_args, + MagickTrue,exception), + tmp_image=DestroyImage(tmp_image); + if ( resize_alpha == (Image *) NULL ) + return((Image *) NULL); + + /* distort the actual image containing alpha + VP alpha */ + tmp_image=CloneImage(image,0,0,MagickTrue,exception); + if ( tmp_image == (Image *) NULL ) + return((Image *) NULL); + (void) SetImageVirtualPixelMethod(tmp_image, + TransparentVirtualPixelMethod); + resize_image=DistortImage(tmp_image,AffineDistortion,12,distort_args, + MagickTrue,exception), + tmp_image=DestroyImage(tmp_image); + if ( resize_image == (Image *) NULL) + { + resize_alpha=DestroyImage(resize_alpha); + return((Image *) NULL); + } + + /* replace resize images alpha with the separally distorted alpha */ + (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel); + (void) SetImageAlphaChannel(resize_alpha,DeactivateAlphaChannel); + (void) CompositeImage(resize_image,CopyOpacityCompositeOp,resize_alpha, + 0,0); + InheritException(exception,&resize_image->exception); + resize_alpha=DestroyImage(resize_alpha); + } + (void) SetImageVirtualPixelMethod(resize_image,vp_save); + + /* + Clean up the results of the Distortion + */ + crop_area.width=columns; + crop_area.height=rows; + crop_area.x=0; + crop_area.y=0; + + tmp_image=resize_image; + resize_image=CropImage(tmp_image,&crop_area,exception); + tmp_image=DestroyImage(tmp_image); + + if ( resize_image == (Image *) NULL ) + return((Image *) NULL); + + return(resize_image); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % D i s t o r t I m a g e % % % % % @@ -1401,6 +1560,7 @@ static double *GenerateCoefficients(const Image *image, % instead % */ + MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, const size_t number_arguments,const double *arguments, MagickBooleanType bestfit,ExceptionInfo *exception) @@ -1427,6 +1587,24 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); + + /* + Handle Special Compound Distortions (in-direct distortions) + */ + if ( method == ResizeDistortion ) + { + if ( number_arguments != 2 ) + { + (void) ThrowMagickException(exception,GetMagickModule(),OptionError, + "InvalidArgument","%s : '%s'","Resize", + "Invalid number of args: 2 only"); + return((Image *) NULL); + } + distort_image=DistortResizeImage(image,(size_t)arguments[0], + (size_t)arguments[1], exception); + return(distort_image); + } + /* Convert input arguments (usally as control points for reverse mapping) into mapping coefficients to apply the distortion. diff --git a/magick/distort.h b/magick/distort.h index 07c0b36ee..1a2480bd5 100644 --- a/magick/distort.h +++ b/magick/distort.h @@ -49,6 +49,7 @@ typedef enum BarrelDistortion, BarrelInverseDistortion, ShepardsDistortion, + ResizeDistortion, SentinelDistortion } DistortImageMethod; @@ -68,6 +69,7 @@ typedef enum extern MagickExport Image *DistortImage(const Image *,const DistortImageMethod,const size_t, const double *,MagickBooleanType,ExceptionInfo *exception), + *DistortResizeImage(const Image *,const size_t,const size_t,ExceptionInfo *), *SparseColorImage(const Image *,const ChannelType,const SparseColorMethod, const size_t,const double *,ExceptionInfo *); diff --git a/magick/option.c b/magick/option.c index 96d6ed8db..82bffffa1 100644 --- a/magick/option.c +++ b/magick/option.c @@ -887,6 +887,7 @@ static const OptionInfo { "Barrel", (ssize_t) BarrelDistortion, MagickFalse }, { "BarrelInverse", (ssize_t) BarrelInverseDistortion, MagickFalse }, { "Shepards", (ssize_t) ShepardsDistortion, MagickFalse }, + { "Resize", (ssize_t) ResizeDistortion, MagickFalse }, { (char *) NULL, (ssize_t) UndefinedDistortion, MagickFalse } }, DitherOptions[] = diff --git a/wand/mogrify.c b/wand/mogrify.c index 646f2accd..8abab0bb7 100644 --- a/wand/mogrify.c +++ b/wand/mogrify.c @@ -1350,6 +1350,21 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc, (void) SyncImageSettings(mogrify_info,*image); method=(DistortImageMethod) ParseMagickOption(MagickDistortOptions, MagickFalse,argv[i+1]); + if ( method == ResizeDistortion ) + { + /* Special Case - Argument is actually a resize geometry! + ** Convert that to an appropriate distortion argument array. + */ + double + resize_args[2]; + (void) ParseRegionGeometry(*image,argv[i+2],&geometry, + exception); + resize_args[0]=(double)geometry.width; + resize_args[1]=(double)geometry.height; + mogrify_image=DistortImage(*image,method,(size_t)2, + resize_args,MagickTrue,exception); + break; + } args=InterpretImageProperties(mogrify_info,*image,argv[i+2]); InheritException(exception,&(*image)->exception); if (args == (char *) NULL) -- 2.40.0