]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Mon, 7 Nov 2011 12:14:23 +0000 (12:14 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Mon, 7 Nov 2011 12:14:23 +0000 (12:14 +0000)
MagickCore/shear.c
MagickCore/shear.h

index 62720c6ace888daae1313be8e90c943e13328312..942616ed80e09ef847f9af1c4480e9648b625777 100644 (file)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  The  XShearImage, and YShearImage methods are based on the paper "A Fast
+%  The XShearImage() and YShearImage() methods are based on the paper "A Fast
 %  Algorithm for General Raster Rotatation" by Alan W. Paeth, Graphics
-%  Interface '86 (Vancouver).  RotateImage is adapted from a similar method
-%  based on the Paeth paper written by Michael Halle of the Spatial Imaging
-%  Group, MIT Media Lab.
+%  Interface '86 (Vancouver).  ShearRotateImage() is adapted from a similar
+%  method based on the Paeth paper written by Michael Halle of the Spatial
+%  Imaging Group, MIT Media Lab.
 %
 */
 \f
@@ -2056,3 +2056,167 @@ MagickExport Image *ShearImage(const Image *image,const double x_shear,
   shear_image->page.height=0;
   return(shear_image);
 }
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   S h e a r R o t a t e I m a g e                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ShearRotateImage() creates a new image that is a rotated copy of an existing
+%  one.  Positive angles rotate counter-clockwise (right-hand rule), while
+%  negative angles rotate clockwise.  Rotated images are usually larger than
+%  the originals and have 'empty' triangular corners.  X axis.  Empty
+%  triangles left over from shearing the image are filled with the background
+%  color defined by member 'background_color' of the image.  ShearRotateImage
+%  allocates the memory necessary for the new Image structure and returns a
+%  pointer to the new image.
+%
+%  ShearRotateImage() is based on the paper "A Fast Algorithm for General
+%  Raster Rotatation" by Alan W. Paeth.  ShearRotateImage is adapted from a
+%  similar method based on the Paeth paper written by Michael Halle of the
+%  Spatial Imaging Group, MIT Media Lab.
+%
+%  The format of the ShearRotateImage method is:
+%
+%      Image *ShearRotateImage(const Image *image,const double degrees,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o degrees: Specifies the number of degrees to rotate the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *ShearRotateImage(const Image *image,const double degrees,
+  ExceptionInfo *exception)
+{
+  Image
+    *integral_image,
+    *rotate_image;
+
+  MagickBooleanType
+    status;
+
+  MagickRealType
+    angle;
+
+  PointInfo
+    shear;
+
+  RectangleInfo
+    border_info;
+
+  size_t
+    height,
+    rotations,
+    width,
+    y_width;
+
+  ssize_t
+    x_offset,
+    y_offset;
+
+  /*
+    Adjust rotation angle.
+  */
+  assert(image != (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);
+  angle=degrees;
+  while (angle < -45.0)
+    angle+=360.0;
+  for (rotations=0; angle > 45.0; rotations++)
+    angle-=90.0;
+  rotations%=4;
+  /*
+    Calculate shear equations.
+  */
+  integral_image=IntegralRotateImage(image,rotations,exception);
+  if (integral_image == (Image *) NULL)
+    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
+  shear.x=(-tan((double) DegreesToRadians(angle)/2.0));
+  shear.y=sin((double) DegreesToRadians(angle));
+  if ((shear.x == 0.0) && (shear.y == 0.0))
+    return(integral_image);
+  if (SetImageStorageClass(integral_image,DirectClass,exception) == MagickFalse)
+    {
+      integral_image=DestroyImage(integral_image);
+      return(integral_image);
+    }
+  if (integral_image->matte == MagickFalse)
+    (void) SetImageAlphaChannel(integral_image,OpaqueAlphaChannel,exception);
+  /*
+    Compute image size.
+  */
+  width=image->columns;
+  height=image->rows;
+  if ((rotations == 1) || (rotations == 3))
+    {
+      width=image->rows;
+      height=image->columns;
+    }
+  y_width=width+(ssize_t) floor(fabs(shear.x)*height+0.5);
+  x_offset=(ssize_t) ceil((double) width+((fabs(shear.y)*height)-width)/2.0-
+    0.5);
+  y_offset=(ssize_t) ceil((double) height+((fabs(shear.y)*y_width)-height)/2.0-
+    0.5);
+  /*
+    Surround image with a border.
+  */
+  integral_image->border_color=integral_image->background_color;
+  integral_image->compose=CopyCompositeOp;
+  border_info.width=(size_t) x_offset;
+  border_info.height=(size_t) y_offset;
+  rotate_image=BorderImage(integral_image,&border_info,image->compose,
+    exception);
+  integral_image=DestroyImage(integral_image);
+  if (rotate_image == (Image *) NULL)
+    ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
+  /*
+    Rotate the image.
+  */
+  status=XShearImage(rotate_image,shear.x,width,height,x_offset,(ssize_t)
+    (rotate_image->rows-height)/2,exception);
+  if (status == MagickFalse)
+    {
+      rotate_image=DestroyImage(rotate_image);
+      return((Image *) NULL);
+    }
+  status=YShearImage(rotate_image,shear.y,y_width,height,(ssize_t)
+    (rotate_image->columns-y_width)/2,y_offset,exception);
+  if (status == MagickFalse)
+    {
+      rotate_image=DestroyImage(rotate_image);
+      return((Image *) NULL);
+    }
+  status=XShearImage(rotate_image,shear.x,y_width,rotate_image->rows,(ssize_t)
+    (rotate_image->columns-y_width)/2,0,exception);
+  if (status == MagickFalse)
+    {
+      rotate_image=DestroyImage(rotate_image);
+      return((Image *) NULL);
+    }
+  status=CropToFitImage(&rotate_image,shear.x,shear.y,(MagickRealType) width,
+    (MagickRealType) height,MagickTrue,exception);
+  if (status == MagickFalse)
+    {
+      rotate_image=DestroyImage(rotate_image);
+      return((Image *) NULL);
+    }
+  rotate_image->compose=image->compose;
+  rotate_image->page.width=0;
+  rotate_image->page.height=0;
+  return(rotate_image);
+}
index 3d8a2c3ac24773ce9c439361f020b12c2bf1449a..f1871c1b967f445321f7257fa50ae2a493e48346 100644 (file)
@@ -26,7 +26,8 @@ extern MagickExport Image
   *AffineTransformImage(const Image *,const AffineMatrix *,ExceptionInfo *),
   *DeskewImage(const Image *,const double,ExceptionInfo *),
   *RotateImage(const Image *,const double,ExceptionInfo *),
-  *ShearImage(const Image *,const double,const double,ExceptionInfo *);
+  *ShearImage(const Image *,const double,const double,ExceptionInfo *),
+  *ShearRotateImage(const Image *,const double,ExceptionInfo *);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }