42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/channel.h"
45 #include "MagickCore/color.h"
46 #include "MagickCore/color-private.h"
47 #include "MagickCore/colorspace-private.h"
48 #include "MagickCore/composite.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/draw.h"
51 #include "MagickCore/draw-private.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/gem.h"
55 #include "MagickCore/gem-private.h"
56 #include "MagickCore/monitor.h"
57 #include "MagickCore/monitor-private.h"
58 #include "MagickCore/option.h"
59 #include "MagickCore/paint.h"
60 #include "MagickCore/pixel-accessor.h"
61 #include "MagickCore/resource_.h"
62 #include "MagickCore/statistic.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/string-private.h"
65 #include "MagickCore/thread-private.h"
112 MagickExport MagickBooleanType FloodfillPaintImage(
Image *image,
114 const ssize_t y_offset,
const MagickBooleanType invert,
117 #define MaxStacksize 524288UL
118 #define PushSegmentStack(up,left,right,delta) \
120 if (s >= (segment_stack+MaxStacksize)) \
122 segment_info=RelinquishVirtualMemory(segment_info); \
123 image_view=DestroyCacheView(image_view); \
124 floodplane_view=DestroyCacheView(floodplane_view); \
125 floodplane_image=DestroyImage(floodplane_image); \
126 ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \
130 if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \
132 s->x1=(double) (left); \
133 s->y1=(double) (up); \
134 s->x2=(double) (right); \
135 s->y2=(double) (delta); \
175 assert(image != (
Image *) NULL);
176 assert(image->signature == MagickCoreSignature);
177 assert(draw_info != (
DrawInfo *) NULL);
178 assert(draw_info->signature == MagickCoreSignature);
179 if (IsEventLogging() != MagickFalse)
180 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
181 if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
183 if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
185 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
187 if (IsGrayColorspace(image->colorspace) != MagickFalse)
188 (
void) SetImageColorspace(image,sRGBColorspace,exception);
189 if ((image->alpha_trait == UndefinedPixelTrait) &&
190 (draw_info->fill.alpha_trait != UndefinedPixelTrait))
191 (void) SetImageAlpha(image,OpaqueAlpha,exception);
195 floodplane_image=CloneImage(image,0,0,MagickTrue,exception);
196 if (floodplane_image == (
Image *) NULL)
198 floodplane_image->alpha_trait=UndefinedPixelTrait;
199 floodplane_image->colorspace=GRAYColorspace;
200 (void) QueryColorCompliance(
"#000",AllCompliance,
201 &floodplane_image->background_color,exception);
202 (void) SetImageBackgroundColor(floodplane_image,exception);
203 segment_info=AcquireVirtualMemory(MaxStacksize,
sizeof(*segment_stack));
206 floodplane_image=DestroyImage(floodplane_image);
207 ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
210 segment_stack=(
SegmentInfo *) GetVirtualMemoryBlob(segment_info);
217 GetPixelInfo(image,&pixel);
218 image_view=AcquireVirtualCacheView(image,exception);
219 floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
220 PushSegmentStack(y_offset,x_offset,x_offset,1);
221 PushSegmentStack(y_offset+1,x_offset,x_offset,-1);
222 while (s > segment_stack)
239 offset=(ssize_t) s->y2;
240 y=(ssize_t) s->y1+offset;
244 p=GetCacheViewVirtualPixels(image_view,0,y,(
size_t) (x1+1),1,exception);
245 q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(
size_t) (x1+1),1,
247 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
249 p+=x1*GetPixelChannels(image);
250 q+=x1*GetPixelChannels(floodplane_image);
251 for (x=x1; x >= 0; x--)
253 if (GetPixelGray(floodplane_image,q) != 0)
255 GetPixelInfoPixel(image,p,&pixel);
256 if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert)
258 SetPixelGray(floodplane_image,QuantumRange,q);
259 p-=GetPixelChannels(image);
260 q-=GetPixelChannels(floodplane_image);
262 if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
264 skip=x >= x1 ? MagickTrue : MagickFalse;
265 if (skip == MagickFalse)
269 PushSegmentStack(y,start,x1-1,-offset);
274 if (skip == MagickFalse)
276 if (x < (ssize_t) image->columns)
278 p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1,
280 q=GetCacheViewAuthenticPixels(floodplane_view,x,y,image->columns-
282 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
284 for ( ; x < (ssize_t) image->columns; x++)
286 if (GetPixelGray(floodplane_image,q) != 0)
288 GetPixelInfoPixel(image,p,&pixel);
289 if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert)
291 SetPixelGray(floodplane_image,QuantumRange,q);
292 p+=GetPixelChannels(image);
293 q+=GetPixelChannels(floodplane_image);
295 status=SyncCacheViewAuthenticPixels(floodplane_view,exception);
296 if (status == MagickFalse)
299 PushSegmentStack(y,start,x-1,offset);
301 PushSegmentStack(y,x2+1,x-1,-offset);
307 p=GetCacheViewVirtualPixels(image_view,x,y,(
size_t) (x2-x+1),1,
309 q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(
size_t) (x2-x+1),1,
311 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
313 for ( ; x <= x2; x++)
315 if (GetPixelGray(floodplane_image,q) != 0)
317 GetPixelInfoPixel(image,p,&pixel);
318 if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert)
320 p+=GetPixelChannels(image);
321 q+=GetPixelChannels(floodplane_image);
328 for (y=0; y < (ssize_t) image->rows; y++)
342 if (status == MagickFalse)
344 p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,exception);
345 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
346 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
351 for (x=0; x < (ssize_t) image->columns; x++)
353 if (GetPixelGray(floodplane_image,p) != 0)
355 GetFillColor(draw_info,x,y,&fill_color,exception);
356 SetPixelViaPixelInfo(image,&fill_color,q);
358 p+=GetPixelChannels(floodplane_image);
359 q+=GetPixelChannels(image);
361 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
364 floodplane_view=DestroyCacheView(floodplane_view);
365 image_view=DestroyCacheView(image_view);
366 segment_info=RelinquishVirtualMemory(segment_info);
367 floodplane_image=DestroyImage(floodplane_image);
409 MagickExport MagickBooleanType GradientImage(
Image *image,
410 const GradientType type,
const SpreadMethod method,
const StopInfo *stops,
428 assert(image != (
const Image *) NULL);
429 assert(image->signature == MagickCoreSignature);
430 assert(stops != (
const StopInfo *) NULL);
431 assert(number_stops > 0);
432 if (IsEventLogging() != MagickFalse)
433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
434 draw_info=AcquireDrawInfo();
435 gradient=(&draw_info->gradient);
437 gradient->bounding_box.width=image->columns;
438 gradient->bounding_box.height=image->rows;
439 artifact=GetImageArtifact(image,
"gradient:bounding-box");
440 if (artifact != (
const char *) NULL)
441 (void) ParseAbsoluteGeometry(artifact,&gradient->bounding_box);
442 gradient->gradient_vector.x2=(double) image->columns-1;
443 gradient->gradient_vector.y2=(
double) image->rows-1;
444 artifact=GetImageArtifact(image,
"gradient:direction");
445 if (artifact != (
const char *) NULL)
450 direction=(GravityType) ParseCommandOption(MagickGravityOptions,
451 MagickFalse,artifact);
454 case NorthWestGravity:
456 gradient->gradient_vector.x1=(double) image->columns-1;
457 gradient->gradient_vector.y1=(
double) image->rows-1;
458 gradient->gradient_vector.x2=0.0;
459 gradient->gradient_vector.y2=0.0;
464 gradient->gradient_vector.x1=0.0;
465 gradient->gradient_vector.y1=(double) image->rows-1;
466 gradient->gradient_vector.x2=0.0;
467 gradient->gradient_vector.y2=0.0;
470 case NorthEastGravity:
472 gradient->gradient_vector.x1=0.0;
473 gradient->gradient_vector.y1=(double) image->rows-1;
474 gradient->gradient_vector.x2=(
double) image->columns-1;
475 gradient->gradient_vector.y2=0.0;
480 gradient->gradient_vector.x1=(double) image->columns-1;
481 gradient->gradient_vector.y1=0.0;
482 gradient->gradient_vector.x2=0.0;
483 gradient->gradient_vector.y2=0.0;
488 gradient->gradient_vector.x1=0.0;
489 gradient->gradient_vector.y1=0.0;
490 gradient->gradient_vector.x2=(double) image->columns-1;
491 gradient->gradient_vector.y2=0.0;
494 case SouthWestGravity:
496 gradient->gradient_vector.x1=(double) image->columns-1;
497 gradient->gradient_vector.y1=0.0;
498 gradient->gradient_vector.x2=0.0;
499 gradient->gradient_vector.y2=(
double) image->rows-1;
504 gradient->gradient_vector.x1=0.0;
505 gradient->gradient_vector.y1=0.0;
506 gradient->gradient_vector.x2=0.0;
507 gradient->gradient_vector.y2=(double) image->columns-1;
510 case SouthEastGravity:
512 gradient->gradient_vector.x1=0.0;
513 gradient->gradient_vector.y1=0.0;
514 gradient->gradient_vector.x2=(double) image->columns-1;
515 gradient->gradient_vector.y2=(
double) image->rows-1;
522 artifact=GetImageArtifact(image,
"gradient:angle");
523 if (artifact != (
const char *) NULL)
524 gradient->angle=StringToDouble(artifact,(
char **) NULL);
525 artifact=GetImageArtifact(image,
"gradient:vector");
526 if (artifact != (
const char *) NULL)
527 (void) sscanf(artifact,
"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf",
528 &gradient->gradient_vector.x1,&gradient->gradient_vector.y1,
529 &gradient->gradient_vector.x2,&gradient->gradient_vector.y2);
530 if ((GetImageArtifact(image,
"gradient:angle") == (
const char *) NULL) &&
531 (GetImageArtifact(image,
"gradient:direction") == (
const char *) NULL) &&
532 (GetImageArtifact(image,
"gradient:extent") == (
const char *) NULL) &&
533 (GetImageArtifact(image,
"gradient:vector") == (
const char *) NULL))
534 if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0))
535 gradient->gradient_vector.x2=0.0;
536 gradient->center.x=(double) gradient->gradient_vector.x2/2.0;
537 gradient->center.y=(
double) gradient->gradient_vector.y2/2.0;
538 artifact=GetImageArtifact(image,
"gradient:center");
539 if (artifact != (
const char *) NULL)
540 (void) sscanf(artifact,
"%lf%*[ ,]%lf",&gradient->center.x,
541 &gradient->center.y);
542 artifact=GetImageArtifact(image,
"gradient:angle");
543 if ((type == LinearGradient) && (artifact != (
const char *) NULL))
553 sine=sin((
double) DegreesToRadians(gradient->angle-90.0));
554 cosine=cos((
double) DegreesToRadians(gradient->angle-90.0));
555 distance=fabs((
double) (image->columns-1.0)*cosine)+
556 fabs((
double) (image->rows-1.0)*sine);
557 gradient->gradient_vector.x1=0.5*((image->columns-1.0)-distance*cosine);
558 gradient->gradient_vector.y1=0.5*((image->rows-1.0)-distance*sine);
559 gradient->gradient_vector.x2=0.5*((image->columns-1.0)+distance*cosine);
560 gradient->gradient_vector.y2=0.5*((image->rows-1.0)+distance*sine);
562 gradient->radii.x=(double) MagickMax((image->columns-1.0),(image->rows-1.0))/
564 gradient->radii.y=gradient->radii.x;
565 artifact=GetImageArtifact(image,
"gradient:extent");
566 if (artifact != (
const char *) NULL)
568 if (LocaleCompare(artifact,
"Circle") == 0)
570 gradient->radii.x=(double) MagickMax((image->columns-1.0),
571 (image->rows-1.0))/2.0;
572 gradient->radii.y=gradient->radii.x;
574 if (LocaleCompare(artifact,
"Diagonal") == 0)
576 gradient->radii.x=(double) (sqrt((
double) (image->columns-1.0)*
577 (image->columns-1.0)+(image->rows-1.0)*(image->rows-1.0)))/2.0;
578 gradient->radii.y=gradient->radii.x;
580 if (LocaleCompare(artifact,
"Ellipse") == 0)
582 gradient->radii.x=(double) (image->columns-1.0)/2.0;
583 gradient->radii.y=(double) (image->rows-1.0)/2.0;
585 if (LocaleCompare(artifact,
"Maximum") == 0)
587 gradient->radii.x=(double) MagickMax((image->columns-1.0),
588 (image->rows-1.0))/2.0;
589 gradient->radii.y=gradient->radii.x;
591 if (LocaleCompare(artifact,
"Minimum") == 0)
593 gradient->radii.x=(double) (MagickMin((image->columns-1.0),
594 (image->rows-1.0)))/2.0;
595 gradient->radii.y=gradient->radii.x;
598 artifact=GetImageArtifact(image,
"gradient:radii");
599 if (artifact != (
const char *) NULL)
600 (void) sscanf(artifact,
"%lf%*[ ,]%lf",&gradient->radii.x,
602 gradient->radius=MagickMax(gradient->radii.x,gradient->radii.y);
603 gradient->spread=method;
607 gradient->number_stops=number_stops;
608 gradient->stops=(
StopInfo *) AcquireQuantumMemory(gradient->number_stops,
609 sizeof(*gradient->stops));
610 if (gradient->stops == (
StopInfo *) NULL)
611 ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
613 (void) memcpy(gradient->stops,stops,(
size_t) number_stops*
sizeof(*stops));
617 status=DrawGradientImage(image,draw_info,exception);
618 draw_info=DestroyDrawInfo(draw_info);
654 static size_t **DestroyHistogramTLS(
size_t **histogram)
659 assert(histogram != (
size_t **) NULL);
660 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
661 if (histogram[i] != (
size_t *) NULL)
662 histogram[i]=(
size_t *) RelinquishMagickMemory(histogram[i]);
663 histogram=(
size_t **) RelinquishMagickMemory(histogram);
667 static size_t **AcquireHistogramTLS(
const size_t count)
676 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
677 histogram=(
size_t **) AcquireQuantumMemory(number_threads,
sizeof(*histogram));
678 if (histogram == (
size_t **) NULL)
679 return((
size_t **) NULL);
680 (void) memset(histogram,0,number_threads*
sizeof(*histogram));
681 for (i=0; i < (ssize_t) number_threads; i++)
683 histogram[i]=(
size_t *) AcquireQuantumMemory(count,
sizeof(**histogram));
684 if (histogram[i] == (
size_t *) NULL)
685 return(DestroyHistogramTLS(histogram));
690 MagickExport
Image *OilPaintImage(
const Image *image,
const double radius,
693 #define NumberPaintBins 256
694 #define OilPaintImageTag "OilPaint/Image"
721 assert(image != (
const Image *) NULL);
722 assert(image->signature == MagickCoreSignature);
724 assert(exception->signature == MagickCoreSignature);
725 if (IsEventLogging() != MagickFalse)
726 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
727 width=GetOptimalKernelWidth2D(radius,sigma);
728 linear_image=CloneImage(image,0,0,MagickTrue,exception);
729 paint_image=CloneImage(image,0,0,MagickTrue,exception);
730 if ((linear_image == (
Image *) NULL) || (paint_image == (
Image *) NULL))
732 if (linear_image != (
Image *) NULL)
733 linear_image=DestroyImage(linear_image);
734 if (paint_image != (
Image *) NULL)
735 linear_image=DestroyImage(paint_image);
736 return((
Image *) NULL);
738 if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse)
740 linear_image=DestroyImage(linear_image);
741 paint_image=DestroyImage(paint_image);
742 return((
Image *) NULL);
744 histograms=AcquireHistogramTLS(NumberPaintBins);
745 if (histograms == (
size_t **) NULL)
747 linear_image=DestroyImage(linear_image);
748 paint_image=DestroyImage(paint_image);
749 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
756 center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)*
757 (width/2L)+GetPixelChannels(linear_image)*(width/2L);
758 image_view=AcquireVirtualCacheView(linear_image,exception);
759 paint_view=AcquireAuthenticCacheView(paint_image,exception);
760 #if defined(MAGICKCORE_OPENMP_SUPPORT)
761 #pragma omp parallel for schedule(static) shared(progress,status) \
762 magick_number_threads(linear_image,paint_image,linear_image->rows,1)
764 for (y=0; y < (ssize_t) linear_image->rows; y++)
778 if (status == MagickFalse)
780 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
781 (width/2L),linear_image->columns+width,width,exception);
782 q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
784 if ((p == (
const Quantum *) NULL) || (q == (Quantum *) NULL))
789 histogram=histograms[GetOpenMPThreadId()];
790 for (x=0; x < (ssize_t) linear_image->columns; x++)
811 (void) memset(histogram,0,NumberPaintBins*
sizeof(*histogram));
812 for (v=0; v < (ssize_t) width; v++)
814 for (u=0; u < (ssize_t) width; u++)
816 n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(
817 linear_image,p+GetPixelChannels(linear_image)*(u+k))));
819 if (histogram[n] > count)
825 k+=(ssize_t) (linear_image->columns+width);
827 for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++)
829 PixelChannel channel = GetPixelChannelChannel(linear_image,i);
830 PixelTrait traits = GetPixelChannelTraits(linear_image,channel);
831 PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel);
832 if ((traits == UndefinedPixelTrait) ||
833 (paint_traits == UndefinedPixelTrait))
835 if ((paint_traits & CopyPixelTrait) != 0)
837 SetPixelChannel(paint_image,channel,p[center+i],q);
840 SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+
843 p+=GetPixelChannels(linear_image);
844 q+=GetPixelChannels(paint_image);
846 if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
848 if (linear_image->progress_monitor != (MagickProgressMonitor) NULL)
853 #if defined(MAGICKCORE_OPENMP_SUPPORT)
857 proceed=SetImageProgress(linear_image,OilPaintImageTag,progress,
859 if (proceed == MagickFalse)
863 paint_view=DestroyCacheView(paint_view);
864 image_view=DestroyCacheView(image_view);
865 histograms=DestroyHistogramTLS(histograms);
866 linear_image=DestroyImage(linear_image);
867 if (status == MagickFalse)
868 paint_image=DestroyImage(paint_image);
911 MagickExport MagickBooleanType OpaquePaintImage(
Image *image,
915 #define OpaquePaintImageTag "Opaque/Image"
934 assert(image != (
Image *) NULL);
935 assert(image->signature == MagickCoreSignature);
938 if (IsEventLogging() != MagickFalse)
939 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
940 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
942 ConformPixelInfo(image,fill,&conform_fill,exception);
943 ConformPixelInfo(image,target,&conform_target,exception);
949 GetPixelInfo(image,&zero);
950 image_view=AcquireAuthenticCacheView(image,exception);
951 #if defined(MAGICKCORE_OPENMP_SUPPORT)
952 #pragma omp parallel for schedule(static) shared(progress,status) \
953 magick_number_threads(image,image,image->rows,1)
955 for (y=0; y < (ssize_t) image->rows; y++)
966 if (status == MagickFalse)
968 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
969 if (q == (Quantum *) NULL)
975 for (x=0; x < (ssize_t) image->columns; x++)
977 GetPixelInfoPixel(image,q,&pixel);
978 if (IsFuzzyEquivalencePixelInfo(&pixel,&conform_target) != invert)
983 traits=GetPixelChannelTraits(image,RedPixelChannel);
984 if ((traits & UpdatePixelTrait) != 0)
985 SetPixelRed(image,(Quantum) conform_fill.red,q);
986 traits=GetPixelChannelTraits(image,GreenPixelChannel);
987 if ((traits & UpdatePixelTrait) != 0)
988 SetPixelGreen(image,(Quantum) conform_fill.green,q);
989 traits=GetPixelChannelTraits(image,BluePixelChannel);
990 if ((traits & UpdatePixelTrait) != 0)
991 SetPixelBlue(image,(Quantum) conform_fill.blue,q);
992 traits=GetPixelChannelTraits(image,BlackPixelChannel);
993 if ((traits & UpdatePixelTrait) != 0)
994 SetPixelBlack(image,(Quantum) conform_fill.black,q);
995 traits=GetPixelChannelTraits(image,AlphaPixelChannel);
996 if ((traits & UpdatePixelTrait) != 0)
997 SetPixelAlpha(image,(Quantum) conform_fill.alpha,q);
999 q+=GetPixelChannels(image);
1001 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1003 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1008 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1012 proceed=SetImageProgress(image,OpaquePaintImageTag,progress,
1014 if (proceed == MagickFalse)
1018 image_view=DestroyCacheView(image_view);
1061 MagickExport MagickBooleanType TransparentPaintImage(
Image *image,
1062 const PixelInfo *target,
const Quantum opacity,
const MagickBooleanType invert,
1065 #define TransparentPaintImageTag "Transparent/Image"
1082 assert(image != (
Image *) NULL);
1083 assert(image->signature == MagickCoreSignature);
1085 if (IsEventLogging() != MagickFalse)
1086 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1087 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1088 return(MagickFalse);
1089 if (image->alpha_trait == UndefinedPixelTrait)
1090 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1096 GetPixelInfo(image,&zero);
1097 image_view=AcquireAuthenticCacheView(image,exception);
1098 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1099 #pragma omp parallel for schedule(static) shared(progress,status) \
1100 magick_number_threads(image,image,image->rows,1)
1102 for (y=0; y < (ssize_t) image->rows; y++)
1113 if (status == MagickFalse)
1115 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1116 if (q == (Quantum *) NULL)
1122 for (x=0; x < (ssize_t) image->columns; x++)
1124 GetPixelInfoPixel(image,q,&pixel);
1125 if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert)
1126 SetPixelAlpha(image,opacity,q);
1127 q+=GetPixelChannels(image);
1129 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1131 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1136 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1140 proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1142 if (proceed == MagickFalse)
1146 image_view=DestroyCacheView(image_view);
1192 MagickExport MagickBooleanType TransparentPaintImageChroma(
Image *image,
1196 #define TransparentPaintImageTag "Transparent/Image"
1210 assert(image != (
Image *) NULL);
1211 assert(image->signature == MagickCoreSignature);
1214 if (IsEventLogging() != MagickFalse)
1215 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1216 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1217 return(MagickFalse);
1218 if (image->alpha_trait == UndefinedPixelTrait)
1219 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1225 image_view=AcquireAuthenticCacheView(image,exception);
1226 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1227 #pragma omp parallel for schedule(static) shared(progress,status) \
1228 magick_number_threads(image,image,image->rows,1)
1230 for (y=0; y < (ssize_t) image->rows; y++)
1244 if (status == MagickFalse)
1246 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1247 if (q == (Quantum *) NULL)
1252 GetPixelInfo(image,&pixel);
1253 for (x=0; x < (ssize_t) image->columns; x++)
1255 GetPixelInfoPixel(image,q,&pixel);
1256 match=((pixel.red >= low->red) && (pixel.red <= high->red) &&
1257 (pixel.green >= low->green) && (pixel.green <= high->green) &&
1258 (pixel.blue >= low->blue) && (pixel.blue <= high->blue)) ? MagickTrue :
1260 if (match != invert)
1261 SetPixelAlpha(image,opacity,q);
1262 q+=GetPixelChannels(image);
1264 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1266 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1271 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1275 proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1277 if (proceed == MagickFalse)
1281 image_view=DestroyCacheView(image_view);