42 #include "magick/studio.h"
43 #include "magick/artifact.h"
44 #include "magick/cache.h"
45 #include "magick/channel.h"
46 #include "magick/color-private.h"
47 #include "magick/colorspace-private.h"
48 #include "magick/composite.h"
49 #include "magick/composite-private.h"
50 #include "magick/draw.h"
51 #include "magick/draw-private.h"
52 #include "magick/exception.h"
53 #include "magick/exception-private.h"
54 #include "magick/gem.h"
55 #include "magick/monitor.h"
56 #include "magick/monitor-private.h"
57 #include "magick/option.h"
58 #include "magick/paint.h"
59 #include "magick/pixel-private.h"
60 #include "magick/resource_.h"
61 #include "magick/string_.h"
62 #include "magick/string-private.h"
63 #include "magick/thread-private.h"
110 MagickExport MagickBooleanType FloodfillPaintImage(
Image *image,
111 const ChannelType channel,
const DrawInfo *draw_info,
113 const MagickBooleanType invert)
115 #define MaxStacksize 524288UL
116 #define PushSegmentStack(up,left,right,delta) \
118 if (s >= (segment_stack+MaxStacksize)) \
120 segment_info=RelinquishVirtualMemory(segment_info); \
121 image_view=DestroyCacheView(image_view); \
122 floodplane_view=DestroyCacheView(floodplane_view); \
123 floodplane_image=DestroyImage(floodplane_image); \
124 ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \
128 if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \
130 s->x1=(double) (left); \
131 s->y1=(double) (up); \
132 s->x2=(double) (right); \
133 s->y2=(double) (delta); \
179 assert(image != (
Image *) NULL);
180 assert(image->signature == MagickCoreSignature);
181 assert(draw_info != (
DrawInfo *) NULL);
182 assert(draw_info->signature == MagickCoreSignature);
183 if (IsEventLogging() != MagickFalse)
184 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
185 if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
187 if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
189 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
191 exception=(&image->exception);
192 if (IsGrayColorspace(image->colorspace) != MagickFalse)
193 (
void) SetImageColorspace(image,sRGBColorspace);
194 if ((image->matte == MagickFalse) &&
195 (draw_info->fill.opacity != OpaqueOpacity))
196 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
200 floodplane_image=CloneImage(image,0,0,MagickTrue,&image->exception);
201 if (floodplane_image == (
Image *) NULL)
203 (void) SetImageAlphaChannel(floodplane_image,OpaqueAlphaChannel);
204 segment_info=AcquireVirtualMemory(MaxStacksize,
sizeof(*segment_stack));
207 floodplane_image=DestroyImage(floodplane_image);
208 ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
211 segment_stack=(
SegmentInfo *) GetVirtualMemoryBlob(segment_info);
219 GetMagickPixelPacket(image,&fill);
220 GetMagickPixelPacket(image,&pixel);
221 image_view=AcquireVirtualCacheView(image,exception);
222 floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
223 PushSegmentStack(y,x,x,1);
224 PushSegmentStack(y+1,x,x,-1);
225 while (s > segment_stack)
228 *magick_restrict indexes;
245 offset=(ssize_t) s->y2;
246 y=(ssize_t) s->y1+offset;
250 p=GetCacheViewVirtualPixels(image_view,0,y,(
size_t) (x1+1),1,exception);
251 q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(
size_t) (x1+1),1,
255 indexes=GetCacheViewVirtualIndexQueue(image_view);
258 for (x=x1; x >= 0; x--)
260 if (q->opacity == (Quantum) TransparentOpacity)
262 SetMagickPixelPacket(image,p,indexes+x,&pixel);
263 if (IsMagickColorSimilar(&pixel,target) == invert)
265 q->opacity=(Quantum) TransparentOpacity;
269 if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
271 skip=x >= x1 ? MagickTrue : MagickFalse;
272 if (skip == MagickFalse)
276 PushSegmentStack(y,start,x1-1,-offset);
281 if (skip == MagickFalse)
283 if (x < (ssize_t) image->columns)
285 p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1,
287 q=GetCacheViewAuthenticPixels(floodplane_view,x,y,
288 image->columns-x,1,exception);
292 indexes=GetCacheViewVirtualIndexQueue(image_view);
293 for ( ; x < (ssize_t) image->columns; x++)
295 if (q->opacity == (Quantum) TransparentOpacity)
297 SetMagickPixelPacket(image,p,indexes+x,&pixel);
298 if (IsMagickColorSimilar(&pixel,target) == invert)
300 q->opacity=(Quantum) TransparentOpacity;
304 if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
307 PushSegmentStack(y,start,x-1,offset);
309 PushSegmentStack(y,x2+1,x-1,-offset);
315 p=GetCacheViewVirtualPixels(image_view,x,y,(
size_t) (x2-x+1),1,
317 q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(
size_t) (x2-x+1),1,
321 indexes=GetCacheViewVirtualIndexQueue(image_view);
322 for ( ; x <= x2; x++)
324 if (q->opacity == (Quantum) TransparentOpacity)
326 SetMagickPixelPacket(image,p,indexes+x,&pixel);
327 if (IsMagickColorSimilar(&pixel,target) != invert)
336 for (y=0; y < (ssize_t) image->rows; y++)
342 *magick_restrict indexes;
353 p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,
355 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
358 indexes=GetCacheViewAuthenticIndexQueue(image_view);
359 for (x=0; x < (ssize_t) image->columns; x++)
361 if (GetPixelOpacity(p) != OpaqueOpacity)
363 (void) GetFillColor(draw_info,x,y,&fill_color);
364 SetMagickPixelPacket(image,&fill_color,(IndexPacket *) NULL,&fill);
365 if (image->colorspace == CMYKColorspace)
366 ConvertRGBToCMYK(&fill);
367 if ((channel & RedChannel) != 0)
368 SetPixelRed(q,ClampToQuantum(fill.red));
369 if ((channel & GreenChannel) != 0)
370 SetPixelGreen(q,ClampToQuantum(fill.green));
371 if ((channel & BlueChannel) != 0)
372 SetPixelBlue(q,ClampToQuantum(fill.blue));
373 if (((channel & OpacityChannel) != 0) ||
374 (draw_info->fill.opacity != OpaqueOpacity))
375 SetPixelOpacity(q,ClampToQuantum(fill.opacity));
376 if (((channel & IndexChannel) != 0) &&
377 (image->colorspace == CMYKColorspace))
378 SetPixelIndex(indexes+x,ClampToQuantum(fill.index));
383 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
386 floodplane_view=DestroyCacheView(floodplane_view);
387 image_view=DestroyCacheView(image_view);
388 segment_info=RelinquishVirtualMemory(segment_info);
389 floodplane_image=DestroyImage(floodplane_image);
390 return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
432 MagickExport MagickBooleanType GradientImage(
Image *image,
433 const GradientType type,
const SpreadMethod method,
454 assert(image != (
const Image *) NULL);
455 assert(image->signature == MagickCoreSignature);
458 if (IsEventLogging() != MagickFalse)
459 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
460 draw_info=AcquireDrawInfo();
461 gradient=(&draw_info->gradient);
463 gradient->bounding_box.width=image->columns;
464 gradient->bounding_box.height=image->rows;
465 artifact=GetImageArtifact(image,
"gradient:bounding-box");
466 if (artifact != (
const char *) NULL)
467 (void) ParseAbsoluteGeometry(artifact,&gradient->bounding_box);
468 gradient->gradient_vector.x2=(double) image->columns-1;
469 gradient->gradient_vector.y2=(
double) image->rows-1;
470 artifact=GetImageArtifact(image,
"gradient:direction");
471 if (artifact != (
const char *) NULL)
476 direction=(GravityType) ParseCommandOption(MagickGravityOptions,
477 MagickFalse,artifact);
480 case NorthWestGravity:
482 gradient->gradient_vector.x1=(double) image->columns-1;
483 gradient->gradient_vector.y1=(
double) image->rows-1;
484 gradient->gradient_vector.x2=0.0;
485 gradient->gradient_vector.y2=0.0;
490 gradient->gradient_vector.x1=0.0;
491 gradient->gradient_vector.y1=(double) image->rows-1;
492 gradient->gradient_vector.x2=0.0;
493 gradient->gradient_vector.y2=0.0;
496 case NorthEastGravity:
498 gradient->gradient_vector.x1=0.0;
499 gradient->gradient_vector.y1=(double) image->rows-1;
500 gradient->gradient_vector.x2=(
double) image->columns-1;
501 gradient->gradient_vector.y2=0.0;
506 gradient->gradient_vector.x1=(double) image->columns-1;
507 gradient->gradient_vector.y1=0.0;
508 gradient->gradient_vector.x2=0.0;
509 gradient->gradient_vector.y2=0.0;
514 gradient->gradient_vector.x1=0.0;
515 gradient->gradient_vector.y1=0.0;
516 gradient->gradient_vector.x2=(double) image->columns-1;
517 gradient->gradient_vector.y2=0.0;
520 case SouthWestGravity:
522 gradient->gradient_vector.x1=(double) image->columns-1;
523 gradient->gradient_vector.y1=0.0;
524 gradient->gradient_vector.x2=0.0;
525 gradient->gradient_vector.y2=(
double) image->rows-1;
530 gradient->gradient_vector.x1=0.0;
531 gradient->gradient_vector.y1=0.0;
532 gradient->gradient_vector.x2=0.0;
533 gradient->gradient_vector.y2=(double) image->columns-1;
536 case SouthEastGravity:
538 gradient->gradient_vector.x1=0.0;
539 gradient->gradient_vector.y1=0.0;
540 gradient->gradient_vector.x2=(double) image->columns-1;
541 gradient->gradient_vector.y2=(
double) image->rows-1;
548 artifact=GetImageArtifact(image,
"gradient:angle");
549 if (artifact != (
const char *) NULL)
550 gradient->angle=(MagickRealType) StringToDouble(artifact,(
char **) NULL);
551 artifact=GetImageArtifact(image,
"gradient:vector");
552 if (artifact != (
const char *) NULL)
553 (void) sscanf(artifact,
"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf",
554 &gradient->gradient_vector.x1,&gradient->gradient_vector.y1,
555 &gradient->gradient_vector.x2,&gradient->gradient_vector.y2);
556 if ((GetImageArtifact(image,
"gradient:angle") == (
const char *) NULL) &&
557 (GetImageArtifact(image,
"gradient:direction") == (
const char *) NULL) &&
558 (GetImageArtifact(image,
"gradient:extent") == (
const char *) NULL) &&
559 (GetImageArtifact(image,
"gradient:vector") == (
const char *) NULL))
560 if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0))
561 gradient->gradient_vector.x2=0.0;
562 gradient->center.x=(
double) gradient->gradient_vector.x2/2.0;
563 gradient->center.y=(double) gradient->gradient_vector.y2/2.0;
564 artifact=GetImageArtifact(image,
"gradient:center");
565 if (artifact != (
const char *) NULL)
566 (
void) sscanf(artifact,
"%lf%*[ ,]%lf",&gradient->center.x,
567 &gradient->center.y);
568 artifact=GetImageArtifact(image,
"gradient:angle");
569 if ((type == LinearGradient) && (artifact != (
const char *) NULL))
579 sine=sin((
double) DegreesToRadians(gradient->angle-90.0));
580 cosine=cos((
double) DegreesToRadians(gradient->angle-90.0));
581 distance=fabs((
double) (image->columns-1)*cosine)+
582 fabs((
double) (image->rows-1)*sine);
583 gradient->gradient_vector.x1=0.5*((image->columns-1)-distance*cosine);
584 gradient->gradient_vector.y1=0.5*((image->rows-1)-distance*sine);
585 gradient->gradient_vector.x2=0.5*((image->columns-1)+distance*cosine);
586 gradient->gradient_vector.y2=0.5*((image->rows-1)+distance*sine);
588 gradient->radii.x=(double) MagickMax((image->columns-1),(image->rows-1))/2.0;
589 gradient->radii.y=gradient->radii.x;
590 artifact=GetImageArtifact(image,
"gradient:extent");
591 if (artifact != (
const char *) NULL)
593 if (LocaleCompare(artifact,
"Circle") == 0)
595 gradient->radii.x=(double) (MagickMax((image->columns-1),
596 (image->rows-1)))/2.0;
597 gradient->radii.y=gradient->radii.x;
599 if (LocaleCompare(artifact,
"Diagonal") == 0)
601 gradient->radii.x=(double) (sqrt((
double) (image->columns-1)*
602 (image->columns-1)+(image->rows-1)*(image->rows-1)))/2.0;
603 gradient->radii.y=gradient->radii.x;
605 if (LocaleCompare(artifact,
"Ellipse") == 0)
607 gradient->radii.x=(double) (image->columns-1)/2.0;
608 gradient->radii.y=(double) (image->rows-1)/2.0;
610 if (LocaleCompare(artifact,
"Maximum") == 0)
612 gradient->radii.x=(double) MagickMax((image->columns-1),
613 (image->rows-1))/2.0;
614 gradient->radii.y=gradient->radii.x;
616 if (LocaleCompare(artifact,
"Minimum") == 0)
618 gradient->radii.x=(double) MagickMin((image->columns-1),
619 (image->rows-1))/2.0;
620 gradient->radii.y=gradient->radii.x;
623 artifact=GetImageArtifact(image,
"gradient:radii");
624 if (artifact != (
const char *) NULL)
625 (void) sscanf(artifact,
"%lf%*[ ,]%lf",&gradient->radii.x,
627 gradient->radius=MagickMax(gradient->radii.x,gradient->radii.y);
628 gradient->spread=method;
632 gradient->number_stops=2;
633 gradient->stops=(
StopInfo *) AcquireQuantumMemory(gradient->number_stops,
634 sizeof(*gradient->stops));
635 if (gradient->stops == (
StopInfo *) NULL)
636 ThrowBinaryImageException(ResourceLimitError,
"MemoryAllocationFailed",
638 (void) memset(gradient->stops,0,gradient->number_stops*
639 sizeof(*gradient->stops));
640 for (i=0; i < (ssize_t) gradient->number_stops; i++)
641 GetMagickPixelPacket(image,&gradient->stops[i].color);
642 SetMagickPixelPacket(image,start_color,(IndexPacket *) NULL,
643 &gradient->stops[0].color);
644 gradient->stops[0].offset=0.0;
645 SetMagickPixelPacket(image,stop_color,(IndexPacket *) NULL,
646 &gradient->stops[1].color);
647 gradient->stops[1].offset=1.0;
651 status=DrawGradientImage(image,draw_info);
652 draw_info=DestroyDrawInfo(draw_info);
686 static size_t **DestroyHistogramTLS(
size_t **histogram)
691 assert(histogram != (
size_t **) NULL);
692 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
693 if (histogram[i] != (
size_t *) NULL)
694 histogram[i]=(
size_t *) RelinquishMagickMemory(histogram[i]);
695 histogram=(
size_t **) RelinquishMagickMemory(histogram);
699 static size_t **AcquireHistogramTLS(
const size_t count)
708 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
709 histogram=(
size_t **) AcquireQuantumMemory(number_threads,
711 if (histogram == (
size_t **) NULL)
712 return((
size_t **) NULL);
713 (void) memset(histogram,0,number_threads*
sizeof(*histogram));
714 for (i=0; i < (ssize_t) number_threads; i++)
716 histogram[i]=(
size_t *) AcquireQuantumMemory(count,
717 sizeof(**histogram));
718 if (histogram[i] == (
size_t *) NULL)
719 return(DestroyHistogramTLS(histogram));
724 MagickExport
Image *OilPaintImage(
const Image *image,
const double radius,
727 #define NumberPaintBins 256
728 #define OilPaintImageTag "OilPaint/Image"
745 **magick_restrict histograms,
754 assert(image != (
const Image *) NULL);
755 assert(image->signature == MagickCoreSignature);
757 assert(exception->signature == MagickCoreSignature);
758 if (IsEventLogging() != MagickFalse)
759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
760 width=GetOptimalKernelWidth2D(radius,0.5);
761 linear_image=CloneImage(image,0,0,MagickTrue,exception);
762 paint_image=CloneImage(image,0,0,MagickTrue,exception);
763 if ((linear_image == (
Image *) NULL) || (paint_image == (
Image *) NULL))
765 if (linear_image != (
Image *) NULL)
766 linear_image=DestroyImage(linear_image);
767 if (paint_image != (
Image *) NULL)
768 linear_image=DestroyImage(paint_image);
769 return((
Image *) NULL);
771 if (SetImageStorageClass(paint_image,DirectClass) == MagickFalse)
773 InheritException(exception,&paint_image->exception);
774 linear_image=DestroyImage(linear_image);
775 paint_image=DestroyImage(paint_image);
776 return((
Image *) NULL);
778 histograms=AcquireHistogramTLS(NumberPaintBins);
779 if (histograms == (
size_t **) NULL)
781 linear_image=DestroyImage(linear_image);
782 paint_image=DestroyImage(paint_image);
783 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
790 image_view=AcquireVirtualCacheView(linear_image,exception);
791 paint_view=AcquireAuthenticCacheView(paint_image,exception);
792 #if defined(MAGICKCORE_OPENMP_SUPPORT)
793 #pragma omp parallel for schedule(static) shared(progress,status) \
794 magick_number_threads(linear_image,paint_image,linear_image->rows,1)
796 for (y=0; y < (ssize_t) linear_image->rows; y++)
799 *magick_restrict indexes;
805 *magick_restrict paint_indexes;
816 if (status == MagickFalse)
818 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
819 (width/2L),linear_image->columns+width,width,exception);
820 q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
827 indexes=GetCacheViewVirtualIndexQueue(image_view);
828 paint_indexes=GetCacheViewAuthenticIndexQueue(paint_view);
829 histogram=histograms[GetOpenMPThreadId()];
830 for (x=0; x < (ssize_t) linear_image->columns; x++)
850 (void) memset(histogram,0,NumberPaintBins*
sizeof(*histogram));
851 for (v=0; v < (ssize_t) width; v++)
853 for (u=0; u < (ssize_t) width; u++)
855 k=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(
856 linear_image,p+u+i)));
858 if (histogram[k] > count)
864 i+=(ssize_t) (linear_image->columns+width);
867 if (linear_image->colorspace == CMYKColorspace)
868 SetPixelIndex(paint_indexes+x,GetPixelIndex(indexes+x+j));
872 if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
874 if (image->progress_monitor != (MagickProgressMonitor) NULL)
879 #if defined(MAGICKCORE_OPENMP_SUPPORT)
883 proceed=SetImageProgress(image,OilPaintImageTag,progress,image->rows);
884 if (proceed == MagickFalse)
888 paint_view=DestroyCacheView(paint_view);
889 image_view=DestroyCacheView(image_view);
890 histograms=DestroyHistogramTLS(histograms);
891 linear_image=DestroyImage(linear_image);
892 if (status == MagickFalse)
893 paint_image=DestroyImage(paint_image);
940 MagickExport MagickBooleanType OpaquePaintImage(
Image *image,
942 const MagickBooleanType invert)
944 return(OpaquePaintImageChannel(image,CompositeChannels,target,fill,invert));
947 MagickExport MagickBooleanType OpaquePaintImageChannel(
Image *image,
951 #define OpaquePaintImageTag "Opaque/Image"
973 assert(image != (
Image *) NULL);
974 assert(image->signature == MagickCoreSignature);
977 if (IsEventLogging() != MagickFalse)
978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
979 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
981 exception=(&image->exception);
982 ConformMagickPixelPacket(image,fill,&conform_fill,exception);
983 ConformMagickPixelPacket(image,target,&conform_target,exception);
989 GetMagickPixelPacket(image,&zero);
990 image_view=AcquireAuthenticCacheView(image,exception);
991 #if defined(MAGICKCORE_OPENMP_SUPPORT)
992 #pragma omp parallel for schedule(static) shared(progress,status) \
993 magick_number_threads(image,image,image->rows,1)
995 for (y=0; y < (ssize_t) image->rows; y++)
1001 *magick_restrict indexes;
1009 if (status == MagickFalse)
1011 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1017 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1019 for (x=0; x < (ssize_t) image->columns; x++)
1021 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1022 if (IsMagickColorSimilar(&pixel,&conform_target) != invert)
1024 if ((channel & RedChannel) != 0)
1025 SetPixelRed(q,ClampToQuantum(conform_fill.red));
1026 if ((channel & GreenChannel) != 0)
1027 SetPixelGreen(q,ClampToQuantum(conform_fill.green));
1028 if ((channel & BlueChannel) != 0)
1029 SetPixelBlue(q,ClampToQuantum(conform_fill.blue));
1030 if ((channel & OpacityChannel) != 0)
1031 SetPixelOpacity(q,ClampToQuantum(conform_fill.opacity));
1032 if (((channel & IndexChannel) != 0) &&
1033 (image->colorspace == CMYKColorspace))
1034 SetPixelIndex(indexes+x,ClampToQuantum(conform_fill.index));
1038 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1040 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1045 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1049 proceed=SetImageProgress(image,OpaquePaintImageTag,progress,
1051 if (proceed == MagickFalse)
1055 image_view=DestroyCacheView(image_view);
1096 MagickExport MagickBooleanType TransparentPaintImage(
Image *image,
1098 const MagickBooleanType invert)
1100 #define TransparentPaintImageTag "Transparent/Image"
1120 assert(image != (
Image *) NULL);
1121 assert(image->signature == MagickCoreSignature);
1123 if (IsEventLogging() != MagickFalse)
1124 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1125 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1126 return(MagickFalse);
1127 if (image->matte == MagickFalse)
1128 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1134 exception=(&image->exception);
1135 GetMagickPixelPacket(image,&zero);
1136 image_view=AcquireAuthenticCacheView(image,exception);
1137 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1138 #pragma omp parallel for schedule(static) shared(progress,status) \
1139 magick_number_threads(image,image,image->rows,1)
1141 for (y=0; y < (ssize_t) image->rows; y++)
1147 *magick_restrict indexes;
1155 if (status == MagickFalse)
1157 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1163 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1165 for (x=0; x < (ssize_t) image->columns; x++)
1167 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1168 if (IsMagickColorSimilar(&pixel,target) != invert)
1172 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1174 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1179 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1183 proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1185 if (proceed == MagickFalse)
1189 image_view=DestroyCacheView(image_view);
1233 MagickExport MagickBooleanType TransparentPaintImageChroma(
Image *image,
1235 const Quantum opacity,
const MagickBooleanType invert)
1237 #define TransparentPaintImageTag "Transparent/Image"
1254 assert(image != (
Image *) NULL);
1255 assert(image->signature == MagickCoreSignature);
1258 if (IsEventLogging() != MagickFalse)
1259 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1260 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1261 return(MagickFalse);
1262 if (image->matte == MagickFalse)
1263 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
1269 exception=(&image->exception);
1270 image_view=AcquireAuthenticCacheView(image,exception);
1271 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1272 #pragma omp parallel for schedule(static) shared(progress,status) \
1273 magick_number_threads(image,image,image->rows,1)
1275 for (y=0; y < (ssize_t) image->rows; y++)
1284 *magick_restrict indexes;
1292 if (status == MagickFalse)
1294 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1300 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1301 GetMagickPixelPacket(image,&pixel);
1302 for (x=0; x < (ssize_t) image->columns; x++)
1304 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1305 match=((pixel.red >= low->red) && (pixel.red <= high->red) &&
1306 (pixel.green >= low->green) && (pixel.green <= high->green) &&
1307 (pixel.blue >= low->blue) && (pixel.blue <= high->blue)) ? MagickTrue : MagickFalse;
1308 if (match != invert)
1312 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1314 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1319 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1323 proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1325 if (proceed == MagickFalse)
1329 image_view=DestroyCacheView(image_view);