From b6f578bf802306a759e9c1b51c8edc4d2041ec9b Mon Sep 17 00:00:00 2001 From: dirk Date: Sun, 12 Jul 2015 17:56:39 +0000 Subject: [PATCH] Added support for more than 2 stop colors. --- MagickCore/draw.c | 71 ++++++++++++++++++++++++++++++++++++---------- MagickCore/paint.c | 27 ++++++------------ MagickCore/paint.h | 4 +-- coders/gradient.c | 30 ++++++++++++-------- 4 files changed, 85 insertions(+), 47 deletions(-) diff --git a/MagickCore/draw.c b/MagickCore/draw.c index c66056146..453fb3e45 100644 --- a/MagickCore/draw.c +++ b/MagickCore/draw.c @@ -1699,9 +1699,6 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, PointInfo point; - PixelInfo - start_color; - PrimitiveInfo *primitive_info; @@ -1720,13 +1717,17 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, size_t length, - number_points; + number_points, + number_stops; ssize_t j, k, n; + StopInfo + *stops; + /* Ensure the annotation info is valid. */ @@ -1752,6 +1753,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, primitive_extent=(double) strlen(primitive); (void) SetImageArtifact(image,"MVG",primitive); n=0; + number_stops=0; + stops=(StopInfo *) NULL; /* Allocate primitive info memory. */ @@ -1783,8 +1786,6 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, graphic_context[n]->viewbox.height=image->rows; } token=AcquireString(primitive); - (void) QueryColorCompliance("#000000",AllCompliance,&start_color, - exception); if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) return(MagickFalse); status=MagickTrue; @@ -2492,22 +2493,28 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, } if (LocaleCompare("stop-color",keyword) == 0) { - GradientType - type; - PixelInfo stop_color; + number_stops++; + if (number_stops == 1) + stops=(StopInfo *) AcquireQuantumMemory(2,sizeof(*stops)); + else if (number_stops > 2) + stops=(StopInfo *) ResizeQuantumMemory(stops,number_stops, + sizeof(*stops)); + if (stops == (StopInfo *) NULL) + { + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'", + image->filename); + break; + } GetMagickToken(q,&q,token); (void) QueryColorCompliance(token,AllCompliance,&stop_color, exception); - type=LinearGradient; - if (draw_info->gradient.type == RadialGradient) - type=RadialGradient; - (void) GradientImage(image,type,PadSpread,&start_color,&stop_color, - exception); - start_color=stop_color; + stops[number_stops-1].color=stop_color; GetMagickToken(q,&q,token); + stops[number_stops-1].offset=StringToDouble(token,(char **) NULL); break; } if (LocaleCompare("stroke",keyword) == 0) @@ -2761,6 +2768,22 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, } if (primitive_type == UndefinedPrimitive) { + if (*q == '\0') + { + if (number_stops > 1) + { + GradientType + type; + + type=LinearGradient; + if (draw_info->gradient.type == RadialGradient) + type=RadialGradient; + (void) GradientImage(image,type,PadSpread,stops,number_stops, + exception); + } + if (number_stops > 0) + stops=(StopInfo *) RelinquishMagickMemory(stops); + } if (image->debug != MagickFalse) (void) LogMagickEvent(DrawEvent,GetMagickModule()," %.*s", (int) (q-p),p); @@ -3230,6 +3253,22 @@ static inline double GetStopColorOffset(const GradientInfo *gradient, return(0.0); } +static int StopInfoCompare(const void *x,const void *y) +{ + StopInfo + *stop_1, + *stop_2; + + stop_1=(StopInfo *) x; + stop_2=(StopInfo *) y; + + if (stop_1->offset > stop_2->offset) + return(1); + if (fabs(stop_1->offset-stop_2->offset) <= MagickEpsilon) + return(0); + return(-1); +} + MagickExport MagickBooleanType DrawGradientImage(Image *image, const DrawInfo *draw_info,ExceptionInfo *exception) { @@ -3269,6 +3308,8 @@ MagickExport MagickBooleanType DrawGradientImage(Image *image, (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (const DrawInfo *) NULL); gradient=(&draw_info->gradient); + qsort(gradient->stops,gradient->number_stops,sizeof(StopInfo), + StopInfoCompare); gradient_vector=(&gradient->gradient_vector); point.x=gradient_vector->x2-gradient_vector->x1; point.y=gradient_vector->y2-gradient_vector->y1; diff --git a/MagickCore/paint.c b/MagickCore/paint.c index 74bdb3660..a8a7514bf 100644 --- a/MagickCore/paint.c +++ b/MagickCore/paint.c @@ -405,9 +405,10 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image, % o exception: return any errors or warnings in this structure. % */ -MagickExport MagickBooleanType GradientImage(Image *image, - const GradientType type,const SpreadMethod method, - const PixelInfo *start_color,const PixelInfo *stop_color, + +MagickExport MagickBooleanType GradientImage(Image *image, + const GradientType type,const SpreadMethod method, + const StopInfo *stops,const size_t number_stops, ExceptionInfo *exception) { DrawInfo @@ -419,9 +420,6 @@ MagickExport MagickBooleanType GradientImage(Image *image, MagickBooleanType status; - register ssize_t - i; - /* Set gradient start-stop end points. */ @@ -429,8 +427,8 @@ MagickExport MagickBooleanType GradientImage(Image *image, assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(start_color != (const PixelInfo *) NULL); - assert(stop_color != (const PixelInfo *) NULL); + assert(stops != (const StopInfo *) NULL); + assert(number_stops > 0); draw_info=AcquireDrawInfo(); gradient=(&draw_info->gradient); gradient->type=type; @@ -447,24 +445,17 @@ MagickExport MagickBooleanType GradientImage(Image *image, /* Define the gradient to fill between the stops. */ - gradient->number_stops=2; + gradient->number_stops=number_stops; gradient->stops=(StopInfo *) AcquireQuantumMemory(gradient->number_stops, sizeof(*gradient->stops)); if (gradient->stops == (StopInfo *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); - (void) ResetMagickMemory(gradient->stops,0,gradient->number_stops* - sizeof(*gradient->stops)); - for (i=0; i < (ssize_t) gradient->number_stops; i++) - GetPixelInfo(image,&gradient->stops[i].color); - gradient->stops[0].color=(*start_color); - gradient->stops[0].offset=0.0; - gradient->stops[1].color=(*stop_color); - gradient->stops[1].offset=1.0; + (void) CopyMagickMemory(gradient->stops,stops,(size_t) number_stops* + sizeof(*stops)); /* Draw a gradient on the image. */ - (void) SetImageColorspace(image,start_color->colorspace,exception); status=DrawGradientImage(image,draw_info,exception); draw_info=DestroyDrawInfo(draw_info); return(status); diff --git a/MagickCore/paint.h b/MagickCore/paint.h index ea61e9756..b61a3dc24 100644 --- a/MagickCore/paint.h +++ b/MagickCore/paint.h @@ -31,8 +31,8 @@ extern MagickExport Image extern MagickExport MagickBooleanType FloodfillPaintImage(Image *,const DrawInfo *,const PixelInfo *,const ssize_t, const ssize_t,const MagickBooleanType,ExceptionInfo *), - GradientImage(Image *,const GradientType,const SpreadMethod,const PixelInfo *, - const PixelInfo *,ExceptionInfo *), + GradientImage(Image *,const GradientType,const SpreadMethod,const StopInfo *, + const size_t,ExceptionInfo *), OpaquePaintImage(Image *,const PixelInfo *,const PixelInfo *, const MagickBooleanType,ExceptionInfo *), TransparentPaintImage(Image *,const PixelInfo *, diff --git a/coders/gradient.c b/coders/gradient.c index 77415d08d..eca241f17 100644 --- a/coders/gradient.c +++ b/coders/gradient.c @@ -108,9 +108,8 @@ static Image *ReadGRADIENTImage(const ImageInfo *image_info, icc_color, status; - PixelInfo - start_color, - stop_color; + StopInfo + *stops; /* Initialize Image structure. @@ -141,32 +140,39 @@ static Image *ReadGRADIENTImage(const ImageInfo *image_info, (void) sscanf(image_info->filename,"%*[^-]-%[^-]",colorname+4); icc_color=MagickTrue; } - status=QueryColorCompliance(colorname,AllCompliance,&start_color,exception); + stops=(StopInfo *) AcquireQuantumMemory(2,sizeof(*stops)); + if (stops == (StopInfo *) NULL) + ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + stops[0].offset=0.0; + stops[1].offset=1.0; + status=QueryColorCompliance(colorname,AllCompliance,&stops[0].color,exception); if (status == MagickFalse) { + stops=(StopInfo *) RelinquishMagickMemory(stops); image=DestroyImage(image); return((Image *) NULL); } - (void) SetImageColorspace(image,start_color.colorspace,exception); + (void) SetImageColorspace(image,stops[0].color.colorspace,exception); (void) CopyMagickString(colorname,"white",MagickPathExtent); - if (GetPixelInfoIntensity(image,&start_color) > (QuantumRange/2.0)) + if (GetPixelInfoIntensity(image,&stops[0].color) > (QuantumRange/2.0)) (void) CopyMagickString(colorname,"black",MagickPathExtent); if (icc_color == MagickFalse) (void) sscanf(image_info->filename,"%*[^-]-%[^-]",colorname); else (void) sscanf(image_info->filename,"%*[^-]-%*[^-]-%[^-]",colorname); - status=QueryColorCompliance(colorname,AllCompliance,&stop_color,exception); + status=QueryColorCompliance(colorname,AllCompliance,&stops[1].color,exception); if (status == MagickFalse) { + stops=(StopInfo *) RelinquishMagickMemory(stops); image=DestroyImage(image); return((Image *) NULL); } - image->alpha_trait=start_color.alpha_trait; - if (stop_color.alpha_trait != UndefinedPixelTrait) - image->alpha_trait=stop_color.alpha_trait; + image->alpha_trait=stops[0].color.alpha_trait; + if (stops[1].color.alpha_trait != UndefinedPixelTrait) + image->alpha_trait=stops[1].color.alpha_trait; status=GradientImage(image,LocaleCompare(image_info->magick,"GRADIENT") == 0 ? - LinearGradient : RadialGradient,PadSpread,&start_color,&stop_color, - exception); + LinearGradient : RadialGradient,PadSpread,stops,2,exception); + stops=(StopInfo *) RelinquishMagickMemory(stops); if (status == MagickFalse) { image=DestroyImageList(image); -- 2.50.0