/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % A f f i n e T r a n s f o r m I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AffineTransformImage() transforms an image as dictated by the affine matrix. % It allocates the memory necessary for the new Image structure and returns % a pointer to the new image. % % The format of the AffineTransformImage method is: % % Image *AffineTransformImage(const Image *image, % AffineMatrix *affine,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: The image. % % o affine: The affine transform. % % o exception: Return any errors or warnings in this structure. % % */ MagickExport Image *AffineTransformImage(const Image *image, const AffineMatrix *affine,ExceptionInfo *exception) { AffineMatrix transform; Image *affine_image; long y; PointInfo extent[4], min, max; register long i, x; /* Determine bounding box. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); assert(affine != (AffineMatrix *) NULL); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); extent[0].x=0; extent[0].y=0; extent[1].x=image->columns; extent[1].y=0; extent[2].x=image->columns; extent[2].y=image->rows; extent[3].x=0; extent[3].y=image->rows; for (i=0; i < 4; i++) { x=(long) (extent[i].x+0.5); y=(long) (extent[i].y+0.5); extent[i].x=x*affine->sx+y*affine->ry+affine->tx; extent[i].y=x*affine->rx+y*affine->sy+affine->ty; } min=extent[0]; max=extent[0]; for (i=1; i < 4; i++) { if (min.x > extent[i].x) min.x=extent[i].x; if (min.y > extent[i].y) min.y=extent[i].y; if (max.x < extent[i].x) max.x=extent[i].x; if (max.y < extent[i].y) max.y=extent[i].y; } /* Affine transform image. */ affine_image=CloneImage(image,(unsigned long) ceil(max.x-min.x-0.5), (unsigned long) ceil(max.y-min.y-0.5),True,exception); if (affine_image == (Image *) NULL) return((Image *) NULL); (void) SetImage(affine_image,TransparentOpacity); transform.sx=affine->sx; transform.rx=affine->rx; transform.ry=affine->ry; transform.sy=affine->sy; transform.tx=(-min.x); transform.ty=(-min.y); (void) DrawAffineImage(affine_image,image,&transform); return(affine_image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % A f f i n e T r a n s f o r m I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AffineTransformImage() transforms an image as dictated by the affine matrix. % It allocates the memory necessary for the new Image structure and returns % a pointer to the new image. % % The format of the AffineTransformImage method is: % % Image *AffineTransformImage(const Image *image, % AffineMatrix *affine_matrix,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o affine_matrix: the affine matrix. % % o exception: Return any errors or warnings in this structure. % */ MagickExport Image *AffineTransformImage(const Image *image, const AffineMatrix *affine_matrix,ExceptionInfo *exception) { AffineMatrix transform; Image *affine_image; PointInfo extent[4], min, max, point; register long i; assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(affine_matrix != (AffineMatrix *) NULL); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); /* Determine destination image bounding box. */ extent[0].x=(double) image->page.x; extent[0].y=(double) image->page.y; extent[1].x=(double) (image->page.x+image->columns); extent[1].y=(double) image->page.y; extent[2].x=(double) (image->page.x+image->columns); extent[2].y=(double) (image->page.y+image->rows); extent[3].x=(double) image->page.x; extent[3].y=(double) (image->page.y+image->rows); for (i=0; i < 4; i++) { point=extent[i]; extent[i].x=(double) (point.x*affine_matrix->sx+point.y*affine_matrix->ry+ affine_matrix->tx); extent[i].y=(double) (point.x*affine_matrix->rx+point.y*affine_matrix->sy+ affine_matrix->ty); } min=extent[0]; max=extent[0]; for (i=1; i < 4; i++) { if (min.x > extent[i].x) min.x=extent[i].x; if (min.y > extent[i].y) min.y=extent[i].y; if (max.x < extent[i].x) max.x=extent[i].x; if (max.y < extent[i].y) max.y=extent[i].y; } affine_image=CloneImage(image,(unsigned long) (max.x-min.x+0.5), (unsigned long) (max.y-min.y+0.5),MagickTrue,exception); if (affine_image == (Image *) NULL) return((Image *) NULL); affine_image->background_color.opacity=(Quantum) TransparentOpacity; (void) SetImageBackgroundColor(affine_image); /* Adjust transform translation for direct image to image transformation. That is, pixel 0,0 translates correctly to its location in destination. */ transform=(*affine_matrix); transform.tx=extent[0].x-min.x; transform.ty=extent[0].y-min.y; /* Affine transform image. */ (void) DrawAffineImage(affine_image,image,&transform); /* Add offset to resulting image. */ affine_image->page.x=(long) floor(min.x+0.5); affine_image->page.y=(long) floor(min.y+0.5); /* Roughly calculate an appropriate virtual canvas (page) size. */ affine_image->page.width=affine_image->columns; if (affine_image->page.x > 0) affine_image->page.width+=affine_image->page.x; affine_image->page.height=affine_image->rows; if (affine_image->page.y > 0) affine_image->page.height+=affine_image->page.y; return(affine_image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % A f f i n e T r a n s f o r m I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AffineTransformImage() transforms an image as dictated by the affine matrix. % It allocates the memory necessary for the new Image structure and returns % a pointer to the new image. % % The format of the AffineTransformImage method is: % % Image *AffineTransformImage(const Image *image,AffineMatrix *affine, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: The image. % % o affine: The affine transform. % % o exception: Return any errors or warnings in this structure. % % */ MagickExport Image *AffineTransformImage(const Image *image, const AffineMatrix *affine,ExceptionInfo *exception) { AffineMatrix transform; Image *affine_image; PointInfo extent[4], min, max, point; register long i; /* Determine bounding box. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(affine != (AffineMatrix *) NULL); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); extent[0].x=0.0; extent[0].y=0.0; extent[1].x=(double) image->columns; extent[1].y=0.0; extent[2].x=(double) image->columns; extent[2].y=(double) image->rows; extent[3].x=0.0; extent[3].y=(double) image->rows; for (i=0; i < 4; i++) { point=extent[i]; extent[i].x=(double) (point.x*affine->sx+point.y*affine->ry+affine->tx); extent[i].y=(double) (point.x*affine->rx+point.y*affine->sy+affine->ty); } min=extent[0]; max=extent[0]; for (i=1; i < 4; i++) { if (min.x > extent[i].x) min.x=extent[i].x; if (min.y > extent[i].y) min.y=extent[i].y; if (max.x < extent[i].x) max.x=extent[i].x; if (max.y < extent[i].y) max.y=extent[i].y; } /* Affine transform image. */ affine_image=CloneImage(image,(unsigned long) (max.x-min.x+0.5), (unsigned long) (max.y-min.y+0.5),MagickTrue,exception); if (affine_image == (Image *) NULL) return((Image *) NULL); affine_image->background_color.opacity=TransparentOpacity; SetImageBackgroundColor(affine_image); transform.sx=affine->sx; transform.rx=affine->rx; transform.ry=affine->ry; transform.sy=affine->sy; transform.tx=min.x; transform.ty=min.y; (void) DrawAffineImage(affine_image,image,&transform); return(affine_image); }