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 floodplane_image->matte=MagickFalse;
204 floodplane_image->colorspace=GRAYColorspace;
205 (void) QueryColorCompliance(
"#000",AllCompliance,
206 &floodplane_image->background_color,exception);
207 (void) SetImageBackgroundColor(floodplane_image);
208 segment_info=AcquireVirtualMemory(MaxStacksize,
sizeof(*segment_stack));
211 floodplane_image=DestroyImage(floodplane_image);
212 ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
215 segment_stack=(
SegmentInfo *) GetVirtualMemoryBlob(segment_info);
223 GetMagickPixelPacket(image,&fill);
224 GetMagickPixelPacket(image,&pixel);
225 image_view=AcquireVirtualCacheView(image,exception);
226 floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
227 PushSegmentStack(y,x,x,1);
228 PushSegmentStack(y+1,x,x,-1);
229 while (s > segment_stack)
232 *magick_restrict indexes;
249 offset=(ssize_t) s->y2;
250 y=(ssize_t) s->y1+offset;
254 p=GetCacheViewVirtualPixels(image_view,0,y,(
size_t) (x1+1),1,exception);
255 q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(
size_t) (x1+1),1,
259 indexes=GetCacheViewVirtualIndexQueue(image_view);
262 for (x=x1; x >= 0; x--)
264 if (GetPixelGray(q) != 0)
266 SetMagickPixelPacket(image,p,indexes+x,&pixel);
267 if (IsMagickColorSimilar(&pixel,target) == invert)
269 SetPixelGray(q,QuantumRange);
273 if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
275 skip=x >= x1 ? MagickTrue : MagickFalse;
276 if (skip == MagickFalse)
280 PushSegmentStack(y,start,x1-1,-offset);
285 if (skip == MagickFalse)
287 if (x < (ssize_t) image->columns)
289 p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1,
291 q=GetCacheViewAuthenticPixels(floodplane_view,x,y,
292 image->columns-x,1,exception);
296 indexes=GetCacheViewVirtualIndexQueue(image_view);
297 for ( ; x < (ssize_t) image->columns; x++)
299 if (GetPixelGray(q) != 0)
301 SetMagickPixelPacket(image,p,indexes+x,&pixel);
302 if (IsMagickColorSimilar(&pixel,target) == invert)
304 SetPixelGray(q,QuantumRange);
308 if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
311 PushSegmentStack(y,start,x-1,offset);
313 PushSegmentStack(y,x2+1,x-1,-offset);
319 p=GetCacheViewVirtualPixels(image_view,x,y,(
size_t) (x2-x+1),1,
321 q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(
size_t) (x2-x+1),1,
325 indexes=GetCacheViewVirtualIndexQueue(image_view);
326 for ( ; x <= x2; x++)
328 if (GetPixelGray(q) != 0)
330 SetMagickPixelPacket(image,p,indexes+x,&pixel);
331 if (IsMagickColorSimilar(&pixel,target) != invert)
340 for (y=0; y < (ssize_t) image->rows; y++)
346 *magick_restrict indexes;
357 p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,
359 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
362 indexes=GetCacheViewAuthenticIndexQueue(image_view);
363 for (x=0; x < (ssize_t) image->columns; x++)
365 if (GetPixelGray(p) != 0)
367 (void) GetFillColor(draw_info,x,y,&fill_color);
368 SetMagickPixelPacket(image,&fill_color,(IndexPacket *) NULL,&fill);
369 if (image->colorspace == CMYKColorspace)
370 ConvertRGBToCMYK(&fill);
371 if ((channel & RedChannel) != 0)
372 SetPixelRed(q,ClampToQuantum(fill.red));
373 if ((channel & GreenChannel) != 0)
374 SetPixelGreen(q,ClampToQuantum(fill.green));
375 if ((channel & BlueChannel) != 0)
376 SetPixelBlue(q,ClampToQuantum(fill.blue));
377 if (((channel & OpacityChannel) != 0) ||
378 (draw_info->fill.opacity != OpaqueOpacity))
379 SetPixelOpacity(q,ClampToQuantum(fill.opacity));
380 if (((channel & IndexChannel) != 0) &&
381 (image->colorspace == CMYKColorspace))
382 SetPixelIndex(indexes+x,ClampToQuantum(fill.index));
387 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
390 floodplane_view=DestroyCacheView(floodplane_view);
391 image_view=DestroyCacheView(image_view);
392 segment_info=RelinquishVirtualMemory(segment_info);
393 floodplane_image=DestroyImage(floodplane_image);
394 return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
436 MagickExport MagickBooleanType GradientImage(
Image *image,
437 const GradientType type,
const SpreadMethod method,
458 assert(image != (
const Image *) NULL);
459 assert(image->signature == MagickCoreSignature);
462 if (IsEventLogging() != MagickFalse)
463 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
464 draw_info=AcquireDrawInfo();
465 gradient=(&draw_info->gradient);
467 gradient->bounding_box.width=image->columns;
468 gradient->bounding_box.height=image->rows;
469 artifact=GetImageArtifact(image,
"gradient:bounding-box");
470 if (artifact != (
const char *) NULL)
471 (void) ParseAbsoluteGeometry(artifact,&gradient->bounding_box);
472 gradient->gradient_vector.x2=(double) image->columns-1;
473 gradient->gradient_vector.y2=(
double) image->rows-1;
474 artifact=GetImageArtifact(image,
"gradient:direction");
475 if (artifact != (
const char *) NULL)
480 direction=(GravityType) ParseCommandOption(MagickGravityOptions,
481 MagickFalse,artifact);
484 case NorthWestGravity:
486 gradient->gradient_vector.x1=(double) image->columns-1;
487 gradient->gradient_vector.y1=(
double) image->rows-1;
488 gradient->gradient_vector.x2=0.0;
489 gradient->gradient_vector.y2=0.0;
494 gradient->gradient_vector.x1=0.0;
495 gradient->gradient_vector.y1=(double) image->rows-1;
496 gradient->gradient_vector.x2=0.0;
497 gradient->gradient_vector.y2=0.0;
500 case NorthEastGravity:
502 gradient->gradient_vector.x1=0.0;
503 gradient->gradient_vector.y1=(double) image->rows-1;
504 gradient->gradient_vector.x2=(
double) image->columns-1;
505 gradient->gradient_vector.y2=0.0;
510 gradient->gradient_vector.x1=(double) image->columns-1;
511 gradient->gradient_vector.y1=0.0;
512 gradient->gradient_vector.x2=0.0;
513 gradient->gradient_vector.y2=0.0;
518 gradient->gradient_vector.x1=0.0;
519 gradient->gradient_vector.y1=0.0;
520 gradient->gradient_vector.x2=(double) image->columns-1;
521 gradient->gradient_vector.y2=0.0;
524 case SouthWestGravity:
526 gradient->gradient_vector.x1=(double) image->columns-1;
527 gradient->gradient_vector.y1=0.0;
528 gradient->gradient_vector.x2=0.0;
529 gradient->gradient_vector.y2=(
double) image->rows-1;
534 gradient->gradient_vector.x1=0.0;
535 gradient->gradient_vector.y1=0.0;
536 gradient->gradient_vector.x2=0.0;
537 gradient->gradient_vector.y2=(double) image->columns-1;
540 case SouthEastGravity:
542 gradient->gradient_vector.x1=0.0;
543 gradient->gradient_vector.y1=0.0;
544 gradient->gradient_vector.x2=(double) image->columns-1;
545 gradient->gradient_vector.y2=(
double) image->rows-1;
552 artifact=GetImageArtifact(image,
"gradient:angle");
553 if (artifact != (
const char *) NULL)
554 gradient->angle=(MagickRealType) StringToDouble(artifact,(
char **) NULL);
555 artifact=GetImageArtifact(image,
"gradient:vector");
556 if (artifact != (
const char *) NULL)
557 (void) sscanf(artifact,
"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf",
558 &gradient->gradient_vector.x1,&gradient->gradient_vector.y1,
559 &gradient->gradient_vector.x2,&gradient->gradient_vector.y2);
560 if ((GetImageArtifact(image,
"gradient:angle") == (
const char *) NULL) &&
561 (GetImageArtifact(image,
"gradient:direction") == (
const char *) NULL) &&
562 (GetImageArtifact(image,
"gradient:extent") == (
const char *) NULL) &&
563 (GetImageArtifact(image,
"gradient:vector") == (
const char *) NULL))
564 if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0))
565 gradient->gradient_vector.x2=0.0;
566 gradient->center.x=(
double) gradient->gradient_vector.x2/2.0;
567 gradient->center.y=(double) gradient->gradient_vector.y2/2.0;
568 artifact=GetImageArtifact(image,
"gradient:center");
569 if (artifact != (
const char *) NULL)
570 (
void) sscanf(artifact,
"%lf%*[ ,]%lf",&gradient->center.x,
571 &gradient->center.y);
572 artifact=GetImageArtifact(image,
"gradient:angle");
573 if ((type == LinearGradient) && (artifact != (
const char *) NULL))
583 sine=sin((
double) DegreesToRadians(gradient->angle-90.0));
584 cosine=cos((
double) DegreesToRadians(gradient->angle-90.0));
585 distance=fabs((
double) (image->columns-1)*cosine)+
586 fabs((
double) (image->rows-1)*sine);
587 gradient->gradient_vector.x1=0.5*((image->columns-1)-distance*cosine);
588 gradient->gradient_vector.y1=0.5*((image->rows-1)-distance*sine);
589 gradient->gradient_vector.x2=0.5*((image->columns-1)+distance*cosine);
590 gradient->gradient_vector.y2=0.5*((image->rows-1)+distance*sine);
592 gradient->radii.x=(double) MagickMax((image->columns-1),(image->rows-1))/2.0;
593 gradient->radii.y=gradient->radii.x;
594 artifact=GetImageArtifact(image,
"gradient:extent");
595 if (artifact != (
const char *) NULL)
597 if (LocaleCompare(artifact,
"Circle") == 0)
599 gradient->radii.x=(double) (MagickMax((image->columns-1),
600 (image->rows-1)))/2.0;
601 gradient->radii.y=gradient->radii.x;
603 if (LocaleCompare(artifact,
"Diagonal") == 0)
605 gradient->radii.x=(double) (sqrt((
double) (image->columns-1)*
606 (image->columns-1)+(image->rows-1)*(image->rows-1)))/2.0;
607 gradient->radii.y=gradient->radii.x;
609 if (LocaleCompare(artifact,
"Ellipse") == 0)
611 gradient->radii.x=(double) (image->columns-1)/2.0;
612 gradient->radii.y=(double) (image->rows-1)/2.0;
614 if (LocaleCompare(artifact,
"Maximum") == 0)
616 gradient->radii.x=(double) MagickMax((image->columns-1),
617 (image->rows-1))/2.0;
618 gradient->radii.y=gradient->radii.x;
620 if (LocaleCompare(artifact,
"Minimum") == 0)
622 gradient->radii.x=(double) MagickMin((image->columns-1),
623 (image->rows-1))/2.0;
624 gradient->radii.y=gradient->radii.x;
627 artifact=GetImageArtifact(image,
"gradient:radii");
628 if (artifact != (
const char *) NULL)
629 (void) sscanf(artifact,
"%lf%*[ ,]%lf",&gradient->radii.x,
631 gradient->radius=MagickMax(gradient->radii.x,gradient->radii.y);
632 gradient->spread=method;
636 gradient->number_stops=2;
637 gradient->stops=(
StopInfo *) AcquireQuantumMemory(gradient->number_stops,
638 sizeof(*gradient->stops));
639 if (gradient->stops == (
StopInfo *) NULL)
640 ThrowBinaryImageException(ResourceLimitError,
"MemoryAllocationFailed",
642 (void) memset(gradient->stops,0,gradient->number_stops*
643 sizeof(*gradient->stops));
644 for (i=0; i < (ssize_t) gradient->number_stops; i++)
645 GetMagickPixelPacket(image,&gradient->stops[i].color);
646 SetMagickPixelPacket(image,start_color,(IndexPacket *) NULL,
647 &gradient->stops[0].color);
648 gradient->stops[0].offset=0.0;
649 SetMagickPixelPacket(image,stop_color,(IndexPacket *) NULL,
650 &gradient->stops[1].color);
651 gradient->stops[1].offset=1.0;
655 status=DrawGradientImage(image,draw_info);
656 draw_info=DestroyDrawInfo(draw_info);
690 static size_t **DestroyHistogramTLS(
size_t **histogram)
695 assert(histogram != (
size_t **) NULL);
696 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
697 if (histogram[i] != (
size_t *) NULL)
698 histogram[i]=(
size_t *) RelinquishMagickMemory(histogram[i]);
699 histogram=(
size_t **) RelinquishMagickMemory(histogram);
703 static size_t **AcquireHistogramTLS(
const size_t count)
712 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
713 histogram=(
size_t **) AcquireQuantumMemory(number_threads,
715 if (histogram == (
size_t **) NULL)
716 return((
size_t **) NULL);
717 (void) memset(histogram,0,number_threads*
sizeof(*histogram));
718 for (i=0; i < (ssize_t) number_threads; i++)
720 histogram[i]=(
size_t *) AcquireQuantumMemory(count,
721 sizeof(**histogram));
722 if (histogram[i] == (
size_t *) NULL)
723 return(DestroyHistogramTLS(histogram));
728 MagickExport
Image *OilPaintImage(
const Image *image,
const double radius,
731 #define NumberPaintBins 256
732 #define OilPaintImageTag "OilPaint/Image"
749 **magick_restrict histograms,
758 assert(image != (
const Image *) NULL);
759 assert(image->signature == MagickCoreSignature);
761 assert(exception->signature == MagickCoreSignature);
762 if (IsEventLogging() != MagickFalse)
763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
764 width=GetOptimalKernelWidth2D(radius,0.5);
765 linear_image=CloneImage(image,0,0,MagickTrue,exception);
766 paint_image=CloneImage(image,0,0,MagickTrue,exception);
767 if ((linear_image == (
Image *) NULL) || (paint_image == (
Image *) NULL))
769 if (linear_image != (
Image *) NULL)
770 linear_image=DestroyImage(linear_image);
771 if (paint_image != (
Image *) NULL)
772 linear_image=DestroyImage(paint_image);
773 return((
Image *) NULL);
775 if (SetImageStorageClass(paint_image,DirectClass) == MagickFalse)
777 InheritException(exception,&paint_image->exception);
778 linear_image=DestroyImage(linear_image);
779 paint_image=DestroyImage(paint_image);
780 return((
Image *) NULL);
782 histograms=AcquireHistogramTLS(NumberPaintBins);
783 if (histograms == (
size_t **) NULL)
785 linear_image=DestroyImage(linear_image);
786 paint_image=DestroyImage(paint_image);
787 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
794 image_view=AcquireVirtualCacheView(linear_image,exception);
795 paint_view=AcquireAuthenticCacheView(paint_image,exception);
796 #if defined(MAGICKCORE_OPENMP_SUPPORT)
797 #pragma omp parallel for schedule(static) shared(progress,status) \
798 magick_number_threads(linear_image,paint_image,linear_image->rows,1)
800 for (y=0; y < (ssize_t) linear_image->rows; y++)
803 *magick_restrict indexes;
809 *magick_restrict paint_indexes;
820 if (status == MagickFalse)
822 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
823 (width/2L),linear_image->columns+width,width,exception);
824 q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
831 indexes=GetCacheViewVirtualIndexQueue(image_view);
832 paint_indexes=GetCacheViewAuthenticIndexQueue(paint_view);
833 histogram=histograms[GetOpenMPThreadId()];
834 for (x=0; x < (ssize_t) linear_image->columns; x++)
854 (void) memset(histogram,0,NumberPaintBins*
sizeof(*histogram));
855 for (v=0; v < (ssize_t) width; v++)
857 for (u=0; u < (ssize_t) width; u++)
859 k=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(
860 linear_image,p+u+i)));
862 if (histogram[k] > count)
868 i+=(ssize_t) (linear_image->columns+width);
871 if (linear_image->colorspace == CMYKColorspace)
872 SetPixelIndex(paint_indexes+x,GetPixelIndex(indexes+x+j));
876 if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
878 if (image->progress_monitor != (MagickProgressMonitor) NULL)
883 #if defined(MAGICKCORE_OPENMP_SUPPORT)
887 proceed=SetImageProgress(image,OilPaintImageTag,progress,image->rows);
888 if (proceed == MagickFalse)
892 paint_view=DestroyCacheView(paint_view);
893 image_view=DestroyCacheView(image_view);
894 histograms=DestroyHistogramTLS(histograms);
895 linear_image=DestroyImage(linear_image);
896 if (status == MagickFalse)
897 paint_image=DestroyImage(paint_image);
944 MagickExport MagickBooleanType OpaquePaintImage(
Image *image,
946 const MagickBooleanType invert)
948 return(OpaquePaintImageChannel(image,CompositeChannels,target,fill,invert));
951 MagickExport MagickBooleanType OpaquePaintImageChannel(
Image *image,
955 #define OpaquePaintImageTag "Opaque/Image"
977 assert(image != (
Image *) NULL);
978 assert(image->signature == MagickCoreSignature);
981 if (IsEventLogging() != MagickFalse)
982 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
983 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
985 exception=(&image->exception);
986 ConformMagickPixelPacket(image,fill,&conform_fill,exception);
987 ConformMagickPixelPacket(image,target,&conform_target,exception);
993 GetMagickPixelPacket(image,&zero);
994 image_view=AcquireAuthenticCacheView(image,exception);
995 #if defined(MAGICKCORE_OPENMP_SUPPORT)
996 #pragma omp parallel for schedule(static) shared(progress,status) \
997 magick_number_threads(image,image,image->rows,1)
999 for (y=0; y < (ssize_t) image->rows; y++)
1005 *magick_restrict indexes;
1013 if (status == MagickFalse)
1015 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1021 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1023 for (x=0; x < (ssize_t) image->columns; x++)
1025 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1026 if (IsMagickColorSimilar(&pixel,&conform_target) != invert)
1028 if ((channel & RedChannel) != 0)
1029 SetPixelRed(q,ClampToQuantum(conform_fill.red));
1030 if ((channel & GreenChannel) != 0)
1031 SetPixelGreen(q,ClampToQuantum(conform_fill.green));
1032 if ((channel & BlueChannel) != 0)
1033 SetPixelBlue(q,ClampToQuantum(conform_fill.blue));
1034 if ((channel & OpacityChannel) != 0)
1035 SetPixelOpacity(q,ClampToQuantum(conform_fill.opacity));
1036 if (((channel & IndexChannel) != 0) &&
1037 (image->colorspace == CMYKColorspace))
1038 SetPixelIndex(indexes+x,ClampToQuantum(conform_fill.index));
1042 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1044 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1049 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1053 proceed=SetImageProgress(image,OpaquePaintImageTag,progress,
1055 if (proceed == MagickFalse)
1059 image_view=DestroyCacheView(image_view);
1100 MagickExport MagickBooleanType TransparentPaintImage(
Image *image,
1102 const MagickBooleanType invert)
1104 #define TransparentPaintImageTag "Transparent/Image"
1124 assert(image != (
Image *) NULL);
1125 assert(image->signature == MagickCoreSignature);
1127 if (IsEventLogging() != MagickFalse)
1128 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1129 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1130 return(MagickFalse);
1131 if (image->matte == MagickFalse)
1132 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
1138 exception=(&image->exception);
1139 GetMagickPixelPacket(image,&zero);
1140 image_view=AcquireAuthenticCacheView(image,exception);
1141 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1142 #pragma omp parallel for schedule(static) shared(progress,status) \
1143 magick_number_threads(image,image,image->rows,1)
1145 for (y=0; y < (ssize_t) image->rows; y++)
1151 *magick_restrict indexes;
1159 if (status == MagickFalse)
1161 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1167 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1169 for (x=0; x < (ssize_t) image->columns; x++)
1171 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1172 if (IsMagickColorSimilar(&pixel,target) != invert)
1176 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1178 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1183 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1187 proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1189 if (proceed == MagickFalse)
1193 image_view=DestroyCacheView(image_view);
1237 MagickExport MagickBooleanType TransparentPaintImageChroma(
Image *image,
1239 const Quantum opacity,
const MagickBooleanType invert)
1241 #define TransparentPaintImageTag "Transparent/Image"
1258 assert(image != (
Image *) NULL);
1259 assert(image->signature == MagickCoreSignature);
1262 if (IsEventLogging() != MagickFalse)
1263 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1264 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1265 return(MagickFalse);
1266 if (image->matte == MagickFalse)
1267 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
1273 exception=(&image->exception);
1274 image_view=AcquireAuthenticCacheView(image,exception);
1275 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1276 #pragma omp parallel for schedule(static) shared(progress,status) \
1277 magick_number_threads(image,image,image->rows,1)
1279 for (y=0; y < (ssize_t) image->rows; y++)
1288 *magick_restrict indexes;
1296 if (status == MagickFalse)
1298 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1304 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1305 GetMagickPixelPacket(image,&pixel);
1306 for (x=0; x < (ssize_t) image->columns; x++)
1308 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1309 match=((pixel.red >= low->red) && (pixel.red <= high->red) &&
1310 (pixel.green >= low->green) && (pixel.green <= high->green) &&
1311 (pixel.blue >= low->blue) && (pixel.blue <= high->blue)) ? MagickTrue : MagickFalse;
1312 if (match != invert)
1316 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1318 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1323 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1327 proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1329 if (proceed == MagickFalse)
1333 image_view=DestroyCacheView(image_view);