MagickCore  7.0.11
paint.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % PPPP AAA IIIII N N TTTTT %
7 % P P A A I NN N T %
8 % PPPP AAAAA I N N N T %
9 % P A A I N NN T %
10 % P A A IIIII N N T %
11 % %
12 % %
13 % Methods to Paint on an Image %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1998 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/channel.h"
45 #include "MagickCore/color.h"
48 #include "MagickCore/composite.h"
50 #include "MagickCore/draw.h"
52 #include "MagickCore/exception.h"
54 #include "MagickCore/gem.h"
55 #include "MagickCore/gem-private.h"
56 #include "MagickCore/monitor.h"
58 #include "MagickCore/option.h"
59 #include "MagickCore/paint.h"
61 #include "MagickCore/resource_.h"
62 #include "MagickCore/statistic.h"
63 #include "MagickCore/string_.h"
66 
67 /*
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 % %
70 % %
71 % %
72 % F l o o d f i l l P a i n t I m a g e %
73 % %
74 % %
75 % %
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %
78 % FloodfillPaintImage() changes the color value of any pixel that matches
79 % target and is an immediate neighbor. If the method FillToBorderMethod is
80 % specified, the color value is changed for any neighbor pixel that does not
81 % match the bordercolor member of image.
82 %
83 % By default target must match a particular pixel color exactly. However,
84 % in many cases two colors may differ by a small amount. The fuzz member of
85 % image defines how much tolerance is acceptable to consider two colors as
86 % the same. For example, set fuzz to 10 and the color red at intensities of
87 % 100 and 102 respectively are now interpreted as the same color for the
88 % purposes of the floodfill.
89 %
90 % The format of the FloodfillPaintImage method is:
91 %
92 % MagickBooleanType FloodfillPaintImage(Image *image,
93 % const DrawInfo *draw_info,const PixelInfo target,
94 % const ssize_t x_offset,const ssize_t y_offset,
95 % const MagickBooleanType invert,ExceptionInfo *exception)
96 %
97 % A description of each parameter follows:
98 %
99 % o image: the image.
100 %
101 % o draw_info: the draw info.
102 %
103 % o target: the RGB value of the target color.
104 %
105 % o x_offset,y_offset: the starting location of the operation.
106 %
107 % o invert: paint any pixel that does not match the target color.
108 %
109 % o exception: return any errors or warnings in this structure.
110 %
111 */
113  const DrawInfo *draw_info,const PixelInfo *target,const ssize_t x_offset,
114  const ssize_t y_offset,const MagickBooleanType invert,
115  ExceptionInfo *exception)
116 {
117 #define MaxStacksize 524288UL
118 #define PushSegmentStack(up,left,right,delta) \
119 { \
120  if (s >= (segment_stack+MaxStacksize)) \
121  ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \
122  else \
123  { \
124  if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \
125  { \
126  s->x1=(double) (left); \
127  s->y1=(double) (up); \
128  s->x2=(double) (right); \
129  s->y2=(double) (delta); \
130  s++; \
131  } \
132  } \
133 }
134 
135  CacheView
136  *floodplane_view,
137  *image_view;
138 
139  Image
140  *floodplane_image;
141 
143  skip,
144  status;
145 
146  MemoryInfo
147  *segment_info;
148 
149  PixelInfo
150  fill_color,
151  pixel;
152 
154  *s;
155 
157  *segment_stack;
158 
159  ssize_t
160  offset,
161  start,
162  x1,
163  x2,
164  y;
165 
166  /*
167  Check boundary conditions.
168  */
169  assert(image != (Image *) NULL);
170  assert(image->signature == MagickCoreSignature);
171  if (image->debug != MagickFalse)
172  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
173  assert(draw_info != (DrawInfo *) NULL);
174  assert(draw_info->signature == MagickCoreSignature);
175  if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
176  return(MagickFalse);
177  if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
178  return(MagickFalse);
179  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
180  return(MagickFalse);
181  if (IsGrayColorspace(image->colorspace) != MagickFalse)
182  (void) SetImageColorspace(image,sRGBColorspace,exception);
183  if ((image->alpha_trait == UndefinedPixelTrait) &&
184  (draw_info->fill.alpha_trait != UndefinedPixelTrait))
185  (void) SetImageAlpha(image,OpaqueAlpha,exception);
186  /*
187  Set floodfill state.
188  */
189  floodplane_image=CloneImage(image,0,0,MagickTrue,exception);
190  if (floodplane_image == (Image *) NULL)
191  return(MagickFalse);
192  floodplane_image->alpha_trait=UndefinedPixelTrait;
193  floodplane_image->colorspace=GRAYColorspace;
194  (void) QueryColorCompliance("#000",AllCompliance,
195  &floodplane_image->background_color,exception);
196  (void) SetImageBackgroundColor(floodplane_image,exception);
197  segment_info=AcquireVirtualMemory(MaxStacksize,sizeof(*segment_stack));
198  if (segment_info == (MemoryInfo *) NULL)
199  {
200  floodplane_image=DestroyImage(floodplane_image);
201  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
202  image->filename);
203  }
204  segment_stack=(SegmentInfo *) GetVirtualMemoryBlob(segment_info);
205  /*
206  Push initial segment on stack.
207  */
208  status=MagickTrue;
209  start=0;
210  s=segment_stack;
211  PushSegmentStack(y_offset,x_offset,x_offset,1);
212  PushSegmentStack(y_offset+1,x_offset,x_offset,-1);
213  GetPixelInfo(image,&pixel);
214  image_view=AcquireVirtualCacheView(image,exception);
215  floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception);
216  while (s > segment_stack)
217  {
218  const Quantum
219  *magick_restrict p;
220 
221  Quantum
222  *magick_restrict q;
223 
224  ssize_t
225  x;
226 
227  /*
228  Pop segment off stack.
229  */
230  s--;
231  x1=(ssize_t) s->x1;
232  x2=(ssize_t) s->x2;
233  offset=(ssize_t) s->y2;
234  y=(ssize_t) s->y1+offset;
235  /*
236  Recolor neighboring pixels.
237  */
238  p=GetCacheViewVirtualPixels(image_view,0,y,(size_t) (x1+1),1,exception);
239  q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(size_t) (x1+1),1,
240  exception);
241  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
242  break;
243  p+=x1*GetPixelChannels(image);
244  q+=x1*GetPixelChannels(floodplane_image);
245  for (x=x1; x >= 0; x--)
246  {
247  if (GetPixelGray(floodplane_image,q) != 0)
248  break;
249  GetPixelInfoPixel(image,p,&pixel);
250  if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert)
251  break;
252  SetPixelGray(floodplane_image,QuantumRange,q);
253  p-=GetPixelChannels(image);
254  q-=GetPixelChannels(floodplane_image);
255  }
256  if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse)
257  break;
258  skip=x >= x1 ? MagickTrue : MagickFalse;
259  if (skip == MagickFalse)
260  {
261  start=x+1;
262  if (start < x1)
263  PushSegmentStack(y,start,x1-1,-offset);
264  x=x1+1;
265  }
266  do
267  {
268  if (skip == MagickFalse)
269  {
270  if (x < (ssize_t) image->columns)
271  {
272  p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1,
273  exception);
274  q=GetCacheViewAuthenticPixels(floodplane_view,x,y,image->columns-
275  x,1,exception);
276  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
277  break;
278  for ( ; x < (ssize_t) image->columns; x++)
279  {
280  if (GetPixelGray(floodplane_image,q) != 0)
281  break;
282  GetPixelInfoPixel(image,p,&pixel);
283  if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert)
284  break;
285  SetPixelGray(floodplane_image,QuantumRange,q);
286  p+=GetPixelChannels(image);
287  q+=GetPixelChannels(floodplane_image);
288  }
289  status=SyncCacheViewAuthenticPixels(floodplane_view,exception);
290  if (status == MagickFalse)
291  break;
292  }
293  PushSegmentStack(y,start,x-1,offset);
294  if (x > (x2+1))
295  PushSegmentStack(y,x2+1,x-1,-offset);
296  }
297  skip=MagickFalse;
298  x++;
299  if (x <= x2)
300  {
301  p=GetCacheViewVirtualPixels(image_view,x,y,(size_t) (x2-x+1),1,
302  exception);
303  q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(size_t) (x2-x+1),1,
304  exception);
305  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
306  break;
307  for ( ; x <= x2; x++)
308  {
309  if (GetPixelGray(floodplane_image,q) != 0)
310  break;
311  GetPixelInfoPixel(image,p,&pixel);
312  if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert)
313  break;
314  p+=GetPixelChannels(image);
315  q+=GetPixelChannels(floodplane_image);
316  }
317  }
318  start=x;
319  } while (x <= x2);
320  }
321  status=MagickTrue;
322  for (y=0; y < (ssize_t) image->rows; y++)
323  {
324  const Quantum
325  *magick_restrict p;
326 
327  Quantum
328  *magick_restrict q;
329 
330  ssize_t
331  x;
332 
333  /*
334  Tile fill color onto floodplane.
335  */
336  if (status == MagickFalse)
337  continue;
338  p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,exception);
339  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
340  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
341  {
342  status=MagickFalse;
343  continue;
344  }
345  for (x=0; x < (ssize_t) image->columns; x++)
346  {
347  if (GetPixelGray(floodplane_image,p) != 0)
348  {
349  GetFillColor(draw_info,x,y,&fill_color,exception);
350  SetPixelViaPixelInfo(image,&fill_color,q);
351  }
352  p+=GetPixelChannels(floodplane_image);
353  q+=GetPixelChannels(image);
354  }
355  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
356  status=MagickFalse;
357  }
358  floodplane_view=DestroyCacheView(floodplane_view);
359  image_view=DestroyCacheView(image_view);
360  segment_info=RelinquishVirtualMemory(segment_info);
361  floodplane_image=DestroyImage(floodplane_image);
362  return(status);
363 }
364 
365 /*
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % %
368 % %
369 % %
370 + G r a d i e n t I m a g e %
371 % %
372 % %
373 % %
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %
376 % GradientImage() applies a continuously smooth color transitions along a
377 % vector from one color to another.
378 %
379 % Note, the interface of this method will change in the future to support
380 % more than one transistion.
381 %
382 % The format of the GradientImage method is:
383 %
384 % MagickBooleanType GradientImage(Image *image,const GradientType type,
385 % const SpreadMethod method,const PixelInfo *start_color,
386 % const PixelInfo *stop_color,ExceptionInfo *exception)
387 %
388 % A description of each parameter follows:
389 %
390 % o image: the image.
391 %
392 % o type: the gradient type: linear or radial.
393 %
394 % o spread: the gradient spread meathod: pad, reflect, or repeat.
395 %
396 % o start_color: the start color.
397 %
398 % o stop_color: the stop color.
399 %
400 % o exception: return any errors or warnings in this structure.
401 %
402 */
404  const GradientType type,const SpreadMethod method,const StopInfo *stops,
405  const size_t number_stops,ExceptionInfo *exception)
406 {
407  const char
408  *artifact;
409 
410  DrawInfo
411  *draw_info;
412 
414  *gradient;
415 
417  status;
418 
419  /*
420  Set gradient start-stop end points.
421  */
422  assert(image != (const Image *) NULL);
423  assert(image->signature == MagickCoreSignature);
424  if (image->debug != MagickFalse)
425  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
426  assert(stops != (const StopInfo *) NULL);
427  assert(number_stops > 0);
428  draw_info=AcquireDrawInfo();
429  gradient=(&draw_info->gradient);
430  gradient->type=type;
431  gradient->bounding_box.width=image->columns;
432  gradient->bounding_box.height=image->rows;
433  artifact=GetImageArtifact(image,"gradient:bounding-box");
434  if (artifact != (const char *) NULL)
435  (void) ParseAbsoluteGeometry(artifact,&gradient->bounding_box);
436  gradient->gradient_vector.x2=(double) image->columns-1;
437  gradient->gradient_vector.y2=(double) image->rows-1;
438  artifact=GetImageArtifact(image,"gradient:direction");
439  if (artifact != (const char *) NULL)
440  {
442  direction;
443 
445  MagickFalse,artifact);
446  switch (direction)
447  {
448  case NorthWestGravity:
449  {
450  gradient->gradient_vector.x1=(double) image->columns-1;
451  gradient->gradient_vector.y1=(double) image->rows-1;
452  gradient->gradient_vector.x2=0.0;
453  gradient->gradient_vector.y2=0.0;
454  break;
455  }
456  case NorthGravity:
457  {
458  gradient->gradient_vector.x1=0.0;
459  gradient->gradient_vector.y1=(double) image->rows-1;
460  gradient->gradient_vector.x2=0.0;
461  gradient->gradient_vector.y2=0.0;
462  break;
463  }
464  case NorthEastGravity:
465  {
466  gradient->gradient_vector.x1=0.0;
467  gradient->gradient_vector.y1=(double) image->rows-1;
468  gradient->gradient_vector.x2=(double) image->columns-1;
469  gradient->gradient_vector.y2=0.0;
470  break;
471  }
472  case WestGravity:
473  {
474  gradient->gradient_vector.x1=(double) image->columns-1;
475  gradient->gradient_vector.y1=0.0;
476  gradient->gradient_vector.x2=0.0;
477  gradient->gradient_vector.y2=0.0;
478  break;
479  }
480  case EastGravity:
481  {
482  gradient->gradient_vector.x1=0.0;
483  gradient->gradient_vector.y1=0.0;
484  gradient->gradient_vector.x2=(double) image->columns-1;
485  gradient->gradient_vector.y2=0.0;
486  break;
487  }
488  case SouthWestGravity:
489  {
490  gradient->gradient_vector.x1=(double) image->columns-1;
491  gradient->gradient_vector.y1=0.0;
492  gradient->gradient_vector.x2=0.0;
493  gradient->gradient_vector.y2=(double) image->rows-1;
494  break;
495  }
496  case SouthGravity:
497  {
498  gradient->gradient_vector.x1=0.0;
499  gradient->gradient_vector.y1=0.0;
500  gradient->gradient_vector.x2=0.0;
501  gradient->gradient_vector.y2=(double) image->columns-1;
502  break;
503  }
504  case SouthEastGravity:
505  {
506  gradient->gradient_vector.x1=0.0;
507  gradient->gradient_vector.y1=0.0;
508  gradient->gradient_vector.x2=(double) image->columns-1;
509  gradient->gradient_vector.y2=(double) image->rows-1;
510  break;
511  }
512  default:
513  break;
514  }
515  }
516  artifact=GetImageArtifact(image,"gradient:angle");
517  if (artifact != (const char *) NULL)
518  gradient->angle=StringToDouble(artifact,(char **) NULL);
519  artifact=GetImageArtifact(image,"gradient:vector");
520  if (artifact != (const char *) NULL)
521  (void) sscanf(artifact,"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf",
522  &gradient->gradient_vector.x1,&gradient->gradient_vector.y1,
523  &gradient->gradient_vector.x2,&gradient->gradient_vector.y2);
524  if ((GetImageArtifact(image,"gradient:angle") == (const char *) NULL) &&
525  (GetImageArtifact(image,"gradient:direction") == (const char *) NULL) &&
526  (GetImageArtifact(image,"gradient:extent") == (const char *) NULL) &&
527  (GetImageArtifact(image,"gradient:vector") == (const char *) NULL))
528  if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0))
529  gradient->gradient_vector.x2=0.0;
530  gradient->center.x=(double) gradient->gradient_vector.x2/2.0;
531  gradient->center.y=(double) gradient->gradient_vector.y2/2.0;
532  artifact=GetImageArtifact(image,"gradient:center");
533  if (artifact != (const char *) NULL)
534  (void) sscanf(artifact,"%lf%*[ ,]%lf",&gradient->center.x,
535  &gradient->center.y);
536  artifact=GetImageArtifact(image,"gradient:angle");
537  if ((type == LinearGradient) && (artifact != (const char *) NULL))
538  {
539  double
540  sine,
541  cosine,
542  distance;
543 
544  /*
545  Reference https://drafts.csswg.org/css-images-3/#linear-gradients.
546  */
547  sine=sin((double) DegreesToRadians(gradient->angle-90.0));
548  cosine=cos((double) DegreesToRadians(gradient->angle-90.0));
549  distance=fabs((double) (image->columns-1.0)*cosine)+
550  fabs((double) (image->rows-1.0)*sine);
551  gradient->gradient_vector.x1=0.5*((image->columns-1.0)-distance*cosine);
552  gradient->gradient_vector.y1=0.5*((image->rows-1.0)-distance*sine);
553  gradient->gradient_vector.x2=0.5*((image->columns-1.0)+distance*cosine);
554  gradient->gradient_vector.y2=0.5*((image->rows-1.0)+distance*sine);
555  }
556  gradient->radii.x=(double) MagickMax((image->columns-1.0),(image->rows-1.0))/
557  2.0;
558  gradient->radii.y=gradient->radii.x;
559  artifact=GetImageArtifact(image,"gradient:extent");
560  if (artifact != (const char *) NULL)
561  {
562  if (LocaleCompare(artifact,"Circle") == 0)
563  {
564  gradient->radii.x=(double) MagickMax((image->columns-1.0),
565  (image->rows-1.0))/2.0;
566  gradient->radii.y=gradient->radii.x;
567  }
568  if (LocaleCompare(artifact,"Diagonal") == 0)
569  {
570  gradient->radii.x=(double) (sqrt((double) (image->columns-1.0)*
571  (image->columns-1.0)+(image->rows-1.0)*(image->rows-1.0)))/2.0;
572  gradient->radii.y=gradient->radii.x;
573  }
574  if (LocaleCompare(artifact,"Ellipse") == 0)
575  {
576  gradient->radii.x=(double) (image->columns-1.0)/2.0;
577  gradient->radii.y=(double) (image->rows-1.0)/2.0;
578  }
579  if (LocaleCompare(artifact,"Maximum") == 0)
580  {
581  gradient->radii.x=(double) MagickMax((image->columns-1.0),
582  (image->rows-1.0))/2.0;
583  gradient->radii.y=gradient->radii.x;
584  }
585  if (LocaleCompare(artifact,"Minimum") == 0)
586  {
587  gradient->radii.x=(double) (MagickMin((image->columns-1.0),
588  (image->rows-1.0)))/2.0;
589  gradient->radii.y=gradient->radii.x;
590  }
591  }
592  artifact=GetImageArtifact(image,"gradient:radii");
593  if (artifact != (const char *) NULL)
594  (void) sscanf(artifact,"%lf%*[ ,]%lf",&gradient->radii.x,
595  &gradient->radii.y);
596  gradient->radius=MagickMax(gradient->radii.x,gradient->radii.y);
597  gradient->spread=method;
598  /*
599  Define the gradient to fill between the stops.
600  */
601  gradient->number_stops=number_stops;
602  gradient->stops=(StopInfo *) AcquireQuantumMemory(gradient->number_stops,
603  sizeof(*gradient->stops));
604  if (gradient->stops == (StopInfo *) NULL)
605  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
606  image->filename);
607  (void) memcpy(gradient->stops,stops,(size_t) number_stops*sizeof(*stops));
608  /*
609  Draw a gradient on the image.
610  */
611  status=DrawGradientImage(image,draw_info,exception);
612  draw_info=DestroyDrawInfo(draw_info);
613  return(status);
614 }
615 
616 /*
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 % %
619 % %
620 % %
621 % O i l P a i n t I m a g e %
622 % %
623 % %
624 % %
625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626 %
627 % OilPaintImage() applies a special effect filter that simulates an oil
628 % painting. Each pixel is replaced by the most frequent color occurring
629 % in a circular region defined by radius.
630 %
631 % The format of the OilPaintImage method is:
632 %
633 % Image *OilPaintImage(const Image *image,const double radius,
634 % const double sigma,ExceptionInfo *exception)
635 %
636 % A description of each parameter follows:
637 %
638 % o image: the image.
639 %
640 % o radius: the radius of the circular neighborhood.
641 %
642 % o sigma: the standard deviation of the Gaussian, in pixels.
643 %
644 % o exception: return any errors or warnings in this structure.
645 %
646 */
647 
648 static size_t **DestroyHistogramThreadSet(size_t **histogram)
649 {
650  ssize_t
651  i;
652 
653  assert(histogram != (size_t **) NULL);
654  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
655  if (histogram[i] != (size_t *) NULL)
656  histogram[i]=(size_t *) RelinquishMagickMemory(histogram[i]);
657  histogram=(size_t **) RelinquishMagickMemory(histogram);
658  return(histogram);
659 }
660 
661 static size_t **AcquireHistogramThreadSet(const size_t count)
662 {
663  ssize_t
664  i;
665 
666  size_t
667  **histogram,
668  number_threads;
669 
670  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
671  histogram=(size_t **) AcquireQuantumMemory(number_threads,sizeof(*histogram));
672  if (histogram == (size_t **) NULL)
673  return((size_t **) NULL);
674  (void) memset(histogram,0,number_threads*sizeof(*histogram));
675  for (i=0; i < (ssize_t) number_threads; i++)
676  {
677  histogram[i]=(size_t *) AcquireQuantumMemory(count,sizeof(**histogram));
678  if (histogram[i] == (size_t *) NULL)
679  return(DestroyHistogramThreadSet(histogram));
680  }
681  return(histogram);
682 }
683 
684 MagickExport Image *OilPaintImage(const Image *image,const double radius,
685  const double sigma,ExceptionInfo *exception)
686 {
687 #define NumberPaintBins 256
688 #define OilPaintImageTag "OilPaint/Image"
689 
690  CacheView
691  *image_view,
692  *paint_view;
693 
694  Image
695  *linear_image,
696  *paint_image;
697 
699  status;
700 
702  progress;
703 
704  size_t
705  **histograms,
706  width;
707 
708  ssize_t
709  center,
710  y;
711 
712  /*
713  Initialize painted image attributes.
714  */
715  assert(image != (const Image *) NULL);
716  assert(image->signature == MagickCoreSignature);
717  if (image->debug != MagickFalse)
718  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
719  assert(exception != (ExceptionInfo *) NULL);
720  assert(exception->signature == MagickCoreSignature);
721  width=GetOptimalKernelWidth2D(radius,sigma);
722  linear_image=CloneImage(image,0,0,MagickTrue,exception);
723  paint_image=CloneImage(image,0,0,MagickTrue,exception);
724  if ((linear_image == (Image *) NULL) || (paint_image == (Image *) NULL))
725  {
726  if (linear_image != (Image *) NULL)
727  linear_image=DestroyImage(linear_image);
728  if (paint_image != (Image *) NULL)
729  linear_image=DestroyImage(paint_image);
730  return((Image *) NULL);
731  }
732  if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse)
733  {
734  linear_image=DestroyImage(linear_image);
735  paint_image=DestroyImage(paint_image);
736  return((Image *) NULL);
737  }
739  if (histograms == (size_t **) NULL)
740  {
741  linear_image=DestroyImage(linear_image);
742  paint_image=DestroyImage(paint_image);
743  ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
744  }
745  /*
746  Oil paint image.
747  */
748  status=MagickTrue;
749  progress=0;
750  center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)*
751  (width/2L)+GetPixelChannels(linear_image)*(width/2L);
752  image_view=AcquireVirtualCacheView(linear_image,exception);
753  paint_view=AcquireAuthenticCacheView(paint_image,exception);
754 #if defined(MAGICKCORE_OPENMP_SUPPORT)
755  #pragma omp parallel for schedule(static) shared(progress,status) \
756  magick_number_threads(linear_image,paint_image,linear_image->rows,1)
757 #endif
758  for (y=0; y < (ssize_t) linear_image->rows; y++)
759  {
760  const Quantum
761  *magick_restrict p;
762 
763  Quantum
764  *magick_restrict q;
765 
766  size_t
767  *histogram;
768 
769  ssize_t
770  x;
771 
772  if (status == MagickFalse)
773  continue;
774  p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
775  (width/2L),linear_image->columns+width,width,exception);
776  q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1,
777  exception);
778  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
779  {
780  status=MagickFalse;
781  continue;
782  }
783  histogram=histograms[GetOpenMPThreadId()];
784  for (x=0; x < (ssize_t) linear_image->columns; x++)
785  {
786  ssize_t
787  i,
788  u;
789 
790  size_t
791  count;
792 
793  ssize_t
794  j,
795  k,
796  n,
797  v;
798 
799  /*
800  Assign most frequent color.
801  */
802  k=0;
803  j=0;
804  count=0;
805  (void) memset(histogram,0,NumberPaintBins* sizeof(*histogram));
806  for (v=0; v < (ssize_t) width; v++)
807  {
808  for (u=0; u < (ssize_t) width; u++)
809  {
810  n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(
811  linear_image,p+GetPixelChannels(linear_image)*(u+k))));
812  histogram[n]++;
813  if (histogram[n] > count)
814  {
815  j=k+u;
816  count=histogram[n];
817  }
818  }
819  k+=(ssize_t) (linear_image->columns+width);
820  }
821  for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++)
822  {
823  PixelChannel channel = GetPixelChannelChannel(linear_image,i);
824  PixelTrait traits = GetPixelChannelTraits(linear_image,channel);
825  PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel);
826  if ((traits == UndefinedPixelTrait) ||
827  (paint_traits == UndefinedPixelTrait))
828  continue;
829  if ((paint_traits & CopyPixelTrait) != 0)
830  {
831  SetPixelChannel(paint_image,channel,p[center+i],q);
832  continue;
833  }
834  SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+
835  i],q);
836  }
837  p+=GetPixelChannels(linear_image);
838  q+=GetPixelChannels(paint_image);
839  }
840  if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse)
841  status=MagickFalse;
842  if (linear_image->progress_monitor != (MagickProgressMonitor) NULL)
843  {
845  proceed;
846 
847 #if defined(MAGICKCORE_OPENMP_SUPPORT)
848  #pragma omp atomic
849 #endif
850  progress++;
851  proceed=SetImageProgress(linear_image,OilPaintImageTag,progress,
852  linear_image->rows);
853  if (proceed == MagickFalse)
854  status=MagickFalse;
855  }
856  }
857  paint_view=DestroyCacheView(paint_view);
858  image_view=DestroyCacheView(image_view);
859  histograms=DestroyHistogramThreadSet(histograms);
860  linear_image=DestroyImage(linear_image);
861  if (status == MagickFalse)
862  paint_image=DestroyImage(paint_image);
863  return(paint_image);
864 }
865 
866 /*
867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868 % %
869 % %
870 % %
871 % O p a q u e P a i n t I m a g e %
872 % %
873 % %
874 % %
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 %
877 % OpaquePaintImage() changes any pixel that matches color with the color
878 % defined by fill argument.
879 %
880 % By default color must match a particular pixel color exactly. However, in
881 % many cases two colors may differ by a small amount. Fuzz defines how much
882 % tolerance is acceptable to consider two colors as the same. For example,
883 % set fuzz to 10 and the color red at intensities of 100 and 102 respectively
884 % are now interpreted as the same color.
885 %
886 % The format of the OpaquePaintImage method is:
887 %
888 % MagickBooleanType OpaquePaintImage(Image *image,const PixelInfo *target,
889 % const PixelInfo *fill,const MagickBooleanType invert,
890 % ExceptionInfo *exception)
891 %
892 % A description of each parameter follows:
893 %
894 % o image: the image.
895 %
896 % o target: the RGB value of the target color.
897 %
898 % o fill: the replacement color.
899 %
900 % o invert: paint any pixel that does not match the target color.
901 %
902 % o exception: return any errors or warnings in this structure.
903 %
904 */
906  const PixelInfo *target,const PixelInfo *fill,const MagickBooleanType invert,
907  ExceptionInfo *exception)
908 {
909 #define OpaquePaintImageTag "Opaque/Image"
910 
911  CacheView
912  *image_view;
913 
915  status;
916 
918  progress;
919 
920  PixelInfo
921  conform_fill,
922  conform_target,
923  zero;
924 
925  ssize_t
926  y;
927 
928  assert(image != (Image *) NULL);
929  assert(image->signature == MagickCoreSignature);
930  assert(target != (PixelInfo *) NULL);
931  assert(fill != (PixelInfo *) NULL);
932  if (image->debug != MagickFalse)
933  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
934  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
935  return(MagickFalse);
936  ConformPixelInfo(image,fill,&conform_fill,exception);
937  ConformPixelInfo(image,target,&conform_target,exception);
938  /*
939  Make image color opaque.
940  */
941  status=MagickTrue;
942  progress=0;
943  GetPixelInfo(image,&zero);
944  image_view=AcquireAuthenticCacheView(image,exception);
945 #if defined(MAGICKCORE_OPENMP_SUPPORT)
946  #pragma omp parallel for schedule(static) shared(progress,status) \
947  magick_number_threads(image,image,image->rows,1)
948 #endif
949  for (y=0; y < (ssize_t) image->rows; y++)
950  {
951  PixelInfo
952  pixel;
953 
954  Quantum
955  *magick_restrict q;
956 
957  ssize_t
958  x;
959 
960  if (status == MagickFalse)
961  continue;
962  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
963  if (q == (Quantum *) NULL)
964  {
965  status=MagickFalse;
966  continue;
967  }
968  pixel=zero;
969  for (x=0; x < (ssize_t) image->columns; x++)
970  {
971  GetPixelInfoPixel(image,q,&pixel);
972  if (IsFuzzyEquivalencePixelInfo(&pixel,&conform_target) != invert)
973  {
974  PixelTrait
975  traits;
976 
978  if ((traits & UpdatePixelTrait) != 0)
979  SetPixelRed(image,(Quantum) conform_fill.red,q);
981  if ((traits & UpdatePixelTrait) != 0)
982  SetPixelGreen(image,(Quantum) conform_fill.green,q);
984  if ((traits & UpdatePixelTrait) != 0)
985  SetPixelBlue(image,(Quantum) conform_fill.blue,q);
987  if ((traits & UpdatePixelTrait) != 0)
988  SetPixelBlack(image,(Quantum) conform_fill.black,q);
990  if ((traits & UpdatePixelTrait) != 0)
991  SetPixelAlpha(image,(Quantum) conform_fill.alpha,q);
992  }
993  q+=GetPixelChannels(image);
994  }
995  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
996  status=MagickFalse;
997  if (image->progress_monitor != (MagickProgressMonitor) NULL)
998  {
1000  proceed;
1001 
1002 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1003  #pragma omp atomic
1004 #endif
1005  progress++;
1006  proceed=SetImageProgress(image,OpaquePaintImageTag,progress,
1007  image->rows);
1008  if (proceed == MagickFalse)
1009  status=MagickFalse;
1010  }
1011  }
1012  image_view=DestroyCacheView(image_view);
1013  return(status);
1014 }
1015 
1016 /*
1017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 % %
1019 % %
1020 % %
1021 % T r a n s p a r e n t P a i n t I m a g e %
1022 % %
1023 % %
1024 % %
1025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 %
1027 % TransparentPaintImage() changes the opacity value associated with any pixel
1028 % that matches color to the value defined by opacity.
1029 %
1030 % By default color must match a particular pixel color exactly. However, in
1031 % many cases two colors may differ by a small amount. Fuzz defines how much
1032 % tolerance is acceptable to consider two colors as the same. For example,
1033 % set fuzz to 10 and the color red at intensities of 100 and 102 respectively
1034 % are now interpreted as the same color.
1035 %
1036 % The format of the TransparentPaintImage method is:
1037 %
1038 % MagickBooleanType TransparentPaintImage(Image *image,
1039 % const PixelInfo *target,const Quantum opacity,
1040 % const MagickBooleanType invert,ExceptionInfo *exception)
1041 %
1042 % A description of each parameter follows:
1043 %
1044 % o image: the image.
1045 %
1046 % o target: the target color.
1047 %
1048 % o opacity: the replacement opacity value.
1049 %
1050 % o invert: paint any pixel that does not match the target color.
1051 %
1052 % o exception: return any errors or warnings in this structure.
1053 %
1054 */
1056  const PixelInfo *target,const Quantum opacity,const MagickBooleanType invert,
1057  ExceptionInfo *exception)
1058 {
1059 #define TransparentPaintImageTag "Transparent/Image"
1060 
1061  CacheView
1062  *image_view;
1063 
1065  status;
1066 
1068  progress;
1069 
1070  PixelInfo
1071  zero;
1072 
1073  ssize_t
1074  y;
1075 
1076  assert(image != (Image *) NULL);
1077  assert(image->signature == MagickCoreSignature);
1078  assert(target != (PixelInfo *) NULL);
1079  if (image->debug != MagickFalse)
1080  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1081  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1082  return(MagickFalse);
1083  if (image->alpha_trait == UndefinedPixelTrait)
1084  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1085  /*
1086  Make image color transparent.
1087  */
1088  status=MagickTrue;
1089  progress=0;
1090  GetPixelInfo(image,&zero);
1091  image_view=AcquireAuthenticCacheView(image,exception);
1092 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1093  #pragma omp parallel for schedule(static) shared(progress,status) \
1094  magick_number_threads(image,image,image->rows,1)
1095 #endif
1096  for (y=0; y < (ssize_t) image->rows; y++)
1097  {
1098  PixelInfo
1099  pixel;
1100 
1101  ssize_t
1102  x;
1103 
1104  Quantum
1105  *magick_restrict q;
1106 
1107  if (status == MagickFalse)
1108  continue;
1109  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1110  if (q == (Quantum *) NULL)
1111  {
1112  status=MagickFalse;
1113  continue;
1114  }
1115  pixel=zero;
1116  for (x=0; x < (ssize_t) image->columns; x++)
1117  {
1118  GetPixelInfoPixel(image,q,&pixel);
1119  if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert)
1120  SetPixelAlpha(image,opacity,q);
1121  q+=GetPixelChannels(image);
1122  }
1123  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1124  status=MagickFalse;
1125  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1126  {
1128  proceed;
1129 
1130 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1131  #pragma omp atomic
1132 #endif
1133  progress++;
1134  proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1135  image->rows);
1136  if (proceed == MagickFalse)
1137  status=MagickFalse;
1138  }
1139  }
1140  image_view=DestroyCacheView(image_view);
1141  return(status);
1142 }
1143 
1144 /*
1145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1146 % %
1147 % %
1148 % %
1149 % T r a n s p a r e n t P a i n t I m a g e C h r o m a %
1150 % %
1151 % %
1152 % %
1153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154 %
1155 % TransparentPaintImageChroma() changes the opacity value associated with any
1156 % pixel that matches color to the value defined by opacity.
1157 %
1158 % As there is one fuzz value for the all the channels, TransparentPaintImage()
1159 % is not suitable for the operations like chroma, where the tolerance for
1160 % similarity of two color component (RGB) can be different. Thus we define
1161 % this method to take two target pixels (one low and one high) and all the
1162 % pixels of an image which are lying between these two pixels are made
1163 % transparent.
1164 %
1165 % The format of the TransparentPaintImageChroma method is:
1166 %
1167 % MagickBooleanType TransparentPaintImageChroma(Image *image,
1168 % const PixelInfo *low,const PixelInfo *high,const Quantum opacity,
1169 % const MagickBooleanType invert,ExceptionInfo *exception)
1170 %
1171 % A description of each parameter follows:
1172 %
1173 % o image: the image.
1174 %
1175 % o low: the low target color.
1176 %
1177 % o high: the high target color.
1178 %
1179 % o opacity: the replacement opacity value.
1180 %
1181 % o invert: paint any pixel that does not match the target color.
1182 %
1183 % o exception: return any errors or warnings in this structure.
1184 %
1185 */
1187  const PixelInfo *low,const PixelInfo *high,const Quantum opacity,
1188  const MagickBooleanType invert,ExceptionInfo *exception)
1189 {
1190 #define TransparentPaintImageTag "Transparent/Image"
1191 
1192  CacheView
1193  *image_view;
1194 
1196  status;
1197 
1199  progress;
1200 
1201  ssize_t
1202  y;
1203 
1204  assert(image != (Image *) NULL);
1205  assert(image->signature == MagickCoreSignature);
1206  assert(high != (PixelInfo *) NULL);
1207  assert(low != (PixelInfo *) NULL);
1208  if (image->debug != MagickFalse)
1209  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1210  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1211  return(MagickFalse);
1212  if (image->alpha_trait == UndefinedPixelTrait)
1213  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1214  /*
1215  Make image color transparent.
1216  */
1217  status=MagickTrue;
1218  progress=0;
1219  image_view=AcquireAuthenticCacheView(image,exception);
1220 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1221  #pragma omp parallel for schedule(static) shared(progress,status) \
1222  magick_number_threads(image,image,image->rows,1)
1223 #endif
1224  for (y=0; y < (ssize_t) image->rows; y++)
1225  {
1227  match;
1228 
1229  PixelInfo
1230  pixel;
1231 
1232  Quantum
1233  *magick_restrict q;
1234 
1235  ssize_t
1236  x;
1237 
1238  if (status == MagickFalse)
1239  continue;
1240  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1241  if (q == (Quantum *) NULL)
1242  {
1243  status=MagickFalse;
1244  continue;
1245  }
1246  GetPixelInfo(image,&pixel);
1247  for (x=0; x < (ssize_t) image->columns; x++)
1248  {
1249  GetPixelInfoPixel(image,q,&pixel);
1250  match=((pixel.red >= low->red) && (pixel.red <= high->red) &&
1251  (pixel.green >= low->green) && (pixel.green <= high->green) &&
1252  (pixel.blue >= low->blue) && (pixel.blue <= high->blue)) ? MagickTrue :
1253  MagickFalse;
1254  if (match != invert)
1255  SetPixelAlpha(image,opacity,q);
1256  q+=GetPixelChannels(image);
1257  }
1258  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1259  status=MagickFalse;
1260  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1261  {
1263  proceed;
1264 
1265 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1266  #pragma omp atomic
1267 #endif
1268  progress++;
1269  proceed=SetImageProgress(image,TransparentPaintImageTag,progress,
1270  image->rows);
1271  if (proceed == MagickFalse)
1272  status=MagickFalse;
1273  }
1274  }
1275  image_view=DestroyCacheView(image_view);
1276  return(status);
1277 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
PixelInfo fill
Definition: draw.h:214
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
double x2
Definition: image.h:107
MagickExport MemoryInfo * RelinquishVirtualMemory(MemoryInfo *memory_info)
Definition: memory.c:1229
MagickProgressMonitor progress_monitor
Definition: image.h:303
PixelTrait alpha_trait
Definition: pixel.h:181
GradientType type
Definition: draw.h:150
RectangleInfo bounding_box
Definition: draw.h:153
MagickExport ssize_t ParseCommandOption(const CommandOption option, const MagickBooleanType list, const char *options)
Definition: option.c:3052
MagickExport MemoryInfo * AcquireVirtualMemory(const size_t count, const size_t quantum)
Definition: memory.c:705
static Quantum GetPixelGray(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
size_t signature
Definition: exception.h:123
MagickExport MagickStatusType ParseAbsoluteGeometry(const char *geometry, RectangleInfo *region_info)
Definition: geometry.c:710
static void GetFillColor(const DrawInfo *draw_info, const ssize_t x, const ssize_t y, PixelInfo *fill, ExceptionInfo *exception)
Definition: draw-private.h:29
static void SetPixelGray(const Image *magick_restrict image, const Quantum gray, Quantum *magick_restrict pixel)
#define OpaqueAlpha
Definition: image.h:25
MagickExport const char * GetImageArtifact(const Image *image, const char *artifact)
Definition: artifact.c:273
MagickRealType red
Definition: pixel.h:193
MagickExport MagickBooleanType TransparentPaintImage(Image *image, const PixelInfo *target, const Quantum opacity, const MagickBooleanType invert, ExceptionInfo *exception)
Definition: paint.c:1055
MagickExport MagickBooleanType SetImageAlpha(Image *image, const Quantum alpha, ExceptionInfo *exception)
Definition: image.c:2326
static double StringToDouble(const char *magick_restrict string, char **magick_restrict sentinal)
static PixelTrait GetPixelChannelTraits(const Image *magick_restrict image, const PixelChannel channel)
static void SetPixelViaPixelInfo(const Image *magick_restrict image, const PixelInfo *magick_restrict pixel_info, Quantum *magick_restrict pixel)
static MagickBooleanType IsGrayColorspace(const ColorspaceType colorspace)
#define NumberPaintBins
double angle
Definition: draw.h:175
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:651
MagickExport MagickBooleanType FloodfillPaintImage(Image *image, const DrawInfo *draw_info, const PixelInfo *target, const ssize_t x_offset, const ssize_t y_offset, const MagickBooleanType invert, ExceptionInfo *exception)
Definition: paint.c:112
MagickRealType alpha
Definition: pixel.h:193
PointInfo radii
Definition: draw.h:171
SpreadMethod spread
Definition: draw.h:165
size_t width
Definition: geometry.h:131
#define ThrowBinaryException(severity, tag, context)
Definition: log.h:52
ssize_t MagickOffsetType
Definition: magick-type.h:133
static Quantum ClampToQuantum(const MagickRealType quantum)
Definition: quantum.h:85
MagickExport void GetPixelInfo(const Image *image, PixelInfo *pixel)
Definition: pixel.c:2170
Definition: image.h:151
MagickExport MagickBooleanType DrawGradientImage(Image *image, const DrawInfo *draw_info, ExceptionInfo *exception)
Definition: draw.c:1999
double x
Definition: geometry.h:124
#define MaxStacksize
SpreadMethod
Definition: draw.h:130
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:299
GradientType
Definition: draw.h:71
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelOption alpha_type, ExceptionInfo *exception)
Definition: channel.c:974
MagickBooleanType
Definition: magick-type.h:169
MagickExport MagickBooleanType TransparentPaintImageChroma(Image *image, const PixelInfo *low, const PixelInfo *high, const Quantum opacity, const MagickBooleanType invert, ExceptionInfo *exception)
Definition: paint.c:1186
static size_t ** AcquireHistogramThreadSet(const size_t count)
Definition: paint.c:661
double x1
Definition: image.h:107
MagickExport DrawInfo * AcquireDrawInfo(void)
Definition: draw.c:232
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:665
PointInfo center
Definition: draw.h:171
MagickPrivate size_t GetOptimalKernelWidth2D(const double, const double)
Definition: gem.c:1685
static double DegreesToRadians(const double degrees)
Definition: image-private.h:64
double y
Definition: geometry.h:124
static int GetOpenMPThreadId(void)
StopInfo * stops
Definition: draw.h:159
static void GetPixelInfoPixel(const Image *magick_restrict image, const Quantum *magick_restrict pixel, PixelInfo *magick_restrict pixel_info)
PixelTrait alpha_trait
Definition: image.h:280
MagickRealType blue
Definition: pixel.h:193
MagickExport Quantum * QueueCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:977
GravityType
Definition: geometry.h:78
double y2
Definition: image.h:107
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1660
MagickExport MagickBooleanType SetImageBackgroundColor(Image *image, ExceptionInfo *exception)
Definition: image.c:2405
size_t signature
Definition: image.h:354
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
Definition: resource.c:793
size_t columns
Definition: image.h:172
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
size_t height
Definition: geometry.h:131
MagickExport MagickBooleanType QueryColorCompliance(const char *name, const ComplianceType compliance, PixelInfo *color, ExceptionInfo *exception)
Definition: color.c:2265
static void SetPixelBlue(const Image *magick_restrict image, const Quantum blue, Quantum *magick_restrict pixel)
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2605
PixelChannel
Definition: pixel.h:70
#define TransparentPaintImageTag
GradientInfo gradient
Definition: draw.h:227
#define MagickMax(x, y)
Definition: image-private.h:36
MagickExport MagickBooleanType OpaquePaintImage(Image *image, const PixelInfo *target, const PixelInfo *fill, const MagickBooleanType invert, ExceptionInfo *exception)
Definition: paint.c:905
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1403
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
#define OilPaintImageTag
MagickExport void ConformPixelInfo(Image *image, const PixelInfo *source, PixelInfo *destination, ExceptionInfo *exception)
Definition: pixel.c:212
#define ThrowImageException(severity, tag)
static PixelChannel GetPixelChannelChannel(const Image *magick_restrict image, const ssize_t offset)
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:149
size_t signature
Definition: draw.h:323
unsigned short Quantum
Definition: magick-type.h:86
MagickExport MagickBooleanType SetImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1419
MagickExport DrawInfo * DestroyDrawInfo(DrawInfo *draw_info)
Definition: draw.c:966
static size_t ** DestroyHistogramThreadSet(size_t **histogram)
Definition: paint.c:648
MagickRealType black
Definition: pixel.h:193
MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p, const PixelInfo *q)
Definition: pixel.c:6056
SegmentInfo gradient_vector
Definition: draw.h:156
#define OpaquePaintImageTag
static void SetPixelChannel(const Image *magick_restrict image, const PixelChannel channel, const Quantum quantum, Quantum *magick_restrict pixel)
#define MagickMin(x, y)
Definition: image-private.h:37
static void SetPixelAlpha(const Image *magick_restrict image, const Quantum alpha, Quantum *magick_restrict pixel)
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1162
MagickRealType green
Definition: pixel.h:193
MagickExport MagickBooleanType GradientImage(Image *image, const GradientType type, const SpreadMethod method, const StopInfo *stops, const size_t number_stops, ExceptionInfo *exception)
Definition: paint.c:403
static void SetPixelRed(const Image *magick_restrict image, const Quantum red, Quantum *magick_restrict pixel)
size_t number_stops
Definition: draw.h:162
#define PushSegmentStack(up, left, right, delta)
#define MagickExport
double radius
Definition: draw.h:175
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
MagickExport Image * OilPaintImage(const Image *image, const double radius, const double sigma, ExceptionInfo *exception)
Definition: paint.c:684
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
double y1
Definition: image.h:107
static void SetPixelBlack(const Image *magick_restrict image, const Quantum black, Quantum *magick_restrict pixel)
PixelTrait
Definition: pixel.h:137
MagickExport void * GetVirtualMemoryBlob(const MemoryInfo *memory_info)
Definition: memory.c:1090
MagickExport MagickRealType GetPixelIntensity(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
Definition: pixel.c:2358
PixelInfo background_color
Definition: image.h:179
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1168
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:779
ColorspaceType colorspace
Definition: image.h:157
#define QuantumRange
Definition: magick-type.h:87
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickBooleanType debug
Definition: image.h:334
static void SetPixelGreen(const Image *magick_restrict image, const Quantum green, Quantum *magick_restrict pixel)