Crop into MxN tiles of roughly equal area in various ways
This adds the use of the '@' flag to the -crop operator.
diff --git a/magick/transform.c b/magick/transform.c
index eb1a49e..6f1e5d1 100644
--- a/magick/transform.c
+++ b/magick/transform.c
@@ -1628,6 +1628,14 @@
% final size of the image.
%
*/
+static inline double MagickRound(double x)
+{
+ /* round the fraction to nearest integer */
+ if (x >= 0.0)
+ return((double) ((long) (x+0.5)));
+ return((double) ((long) (x-0.5)));
+}
+
MagickExport MagickBooleanType TransformImage(Image **image,
const char *crop_geometry,const char *image_geometry)
{
@@ -1660,8 +1668,80 @@
crop_image=NewImageList();
flags=ParseGravityGeometry(transform_image,crop_geometry,&geometry,
&(*image)->exception);
- if (((geometry.width == 0) && (geometry.height == 0)) ||
- ((flags & XValue) != 0) || ((flags & YValue) != 0))
+ /* crop into NxM tiles (@ flag) - AT */
+ if ((flags & AreaValue) != 0 )
+ {
+ Image
+ *next;
+
+ MagickRealType
+ width, height, w_step, h_step, x, y;
+
+ RectangleInfo
+ crop;
+
+ if ( geometry.width == 0 ) geometry.width = 1;
+ if ( geometry.height == 0 ) geometry.height = 1;
+
+ width=(MagickRealType)transform_image->columns;
+ height=(MagickRealType)transform_image->rows;
+ if ((flags & AspectValue) == 0)
+ {
+ width -= (MagickRealType)labs(geometry.x);
+ height -= (MagickRealType)labs(geometry.y);
+ }
+ else
+ {
+ width += (MagickRealType)labs(geometry.x);
+ height += (MagickRealType)labs(geometry.y);
+ }
+ w_step=width/geometry.width;
+ h_step=height/geometry.height;
+
+ next=NewImageList();
+ for (y=0.0; y < height; )
+ {
+ if ((flags & AspectValue) == 0)
+ {
+ crop.y=MagickRound(y-(geometry.y>0?0:geometry.y));
+ y+=h_step;
+ crop.height=MagickRound(y+(geometry.y<0?0:geometry.y));
+ }
+ else
+ {
+ crop.y=MagickRound(y-(geometry.y>0?geometry.y:0) );
+ y+=h_step;
+ crop.height=MagickRound(y+(geometry.y<0?geometry.y:0) );
+ }
+ crop.height -= crop.y;
+ for (x=0.0; x < width; )
+ {
+ if ((flags & AspectValue) == 0)
+ {
+ crop.x=MagickRound(x-(geometry.x>0?0:geometry.x));
+ x+=w_step;
+ crop.width=MagickRound(x+(geometry.x<0?0:geometry.x));
+ }
+ else
+ {
+ crop.x=MagickRound(x-(geometry.x>0?geometry.x:0) );
+ x+=w_step;
+ crop.width=MagickRound(x+(geometry.x<0?geometry.x:0) );
+ }
+ crop.width -= crop.x;
+printf("crop %ldx%ld+%ld+%ld\n", crop.width, crop.height, crop.x, crop.y);
+ next=CropImage(transform_image,&crop,&(*image)->exception);
+ if (next == (Image *) NULL)
+ break;
+ AppendImageToList(&crop_image,next);
+ }
+ if (next == (Image *) NULL)
+ break;
+ }
+ }
+ /* crop a single region at +X+Y */
+ else if (((geometry.width == 0) && (geometry.height == 0)) ||
+ ((flags & XValue) != 0) || ((flags & YValue) != 0))
{
crop_image=CropImage(transform_image,&geometry,&(*image)->exception);
if ((crop_image != (Image *) NULL) && ((flags & AspectValue) != 0))
@@ -1672,54 +1752,54 @@
crop_image->page.y-=geometry.y;
}
}
- else
- if ((transform_image->columns > geometry.width) ||
+ /* crop into tiles of fixed size WxH */
+ else if ((transform_image->columns > geometry.width) ||
(transform_image->rows > geometry.height))
+ {
+ Image
+ *next;
+
+ long
+ y;
+
+ register long
+ x;
+
+ unsigned long
+ height,
+ width;
+
+ /*
+ Crop repeatedly to create uniform scenes.
+ */
+ if (transform_image->page.width == 0)
+ transform_image->page.width=transform_image->columns;
+ if (transform_image->page.height == 0)
+ transform_image->page.height=transform_image->rows;
+ width=geometry.width;
+ if (width == 0)
+ width=transform_image->page.width;
+ height=geometry.height;
+ if (height == 0)
+ height=transform_image->page.height;
+ next=NewImageList();
+ for (y=0; y < (long) transform_image->page.height; y+=height)
{
- Image
- *next;
-
- long
- y;
-
- register long
- x;
-
- unsigned long
- height,
- width;
-
- /*
- Crop repeatedly to create uniform scenes.
- */
- if (transform_image->page.width == 0)
- transform_image->page.width=transform_image->columns;
- if (transform_image->page.height == 0)
- transform_image->page.height=transform_image->rows;
- width=geometry.width;
- if (width == 0)
- width=transform_image->page.width;
- height=geometry.height;
- if (height == 0)
- height=transform_image->page.height;
- next=NewImageList();
- for (y=0; y < (long) transform_image->page.height; y+=height)
+ for (x=0; x < (long) transform_image->page.width; x+=width)
{
- for (x=0; x < (long) transform_image->page.width; x+=width)
- {
- geometry.width=width;
- geometry.height=height;
- geometry.x=x;
- geometry.y=y;
- next=CropImage(transform_image,&geometry,&(*image)->exception);
- if (next == (Image *) NULL)
- break;
- AppendImageToList(&crop_image,next);
- }
+ geometry.width=width;
+ geometry.height=height;
+ geometry.x=x;
+ geometry.y=y;
+ next=CropImage(transform_image,&geometry,&(*image)->exception);
if (next == (Image *) NULL)
break;
+ AppendImageToList(&crop_image,next);
}
+ if (next == (Image *) NULL)
+ break;
}
+ }
if (crop_image == (Image *) NULL)
transform_image=CloneImage(*image,0,0,MagickTrue,&(*image)->exception);
else