/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + Y S h e a r I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % YShearImage shears the image in the Y direction with a shear angle of % 'degrees'. Positive angles shear counter-clockwise (right-hand rule), and % negative angles shear clockwise. Angles are measured relative to a % horizontal X-axis. Y shears will increase the height of an image creating % 'empty' triangles on the top and bottom of the source image. % % The format of the YShearImage method is: % % void YShearImage(Image *image,const MagickRealType degrees, % const unsigned long width,const unsigned long height,long x_offset, % const long y_offset) % % A description of each parameter follows. % % o image: the image. % % o degrees: A MagickRealType representing the shearing angle along the Y % axis. % % o width, height, x_offset, y_offset: Defines a region of the image % to shear. % */ static void YShearImage(Image *image,const MagickRealType degrees, const unsigned long width,const unsigned long height,long x_offset, const long y_offset) { #define YShearImageTag "YShear/Image" enum {UP, DOWN} direction; IndexPacket *indexes, *shear_indexes; long step, y; MagickBooleanType status; MagickPixelPacket background, pixel, source, destination; MagickRealType area, displacement; register PixelPacket *p, *q; register long i; assert(image != (Image *) NULL); x_offset--; for (y=0; y < (long) width; y++) { x_offset++; displacement=degrees*(MagickRealType) (y-width/2.0); if (displacement == 0.0) continue; if (displacement > 0.0) direction=DOWN; else { displacement*=(-1.0); direction=UP; } step=(long) floor((double) displacement); area=(MagickRealType) (displacement-step); step++; GetMagickPixelPacket(image,&background); SetMagickPixelPacket(image,&image->background_color,(IndexPacket *) NULL, &background); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&background); pixel=background; GetMagickPixelPacket(image,&source); GetMagickPixelPacket(image,&destination); switch (direction) { case UP: { /* Transfer pixels top-to-bottom. */ if (step > y_offset) break; p=GetImagePixels(image,x_offset,0,1,image->rows); if (p == (PixelPacket *) NULL) break; p+=y_offset; indexes=GetIndexes(image); indexes+=y_offset; q=p-step; shear_indexes=indexes-step; for (i=0; i < (long) height; i++) { if ((y_offset+i) < step) { SetMagickPixelPacket(image,++p,++indexes,&pixel); q++; shear_indexes++; continue; } SetMagickPixelPacket(image,p,indexes,&source); MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&source, (MagickRealType) p->opacity,area,&destination); SetPixelPacket(image,&destination,q++,shear_indexes++); SetMagickPixelPacket(image,p++,indexes++,&pixel); } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&background, (MagickRealType) background.opacity,area,&destination); SetPixelPacket(image,&destination,q++,shear_indexes++); for (i=0; i < (step-1); i++) SetPixelPacket(image,&background,q++,shear_indexes++); break; } case DOWN: { /* Transfer pixels bottom-to-top. */ p=GetImagePixels(image,x_offset,0,1,image->rows); if (p == (PixelPacket *) NULL) break; p+=y_offset+height; indexes=GetIndexes(image); indexes+=y_offset+height; q=p+step; shear_indexes=indexes+step; for (i=0; i < (long) height; i++) { p--; indexes--; q--; shear_indexes--; if ((unsigned long) (y_offset+height+step-i) >= image->rows) continue; SetMagickPixelPacket(image,p,indexes,&source); MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&source, (MagickRealType) p->opacity,area,&destination); SetPixelPacket(image,&destination,q,shear_indexes); SetMagickPixelPacket(image,p,indexes,&pixel); } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&background, (MagickRealType) background.opacity,area,&destination); SetPixelPacket(image,&destination,--q,--shear_indexes); for (i=0; i < (step-1); i++) SetPixelPacket(image,&background,--q,--shear_indexes); break; } } if (SyncImagePixels(image) == MagickFalse) break; if ((image->progress_monitor != (MagickProgressMonitor) NULL) && (QuantumTick(y,width) != MagickFalse)) { status=image->progress_monitor(XShearImageTag,y,width, image->client_data); if (status == MagickFalse) break; } } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + Y S h e a r I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % YShearImage shears the image in the Y direction with a shear angle of % 'degrees'. Positive angles shear counter-clockwise (right-hand rule), and % negative angles shear clockwise. Angles are measured relative to a % horizontal X-axis. Y shears will increase the height of an image creating % 'empty' triangles on the top and bottom of the source image. % % The format of the YShearImage method is: % % void YShearImage(Image *image,const MagickRealType degrees, % const unsigned long width,const unsigned long height,long x_offset, % const long y_offset) % % A description of each parameter follows. % % o image: The image. % % o degrees: A MagickRealType representing the shearing angle along the Y % axis. % % o width, height, x_offset, y_offset: Defines a region of the image % to shear. % % */ static inline void YShearImage(Image *image,const MagickRealType degrees, const unsigned long width,const unsigned long height,long x_offset, const long y_offset) { #define YShearImageTag "YShear/Image" enum {UP, DOWN} direction; long step, y; MagickBooleanType status; MagickRealType area, displacement; register PixelPacket *p, *q; register long i; PixelPacket pixel; assert(image != (Image *) NULL); x_offset--; for (y=0; y < (long) width; y++) { x_offset++; displacement=degrees*(MagickRealType) (y-width/2.0); if (displacement == 0.0) continue; if (displacement > 0.0) direction=DOWN; else { displacement*=(-1.0); direction=UP; } step=(long) floor((double) displacement); area=(MagickRealType) (displacement-step); step++; pixel=image->background_color; switch (direction) { case UP: { /* Transfer pixels top-to-bottom. */ if (step > y_offset) break; p=GetImagePixels(image,x_offset,0,1,image->rows); if (p == (PixelPacket *) NULL) break; p+=y_offset; q=p-step; for (i=0; i < (long) height; i++) { if ((y_offset+i) < step) { pixel=(*++p); q++; continue; } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,p, (MagickRealType) p->opacity,area,q); q++; pixel=(*p++); } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity, &image->background_color,(MagickRealType) image->background_color.opacity,area,q); q++; for (i=0; i < (step-1); i++) *q++=image->background_color; break; } case DOWN: { /* Transfer pixels bottom-to-top. */ p=GetImagePixels(image,x_offset,0,1,image->rows); if (p == (PixelPacket *) NULL) break; p+=y_offset+height; q=p+step; for (i=0; i < (long) height; i++) { p--; q--; if ((unsigned long) (y_offset+height+step-i) >= image->rows) continue; MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,p, (MagickRealType) p->opacity,area,q); pixel=(*p); } q--; MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity, &image->background_color,(MagickRealType) image->background_color.opacity,area,q); for (i=0; i < (step-1); i++) *--q=image->background_color; break; } } if (SyncImagePixels(image) == MagickFalse) break; if ((image->progress_monitor != (MagickProgressMonitor) NULL) && (QuantumTick(y,width) != MagickFalse)) { status=image->progress_monitor(XShearImageTag,y,width, image->client_data); if (status == MagickFalse) break; } } }
static void XShearImage(Image *image,const MagickRealType degrees, const unsigned long width,const unsigned long height,const long x_offset, long y_offset) { #define XShearImageTag "XShear/Image" enum {LEFT, RIGHT} direction; IndexPacket *indexes, *shear_indexes; long step, y; MagickBooleanType status; MagickPixelPacket background, pixel, source, destination; MagickRealType area, displacement; register long i; register PixelPacket *p, *q; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); y_offset--; for (y=0; y < (long) height; y++) { y_offset++; displacement=degrees*(MagickRealType) (y-height/2.0); if (displacement == 0.0) continue; if (displacement > 0.0) direction=RIGHT; else { displacement*=(-1.0); direction=LEFT; } step=(long) floor((double) displacement); area=(MagickRealType) (displacement-step); step++; GetMagickPixelPacket(image,&background); SetMagickPixelPacket(image,&image->background_color,(IndexPacket *) NULL, &background); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&background); pixel=background; GetMagickPixelPacket(image,&source); GetMagickPixelPacket(image,&destination); switch (direction) { case LEFT: { /* Transfer pixels left-to-right. */ if (step > x_offset) break; p=GetImagePixels(image,0,y_offset,image->columns,1); if (p == (PixelPacket *) NULL) break; p+=x_offset; indexes=GetIndexes(image); indexes+=x_offset; q=p-step; shear_indexes=indexes-step; for (i=0; i < (long) width; i++) { if ((x_offset+i) < step) { SetMagickPixelPacket(image,++p,++indexes,&pixel); q++; shear_indexes++; continue; } SetMagickPixelPacket(image,p,indexes,&source); MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&source, (MagickRealType) p->opacity,area,&destination); SetPixelPacket(image,&destination,q++,shear_indexes++); SetMagickPixelPacket(image,p++,indexes++,&pixel); } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&background, (MagickRealType) background.opacity,area,&destination); SetPixelPacket(image,&destination,q++,shear_indexes++); for (i=0; i < (step-1); i++) SetPixelPacket(image,&background,q++,shear_indexes++); break; } case RIGHT: { /* Transfer pixels right-to-left. */ p=GetImagePixels(image,0,y_offset,image->columns,1); if (p == (PixelPacket *) NULL) break; p+=x_offset+width; indexes=GetIndexes(image); indexes+=x_offset+width; q=p+step; shear_indexes=indexes+step; for (i=0; i < (long) width; i++) { p--; indexes--; q--; shear_indexes--; if ((unsigned long) (x_offset+width+step-i) >= image->columns) continue; SetMagickPixelPacket(image,p,indexes,&source); MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&source, (MagickRealType) p->opacity,area,&destination); SetPixelPacket(image,&destination,q,shear_indexes); SetMagickPixelPacket(image,p,indexes,&pixel); } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,&background, (MagickRealType) background.opacity,area,&destination); SetPixelPacket(image,&destination,--q,--shear_indexes); for (i=0; i < (step-1); i++) SetPixelPacket(image,&background,--q,--shear_indexes); break; } } if (SyncImagePixels(image) == MagickFalse) break; if ((image->progress_monitor != (MagickProgressMonitor) NULL) && (QuantumTick(y,height) != MagickFalse)) { status=image->progress_monitor(XShearImageTag,y,height, image->client_data); if (status == MagickFalse) break; } } }
static inline void XShearImage(Image *image,const MagickRealType degrees, const unsigned long width,const unsigned long height,const long x_offset, long y_offset) { #define XShearImageTag "XShear/Image" enum {LEFT, RIGHT} direction; long step, y; MagickBooleanType status; MagickRealType area, displacement; PixelPacket pixel; register long i; register PixelPacket *p, *q; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); y_offset--; for (y=0; y < (long) height; y++) { y_offset++; displacement=degrees*(MagickRealType) (y-height/2.0); if (displacement == 0.0) continue; if (displacement > 0.0) direction=RIGHT; else { displacement*=(-1.0); direction=LEFT; } step=(long) floor((double) displacement); area=(MagickRealType) (displacement-step); step++; pixel=image->background_color; switch (direction) { case LEFT: { /* Transfer pixels left-to-right. */ if (step > x_offset) break; p=GetImagePixels(image,0,y_offset,image->columns,1); if (p == (PixelPacket *) NULL) break; p+=x_offset; q=p-step; for (i=0; i < (long) width; i++) { if ((x_offset+i) < step) { pixel=(*++p); q++; continue; } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,p, (MagickRealType) p->opacity,area,q); q++; pixel=(*p++); } MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity, &image->background_color,(MagickRealType) image->background_color.opacity,area,q); q++; for (i=0; i < (step-1); i++) *q++=image->background_color; break; } case RIGHT: { /* Transfer pixels right-to-left. */ p=GetImagePixels(image,0,y_offset,image->columns,1); if (p == (PixelPacket *) NULL) break; p+=x_offset+width; q=p+step; for (i=0; i < (long) width; i++) { p--; q--; if ((unsigned long) (x_offset+width+step-i) >= image->columns) continue; MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity,p, (MagickRealType) p->opacity,area,q); pixel=(*p); } q--; MagickCompositeBlend(&pixel,(MagickRealType) pixel.opacity, &image->background_color,(MagickRealType) image->background_color.opacity,area,q); for (i=0; i < (step-1); i++) *--q=image->background_color; break; } } if (SyncImagePixels(image) == MagickFalse) break; if ((image->progress_monitor != (MagickProgressMonitor) NULL) && (QuantumTick(y,height) != MagickFalse)) { status=image->progress_monitor(XShearImageTag,y,height, image->client_data); if (status == MagickFalse) break; } } }