From 4d727156230459f39669d580f55fae20e1b303f3 Mon Sep 17 00:00:00 2001 From: cristy Date: Thu, 10 Feb 2011 19:57:21 +0000 Subject: [PATCH] --- ChangeLog | 2 +- magick/image.c | 144 +++++++++++++++++++++++++++++++++++++++++++-- magick/quantize.c | 14 ++++- magick/transform.c | 1 + wand/stream.c | 1 - 5 files changed, 151 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b1151851..0538e1ce3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ * Fix off-by-one error in PosterizeImage(). * Posterize now distributes color uniformally (reference http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=17623). - * Add -smush option (doesn't work yet) (reference + * Add -smush option (reference http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=17953). 2011-02-07 6.6.7-6 Cristy diff --git a/magick/image.c b/magick/image.c index bc6c62807..4b827814d 100644 --- a/magick/image.c +++ b/magick/image.c @@ -3831,14 +3831,138 @@ MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image, % */ -static ssize_t SmushXOffset(const Image *images,ExceptionInfo *exception) +static size_t SmushXOffset(const Image *smush_image,const Image *images, + ExceptionInfo *exception) { - return(0); + CacheView + *left_view, + *right_view; + + const Image + *left_image, + *right_image; + + MagickBooleanType + status; + + PixelPacket + pixel; + + RectangleInfo + left_geometry, + right_geometry; + + register ssize_t + y; + + size_t + minimum_offset; + + ssize_t + offset, + x; + + if (images->previous == (Image *) NULL) + return(0); + right_image=images; + SetGeometry(smush_image,&right_geometry); + GravityAdjustGeometry(right_image->columns,right_image->rows, + right_image->gravity,&right_geometry); + left_image=images->previous; + SetGeometry(smush_image,&left_geometry); + GravityAdjustGeometry(left_image->columns,left_image->rows, + left_image->gravity,&left_geometry); + minimum_offset=right_image->rows; + left_view=AcquireCacheView(left_image); + right_view=AcquireCacheView(right_image); + for (y=0; y < (ssize_t) smush_image->rows; y++) + { + for (x=(ssize_t) left_image->columns-1; x > 0; x--) + { + status=GetOneCacheViewVirtualPixel(left_view,x,y,&pixel,exception); + if (pixel.opacity != TransparentOpacity) + break; + } + offset=(ssize_t) left_image->columns-x-1; + for (x=0; x < (ssize_t) right_image->columns; x++) + { + status=GetOneCacheViewVirtualPixel(right_view,x,y,&pixel,exception); + if (pixel.opacity != TransparentOpacity) + break; + } + if ((size_t) (x+offset) < minimum_offset) + minimum_offset=(size_t) (x+offset); + } + right_view=DestroyCacheView(right_view); + left_view=DestroyCacheView(left_view); + return(minimum_offset); } -static ssize_t SmushYOffset(const Image *images,ExceptionInfo *exception) +static size_t SmushYOffset(const Image *smush_image,const Image *images, + ExceptionInfo *exception) { - return(0); + CacheView + *bottom_view, + *top_view; + + const Image + *bottom_image, + *top_image; + + MagickBooleanType + status; + + PixelPacket + pixel; + + RectangleInfo + bottom_geometry, + top_geometry; + + register ssize_t + x; + + size_t + minimum_offset; + + ssize_t + offset, + y; + + if (images->previous == (Image *) NULL) + return(0); + bottom_image=images; + SetGeometry(smush_image,&bottom_geometry); + GravityAdjustGeometry(bottom_image->columns,bottom_image->rows, + bottom_image->gravity,&bottom_geometry); + top_image=images->previous; + SetGeometry(smush_image,&top_geometry); + GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity, + &top_geometry); + minimum_offset=bottom_image->rows; + top_view=AcquireCacheView(top_image); + bottom_view=AcquireCacheView(bottom_image); + for (x=0; x < (ssize_t) smush_image->columns; x++) + { + for (y=(ssize_t) top_image->rows-1; y > 0; y--) + { + status=GetOneCacheViewVirtualPixel(top_view,x,y,&pixel,exception); + if (pixel.opacity != TransparentOpacity) + break; + } + offset=(ssize_t) top_image->rows-y-1; + for (y=0; y < (ssize_t) bottom_image->rows; y++) + { + status=GetOneCacheViewVirtualPixel(bottom_view,x,y,&pixel,exception); + if (pixel.opacity != TransparentOpacity) + break; + } + if ((size_t) (y+offset) < minimum_offset) + minimum_offset=(size_t) (y+offset); + } + bottom_view=DestroyCacheView(bottom_view); + top_view=DestroyCacheView(top_view); + return(minimum_offset); } MagickExport Image *SmushImages(const Image *images, @@ -3892,6 +4016,10 @@ MagickExport Image *SmushImages(const Image *images, number_images=1; width=image->columns; height=image->rows; + if (stack != MagickFalse) + width+=GetImageListLength(image)*offset; + else + height+=GetImageListLength(image)*offset; next=GetNextImageInList(image); for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) { @@ -3934,12 +4062,12 @@ MagickExport Image *SmushImages(const Image *images, if (stack != MagickFalse) { x_offset-=geometry.x; - x_offset-=SmushXOffset(image,exception)+offset; + y_offset-=SmushYOffset(smush_image,image,exception)-offset; } else { + x_offset-=SmushXOffset(smush_image,image,exception)-offset; y_offset-=geometry.y; - y_offset-=SmushYOffset(image,exception)+offset; } status=CompositeImage(smush_image,OverCompositeOp,image,x_offset,y_offset); proceed=SetImageProgress(image,SmushImageTag,n,number_images); @@ -3958,6 +4086,10 @@ MagickExport Image *SmushImages(const Image *images, image=GetNextImageInList(image); } smush_view=DestroyCacheView(smush_view); + if (stack != MagickFalse) + status=SetImageExtent(smush_image,smush_image->columns,(size_t) y_offset); + else + status=SetImageExtent(smush_image,(size_t) x_offset,smush_image->rows); if (status == MagickFalse) smush_image=DestroyImage(smush_image); return(smush_image); diff --git a/magick/quantize.c b/magick/quantize.c index 759831f84..f12004a51 100644 --- a/magick/quantize.c +++ b/magick/quantize.c @@ -2180,6 +2180,16 @@ MagickExport void GetQuantizeInfo(QuantizeInfo *quantize_info) % */ +static inline ssize_t MagickRound(MagickRealType x) +{ + /* + Round the fraction to nearest integer. + */ + if (x >= 0.0) + return((ssize_t) (x+0.5)); + return((ssize_t) (x-0.5)); +} + MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels, const MagickBooleanType dither) { @@ -2194,10 +2204,8 @@ MagickExport MagickBooleanType PosterizeImageChannel(Image *image, const ChannelType channel,const size_t levels,const MagickBooleanType dither) { #define PosterizeImageTag "Posterize/Image" -#define PosterizePixel(pixel) (Quantum) (QuantumRange*(PosterizeRound( \ +#define PosterizePixel(pixel) (Quantum) (QuantumRange*(MagickRound( \ QuantumScale*pixel*(levels-1))/(levels-1))) -#define PosterizeRound(pixel) ((pixel) < 0.0 ? -floor((double) \ - (-(pixel)+0.5)) : floor((double) (pixel)+0.5)) CacheView *image_view; diff --git a/magick/transform.c b/magick/transform.c index 1c47e894f..99dfbc693 100644 --- a/magick/transform.c +++ b/magick/transform.c @@ -1709,6 +1709,7 @@ MagickExport Image *SpliceImage(const Image *image, % final size of the image. % */ + static inline ssize_t MagickRound(MagickRealType x) { /* diff --git a/wand/stream.c b/wand/stream.c index e0d5f0709..ca16b1a1e 100644 --- a/wand/stream.c +++ b/wand/stream.c @@ -81,7 +81,6 @@ % % o exception: return any errors or warnings in this structure. % -% */ static MagickBooleanType StreamUsage(void) -- 2.40.0