static void XShearImage(Image *image,const double degrees, const unsigned long width,const unsigned long height, const long x_offset,long y_offset) { #define XShearImageText "[%s] X Shear: %+g degrees, region %lux%lu%+ld%+ld... " long y; unsigned long row_count=0; unsigned int is_grayscale; MagickPassFail status=MagickPass; assert(image != (Image *) NULL); is_grayscale=image->is_grayscale; #if defined(HAVE_OPENMP) # pragma omp parallel for schedule(dynamic,8) shared(row_count, status) #endif for (y=0; y < (long) height; y++) { double alpha, displacement; long step; PixelPacket pixel; register long i; register PixelPacket *p, *q; enum { LEFT, RIGHT } direction; MagickPassFail thread_status; thread_status=status; if (thread_status == MagickFail) continue; displacement=degrees*(y-height/2.0); if (displacement == 0.0) continue; if (displacement > 0.0) direction=RIGHT; else { displacement*=(-1.0); direction=LEFT; } step=(long) floor(displacement); alpha=MaxRGBDouble*(displacement-step); if (alpha == 0.0) { /* No fractional displacement-- just copy. */ switch (direction) { case LEFT: { /* Transfer pixels left-to-right. */ if (step > x_offset) break; p=GetImagePixelsEx(image,0,y+y_offset,image->columns,1,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=x_offset; q=p-step; (void) memcpy(q,p,width*sizeof(PixelPacket)); q+=width; for (i=0; i < (long) step; i++) *q++=image->background_color; break; } case RIGHT: { /* Transfer pixels right-to-left. */ p=GetImagePixelsEx(image,0,y+y_offset,image->columns,1,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=x_offset+width; q=p+step; for (i=0; i < (long) width; i++) *--q=(*--p); for (i=0; i < (long) step; i++) *--q=image->background_color; break; } } if (!SyncImagePixelsEx(image,&image->exception)) thread_status=MagickFail; #if defined(HAVE_OPENMP) # pragma omp critical (GM_XShearImage) #endif { row_count++; if (QuantumTick(row_count,height)) if (!MagickMonitorFormatted(row_count,height,&image->exception, XShearImageText,image->filename, degrees,width,height, x_offset,y_offset)) thread_status=MagickFail; if (thread_status == MagickFail) status=MagickFail; } continue; } /* Fractional displacement. */ step++; pixel=image->background_color; switch (direction) { case LEFT: { /* Transfer pixels left-to-right. */ if (step > x_offset) break; p=GetImagePixelsEx(image,0,y+y_offset,image->columns,1,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=x_offset; q=p-step; for (i=0; i < (long) width; i++) { if ((x_offset+i) < step) { pixel=(*++p); q++; continue; } BlendCompositePixel(q,&pixel,p,alpha); q++; pixel=(*p++); } BlendCompositePixel(q,&pixel,&image->background_color,alpha); q++; for (i=0; i < (step-1); i++) *q++=image->background_color; break; } case RIGHT: { /* Transfer pixels right-to-left. */ p=GetImagePixelsEx(image,0,y+y_offset,image->columns,1,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=x_offset+width; q=p+step; for (i=0; i < (long) width; i++) { p--; q--; if ((x_offset+width+step-i) >= image->columns) continue; BlendCompositePixel(q,&pixel,p,alpha); pixel=(*p); } --q; BlendCompositePixel(q,&pixel,&image->background_color,alpha); for (i=0; i < (step-1); i++) *--q=image->background_color; break; } } if (!SyncImagePixelsEx(image,&image->exception)) thread_status=MagickFail; #if defined(HAVE_OPENMP) # pragma omp critical (GM_XShearImage) #endif { row_count++; if (QuantumTick(row_count,height)) if (!MagickMonitorFormatted(row_count,height,&image->exception, XShearImageText,image->filename, degrees,width,height, x_offset,y_offset)) thread_status=MagickFail; if (thread_status == MagickFail) status=MagickFail; } } if (is_grayscale && IsGray(image->background_color)) image->is_grayscale=True; }
MagickExport MagickPassFail GradientImage(Image *image, const PixelPacket *start_color, const PixelPacket *stop_color) { const unsigned long image_rows=image->rows, image_columns=image->columns; long y; unsigned long row_count=0; MagickPassFail status=MagickPass; /* Determine (Hue, Saturation, Brightness) gradient. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); assert(start_color != (const PixelPacket *) NULL); assert(stop_color != (const PixelPacket *) NULL); /* Generate gradient pixels. */ #if defined(HAVE_OPENMP) # pragma omp parallel for shared(row_count, status) #endif for (y=0; y < (long) image->rows; y++) { MagickPassFail thread_status; register long x; register PixelPacket *q; #if defined(HAVE_OPENMP) # pragma omp critical (GM_GradientImage) #endif thread_status=status; if (thread_status == MagickFail) continue; q=SetImagePixelsEx(image,0,y,image->columns,1,&image->exception); if (q == (PixelPacket *) NULL) thread_status=MagickFail; if (q != (PixelPacket *) NULL) { for (x=0; x < (long) image->columns; x++) { BlendCompositePixel(&q[x],start_color,stop_color,(double) MaxRGB*(y*image_columns+x)/(image_columns*image_rows)); } if (!SyncImagePixelsEx(image,&image->exception)) thread_status=MagickFail; } #if defined(HAVE_OPENMP) # pragma omp critical (GM_GradientImage) #endif { row_count++; if (QuantumTick(row_count,image->rows)) if (!MagickMonitorFormatted(row_count,image->rows,&image->exception, GradientImageText,image->filename)) thread_status=MagickFail; if (thread_status == MagickFail) status=MagickFail; } } if (IsGray(*start_color) && IsGray(*stop_color)) image->is_grayscale=MagickTrue; if (IsMonochrome(*start_color) && ColorMatch(start_color,stop_color)) image->is_monochrome=MagickTrue; return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + Y S h e a r I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure 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 double 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 double 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 double degrees, const unsigned long width,const unsigned long height,long x_offset, const long y_offset) { #define YShearImageText "[%s] Y Shear: %+g degrees, region %lux%lu%+ld%+ld... " long y; unsigned long row_count=0; unsigned int is_grayscale; MagickPassFail status=MagickPass; assert(image != (Image *) NULL); is_grayscale=image->is_grayscale; #if defined(HAVE_OPENMP) # pragma omp parallel for schedule(dynamic,8) shared(row_count, status) #endif for (y=0; y < (long) width; y++) { double alpha, displacement; enum { UP, DOWN } direction; long step; register PixelPacket *p, *q; register long i; PixelPacket pixel; MagickPassFail thread_status; thread_status=status; if (thread_status == MagickFail) continue; displacement=degrees*(y-width/2.0); if (displacement == 0.0) continue; if (displacement > 0.0) direction=DOWN; else { displacement*=(-1.0); direction=UP; } step=(long) floor(displacement); alpha=(double) MaxRGB*(displacement-step); if (alpha == 0.0) { /* No fractional displacement-- just copy the pixels. */ switch (direction) { case UP: { /* Transfer pixels top-to-bottom. */ if (step > y_offset) break; p=GetImagePixelsEx(image,y+x_offset,0,1,image->rows,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=y_offset; q=p-step; (void) memcpy(q,p,height*sizeof(PixelPacket)); q+=height; for (i=0; i < (long) step; i++) *q++=image->background_color; break; } case DOWN: { /* Transfer pixels bottom-to-top. */ p=GetImagePixelsEx(image,y+x_offset,0,1,image->rows,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=y_offset+height; q=p+step; for (i=0; i < (long) height; i++) *--q=(*--p); for (i=0; i < (long) step; i++) *--q=image->background_color; break; } } if (!SyncImagePixelsEx(image,&image->exception)) thread_status=MagickFail; #if defined(HAVE_OPENMP) # pragma omp critical (GM_YShearImage) #endif { row_count++; if (QuantumTick(row_count,width)) if (!MagickMonitorFormatted(row_count,width,&image->exception, YShearImageText,image->filename, degrees,width,height, x_offset,y_offset)) thread_status=MagickFail; if (thread_status == MagickFail) status=MagickFail; } continue; } /* Fractional displacment. */ step++; pixel=image->background_color; switch (direction) { case UP: { /* Transfer pixels top-to-bottom. */ if (step > y_offset) break; p=GetImagePixelsEx(image,y+x_offset,0,1,image->rows,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=y_offset; q=p-step; for (i=0; i < (long) height; i++) { if ((y_offset+i) < step) { pixel=(*++p); q++; continue; } BlendCompositePixel(q,&pixel,p,alpha); q++; pixel=(*p++); } BlendCompositePixel(q,&pixel,&image->background_color,alpha); q++; for (i=0; i < (step-1); i++) *q++=image->background_color; break; } case DOWN: { /* Transfer pixels bottom-to-top. */ p=GetImagePixelsEx(image,y+x_offset,0,1,image->rows,&image->exception); if (p == (PixelPacket *) NULL) { thread_status=MagickFail; break; } p+=y_offset+height; q=p+step; for (i=0; i < (long) height; i++) { p--; q--; if ((y_offset+height+step-i) >= image->rows) continue; BlendCompositePixel(q,&pixel,p,alpha); pixel=(*p); } --q; BlendCompositePixel(q,&pixel,&image->background_color,alpha); for (i=0; i < (step-1); i++) *--q=image->background_color; break; } } if (!SyncImagePixelsEx(image,&image->exception)) thread_status=MagickFail; #if defined(HAVE_OPENMP) # pragma omp critical (GM_YShearImage) #endif { row_count++; if (QuantumTick(row_count,width)) if (!MagickMonitorFormatted(row_count,width,&image->exception, YShearImageText,image->filename, degrees,width,height, x_offset,y_offset)) thread_status=MagickFail; if (thread_status == MagickFail) status=MagickFail; } } if (is_grayscale && IsGray(image->background_color)) image->is_grayscale=True; }