20
% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
20
% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21
21
% dedicated to making software imaging solutions freely available. %
23
23
% You may not use this file except in compliance with the License. You may %
89
89
% MagickBooleanType FloodfillPaintImage(Image *image,
90
90
% const ChannelType channel,const DrawInfo *draw_info,
91
% const MagickPixelPacket target,const long x_offset,const long y_offset,
91
% const MagickPixelPacket target,const ssize_t x_offset,const ssize_t y_offset,
92
92
% const MagickBooleanType invert)
94
94
% A description of each parameter follows:
109
109
MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
110
110
const ChannelType channel,const DrawInfo *draw_info,
111
const MagickPixelPacket *target,const long x_offset,const long y_offset,
111
const MagickPixelPacket *target,const ssize_t x_offset,const ssize_t y_offset,
112
112
const MagickBooleanType invert)
114
114
#define MaxStacksize (1UL << 15)
118
118
ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \
121
if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (long) image->rows)) \
121
if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \
123
123
s->x1=(double) (left); \
124
124
s->y1=(double) (up); \
168
168
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
169
169
assert(draw_info != (DrawInfo *) NULL);
170
170
assert(draw_info->signature == MagickSignature);
171
if ((x_offset < 0) || (x_offset >= (long) image->columns))
171
if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
172
172
return(MagickFalse);
173
if ((y_offset < 0) || (y_offset >= (long) image->rows))
173
if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
174
174
return(MagickFalse);
175
175
if (SetImageStorageClass(image,DirectClass) == MagickFalse)
176
176
return(MagickFalse);
206
206
while (s > segment_stack)
208
208
register const IndexPacket
211
211
register const PixelPacket
217
217
register PixelPacket
221
221
Pop segment off stack.
227
y=(long) s->y1+offset;
226
offset=(ssize_t) s->y2;
227
y=(ssize_t) s->y1+offset;
229
229
Recolor neighboring pixels.
231
p=GetVirtualPixels(image,0,y,(unsigned long) (x1+1),1,exception);
232
q=GetAuthenticPixels(floodplane_image,0,y,(unsigned long) (x1+1),1,
231
p=GetVirtualPixels(image,0,y,(size_t) (x1+1),1,exception);
232
q=GetAuthenticPixels(floodplane_image,0,y,(size_t) (x1+1),1,
234
234
if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
262
262
if (skip == MagickFalse)
264
if (x < (long) image->columns)
264
if (x < (ssize_t) image->columns)
266
266
p=GetVirtualPixels(image,x,y,image->columns-x,1,exception);
267
267
q=GetAuthenticPixels(floodplane_image,x,y,image->columns-x,1,
270
270
(q == (PixelPacket *) NULL))
272
272
indexes=GetVirtualIndexQueue(image);
273
for ( ; x < (long) image->columns; x++)
273
for ( ; x < (ssize_t) image->columns; x++)
275
275
if (q->opacity == (Quantum) TransparentOpacity)
295
p=GetVirtualPixels(image,x,y,(unsigned long) (x2-x+1),1,exception);
296
q=GetAuthenticPixels(floodplane_image,x,y,(unsigned long) (x2-x+1),1,
295
p=GetVirtualPixels(image,x,y,(size_t) (x2-x+1),1,exception);
296
q=GetAuthenticPixels(floodplane_image,x,y,(size_t) (x2-x+1),1,
298
298
if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
334
334
if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
336
336
indexes=GetAuthenticIndexQueue(image);
337
for (x=0; x < (long) image->columns; x++)
337
for (x=0; x < (ssize_t) image->columns; x++)
339
339
if (p->opacity != OpaqueOpacity)
343
343
if (image->colorspace == CMYKColorspace)
344
344
ConvertRGBToCMYK(&fill);
345
345
if ((channel & RedChannel) != 0)
346
q->red=RoundToQuantum(fill.red);
346
q->red=ClampToQuantum(fill.red);
347
347
if ((channel & GreenChannel) != 0)
348
q->green=RoundToQuantum(fill.green);
348
q->green=ClampToQuantum(fill.green);
349
349
if ((channel & BlueChannel) != 0)
350
q->blue=RoundToQuantum(fill.blue);
350
q->blue=ClampToQuantum(fill.blue);
351
351
if ((channel & OpacityChannel) != 0)
352
q->opacity=RoundToQuantum(fill.opacity);
352
q->opacity=ClampToQuantum(fill.opacity);
353
353
if (((channel & IndexChannel) != 0) &&
354
354
(image->colorspace == CMYKColorspace))
355
indexes[x]=RoundToQuantum(fill.index);
355
indexes[x]=ClampToQuantum(fill.index);
363
363
segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack);
364
364
floodplane_image=DestroyImage(floodplane_image);
365
return(y == (long) image->rows ? MagickTrue : MagickFalse);
365
return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse);
452
452
image->filename);
453
453
(void) ResetMagickMemory(gradient->stops,0,gradient->number_stops*
454
454
sizeof(*gradient->stops));
455
for (i=0; i < (long) gradient->number_stops; i++)
455
for (i=0; i < (ssize_t) gradient->number_stops; i++)
456
456
GetMagickPixelPacket(image,&gradient->stops[i].color);
457
457
SetMagickPixelPacket(image,start_color,(IndexPacket *) NULL,
458
458
&gradient->stops[0].color);
507
static unsigned long **DestroyHistogramThreadSet(unsigned long **histogram)
507
static size_t **DestroyHistogramThreadSet(size_t **histogram)
512
assert(histogram != (unsigned long **) NULL);
513
for (i=0; i < (long) GetOpenMPMaximumThreads(); i++)
514
if (histogram[i] != (unsigned long *) NULL)
515
histogram[i]=(unsigned long *) RelinquishMagickMemory(histogram[i]);
516
histogram=(unsigned long **) RelinquishAlignedMemory(histogram);
512
assert(histogram != (size_t **) NULL);
513
for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
514
if (histogram[i] != (size_t *) NULL)
515
histogram[i]=(size_t *) RelinquishMagickMemory(histogram[i]);
516
histogram=(size_t **) RelinquishAlignedMemory(histogram);
517
517
return(histogram);
520
static unsigned long **AcquireHistogramThreadSet(const size_t count)
520
static size_t **AcquireHistogramThreadSet(const size_t count)
529
529
number_threads=GetOpenMPMaximumThreads();
530
histogram=(unsigned long **) AcquireAlignedMemory(number_threads,
530
histogram=(size_t **) AcquireAlignedMemory(number_threads,
531
531
sizeof(*histogram));
532
if (histogram == (unsigned long **) NULL)
533
return((unsigned long **) NULL);
532
if (histogram == (size_t **) NULL)
533
return((size_t **) NULL);
534
534
(void) ResetMagickMemory(histogram,0,number_threads*sizeof(*histogram));
535
for (i=0; i < (long) number_threads; i++)
535
for (i=0; i < (ssize_t) number_threads; i++)
537
histogram[i]=(unsigned long *) AcquireQuantumMemory(count,
537
histogram[i]=(size_t *) AcquireQuantumMemory(count,
538
538
sizeof(**histogram));
539
if (histogram[i] == (unsigned long *) NULL)
539
if (histogram[i] == (size_t *) NULL)
540
540
return(DestroyHistogramThreadSet(histogram));
542
542
return(histogram);
588
590
return((Image *) NULL);
590
592
histograms=AcquireHistogramThreadSet(NumberPaintBins);
591
if (histograms == (unsigned long **) NULL)
593
if (histograms == (size_t **) NULL)
593
595
paint_image=DestroyImage(paint_image);
594
596
ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
603
605
#if defined(MAGICKCORE_OPENMP_SUPPORT)
604
606
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
606
for (y=0; y < (long) image->rows; y++)
608
for (y=0; y < (ssize_t) image->rows; y++)
608
610
register const IndexPacket
611
613
register const PixelPacket
614
616
register IndexPacket
615
*__restrict paint_indexes;
617
*restrict paint_indexes;
620
622
register PixelPacket
623
register unsigned long
626
628
if (status == MagickFalse)
628
p=GetCacheViewVirtualPixels(image_view,-((long) width/2L),y-(long) (width/
630
p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/
629
631
2L),image->columns+width,width,exception);
630
632
q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
637
639
indexes=GetCacheViewVirtualIndexQueue(image_view);
638
640
paint_indexes=GetCacheViewAuthenticIndexQueue(paint_view);
639
641
histogram=histograms[GetOpenMPThreadId()];
640
for (x=0; x < (long) image->columns; x++)
642
for (x=0; x < (ssize_t) image->columns; x++)
660
662
(void) ResetMagickMemory(histogram,0,NumberPaintBins*sizeof(*histogram));
661
for (v=0; v < (long) width; v++)
663
for (v=0; v < (ssize_t) width; v++)
663
for (u=0; u < (long) width; u++)
665
for (u=0; u < (ssize_t) width; u++)
665
k=(long) ScaleQuantumToChar(PixelIntensityToQuantum(p+u+i));
667
k=(ssize_t) ScaleQuantumToChar(PixelIntensityToQuantum(p+u+i));
667
669
if (histogram[k] > count)
792
796
#if defined(MAGICKCORE_OPENMP_SUPPORT)
793
797
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
795
for (y=0; y < (long) image->rows; y++)
799
for (y=0; y < (ssize_t) image->rows; y++)
797
801
MagickPixelPacket
800
804
register IndexPacket
806
810
register PixelPacket
809
813
if (status == MagickFalse)
817
821
indexes=GetCacheViewAuthenticIndexQueue(image_view);
819
for (x=0; x < (long) image->columns; x++)
823
for (x=0; x < (ssize_t) image->columns; x++)
821
825
SetMagickPixelPacket(image,q,indexes+x,&pixel);
822
826
if (IsMagickColorSimilar(&pixel,target) != invert)
824
828
if ((channel & RedChannel) != 0)
825
q->red=RoundToQuantum(fill->red);
829
q->red=ClampToQuantum(fill->red);
826
830
if ((channel & GreenChannel) != 0)
827
q->green=RoundToQuantum(fill->green);
831
q->green=ClampToQuantum(fill->green);
828
832
if ((channel & BlueChannel) != 0)
829
q->blue=RoundToQuantum(fill->blue);
833
q->blue=ClampToQuantum(fill->blue);
830
834
if ((channel & OpacityChannel) != 0)
831
q->opacity=RoundToQuantum(fill->opacity);
835
q->opacity=ClampToQuantum(fill->opacity);
832
836
if (((channel & IndexChannel) != 0) &&
833
837
(image->colorspace == CMYKColorspace))
834
indexes[x]=RoundToQuantum(fill->index);
838
indexes[x]=ClampToQuantum(fill->index);
934
940
#if defined(MAGICKCORE_OPENMP_SUPPORT)
935
941
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
937
for (y=0; y < (long) image->rows; y++)
943
for (y=0; y < (ssize_t) image->rows; y++)
939
945
MagickPixelPacket
942
948
register IndexPacket
948
954
register PixelPacket
951
957
if (status == MagickFalse)
959
965
indexes=GetCacheViewAuthenticIndexQueue(image_view);
961
for (x=0; x < (long) image->columns; x++)
967
for (x=0; x < (ssize_t) image->columns; x++)
963
969
SetMagickPixelPacket(image,q,indexes+x,&pixel);
964
970
if (IsMagickColorSimilar(&pixel,target) != invert)
1064
1072
#if defined(MAGICKCORE_OPENMP_SUPPORT)
1065
1073
#pragma omp parallel for schedule(dynamic,4) shared(progress,status)
1067
for (y=0; y < (long) image->rows; y++)
1075
for (y=0; y < (ssize_t) image->rows; y++)
1069
1077
MagickBooleanType
1092
1100
indexes=GetCacheViewAuthenticIndexQueue(image_view);
1093
1101
GetMagickPixelPacket(image,&pixel);
1094
for (x=0; x < (long) image->columns; x++)
1102
for (x=0; x < (ssize_t) image->columns; x++)
1096
1104
SetMagickPixelPacket(image,q,indexes+x,&pixel);
1097
1105
match=((pixel.red >= low->red) && (pixel.red <= high->red) &&