MagickCore  7.0.3
attribute.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % AAA TTTTT TTTTT RRRR IIIII BBBB U U TTTTT EEEEE %
7 % A A T T R R I B B U U T E %
8 % AAAAA T T RRRR I BBBB U U T EEE %
9 % A A T T R R I B B U U T E %
10 % A A T T R R IIIII BBBB UUU T EEEEE %
11 % %
12 % %
13 % MagickCore Get / Set Image Attributes %
14 % %
15 % Software Design %
16 % Cristy %
17 % October 2002 %
18 % %
19 % %
20 % Copyright 1999-2019 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 /*
41  Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/artifact.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/blob.h"
48 #include "MagickCore/cache.h"
50 #include "MagickCore/cache-view.h"
51 #include "MagickCore/channel.h"
52 #include "MagickCore/client.h"
53 #include "MagickCore/color.h"
55 #include "MagickCore/colormap.h"
57 #include "MagickCore/colorspace.h"
59 #include "MagickCore/composite.h"
61 #include "MagickCore/constitute.h"
62 #include "MagickCore/draw.h"
64 #include "MagickCore/effect.h"
65 #include "MagickCore/enhance.h"
66 #include "MagickCore/exception.h"
68 #include "MagickCore/geometry.h"
69 #include "MagickCore/histogram.h"
70 #include "MagickCore/identify.h"
71 #include "MagickCore/image.h"
73 #include "MagickCore/list.h"
74 #include "MagickCore/log.h"
75 #include "MagickCore/memory_.h"
76 #include "MagickCore/magick.h"
77 #include "MagickCore/monitor.h"
79 #include "MagickCore/option.h"
80 #include "MagickCore/paint.h"
81 #include "MagickCore/pixel.h"
83 #include "MagickCore/property.h"
84 #include "MagickCore/quantize.h"
86 #include "MagickCore/random_.h"
87 #include "MagickCore/resource_.h"
88 #include "MagickCore/semaphore.h"
89 #include "MagickCore/segment.h"
90 #include "MagickCore/splay-tree.h"
91 #include "MagickCore/string_.h"
94 #include "MagickCore/threshold.h"
95 #include "MagickCore/transform.h"
96 #include "MagickCore/utility.h"
97 
98 /*
99 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100 % %
101 % %
102 % %
103 + G e t I m a g e B o u n d i n g B o x %
104 % %
105 % %
106 % %
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 %
109 % GetImageBoundingBox() returns the bounding box of an image canvas.
110 %
111 % The format of the GetImageBoundingBox method is:
112 %
113 % RectangleInfo GetImageBoundingBox(const Image *image,
114 % ExceptionInfo *exception)
115 %
116 % A description of each parameter follows:
117 %
118 % o bounds: Method GetImageBoundingBox returns the bounding box of an
119 % image canvas.
120 %
121 % o image: the image.
122 %
123 % o exception: return any errors or warnings in this structure.
124 %
125 */
126 
127 typedef struct _EdgeInfo
128 {
129  double
131  right,
132  top,
133  bottom;
134 } EdgeInfo;
135 
136 static double GetEdgeBackgroundFactor(const Image *image,
137  const CacheView *image_view,const GravityType gravity,const size_t width,
138  const size_t height,const ssize_t x_offset,const ssize_t y_offset,
139  ExceptionInfo *exception)
140 {
141  CacheView
142  *edge_view;
143 
144  double
145  factor;
146 
147  Image
148  *edge_image;
149 
150  PixelInfo
151  background,
152  pixel;
153 
155  edge_geometry;
156 
157  register const Quantum
158  *p;
159 
160  ssize_t
161  y;
162 
163  /*
164  Determine the percent of image background for this edge.
165  */
166  switch (gravity)
167  {
168  case NorthWestGravity:
169  case NorthGravity:
170  default:
171  {
172  p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
173  break;
174  }
175  case NorthEastGravity:
176  case EastGravity:
177  {
178  p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
179  exception);
180  break;
181  }
182  case SouthEastGravity:
183  case SouthGravity:
184  {
185  p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,
186  (ssize_t) image->rows-1,1,1,exception);
187  break;
188  }
189  case SouthWestGravity:
190  case WestGravity:
191  {
192  p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
193  exception);
194  break;
195  }
196  }
197  GetPixelInfoPixel(image,p,&background);
198  edge_geometry.width=width;
199  edge_geometry.height=height;
200  edge_geometry.x=x_offset;
201  edge_geometry.y=y_offset;
202  GravityAdjustGeometry(image->columns,image->rows,gravity,&edge_geometry);
203  edge_image=CropImage(image,&edge_geometry,exception);
204  if (edge_image == (Image *) NULL)
205  return(0.0);
206  factor=0.0;
207  edge_view=AcquireVirtualCacheView(edge_image,exception);
208  for (y=0; y < (ssize_t) edge_image->rows; y++)
209  {
210  register ssize_t
211  x;
212 
213  p=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
214  if (p == (const Quantum *) NULL)
215  break;
216  for (x=0; x < (ssize_t) edge_image->columns; x++)
217  {
218  GetPixelInfoPixel(edge_image,p,&pixel);
219  if (IsFuzzyEquivalencePixelInfo(&pixel,&background) == MagickFalse)
220  factor++;
221  p+=GetPixelChannels(edge_image);
222  }
223  }
224  factor/=((double) edge_image->columns*edge_image->rows);
225  edge_view=DestroyCacheView(edge_view);
226  edge_image=DestroyImage(edge_image);
227  return(factor);
228 }
229 
230 static inline double GetMinEdgeBackgroundFactor(const EdgeInfo *edge)
231 {
232  double
233  factor;
234 
235  factor=MagickMin(MagickMin(MagickMin(edge->left,edge->right),edge->top),
236  edge->bottom);
237  return(factor);
238 }
239 
241  ExceptionInfo *exception)
242 {
243  CacheView
244  *edge_view;
245 
246  const char
247  *artifact;
248 
249  double
250  background_factor,
251  percent_background;
252 
253  EdgeInfo
254  edge,
255  vertex;
256 
257  Image
258  *edge_image;
259 
261  bounds;
262 
263  /*
264  Get the image bounding box.
265  */
266  assert(image != (Image *) NULL);
267  assert(image->signature == MagickCoreSignature);
268  if (image->debug != MagickFalse)
269  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
270  SetGeometry(image,&bounds);
271  edge_image=CloneImage(image,0,0,MagickTrue,exception);
272  if (edge_image == (Image *) NULL)
273  return(bounds);
274  (void) ParseAbsoluteGeometry("0x0+0+0",&edge_image->page);
275  memset(&vertex,0,sizeof(vertex));
276  edge_view=AcquireVirtualCacheView(edge_image,exception);
277  edge.left=GetEdgeBackgroundFactor(edge_image,edge_view,WestGravity,
278  1,0,0,0,exception);
279  edge.right=GetEdgeBackgroundFactor(edge_image,edge_view,EastGravity,
280  1,0,0,0,exception);
281  edge.top=GetEdgeBackgroundFactor(edge_image,edge_view,NorthGravity,
282  0,1,0,0,exception);
283  edge.bottom=GetEdgeBackgroundFactor(edge_image,edge_view,SouthGravity,
284  0,1,0,0,exception);
285  percent_background=1.0;
286  artifact=GetImageArtifact(edge_image,"trim:percent-background");
287  if (artifact != (const char *) NULL)
288  percent_background=StringToDouble(artifact,(char **) NULL)/100.0;
289  percent_background=MagickMin(MagickMax(1.0-percent_background,MagickEpsilon),
290  1.0);
291  background_factor=GetMinEdgeBackgroundFactor(&edge);
292  for ( ; background_factor < percent_background;
293  background_factor=GetMinEdgeBackgroundFactor(&edge))
294  {
295  if ((bounds.width == 0) || (bounds.height == 0))
296  break;
297  if (fabs(edge.left-background_factor) < MagickEpsilon)
298  {
299  /*
300  Trim left edge.
301  */
302  vertex.left++;
303  bounds.width--;
304  edge.left=GetEdgeBackgroundFactor(edge_image,edge_view,
305  NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
306  vertex.top,exception);
307  edge.top=GetEdgeBackgroundFactor(edge_image,edge_view,
308  NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
309  vertex.top,exception);
310  edge.bottom=GetEdgeBackgroundFactor(edge_image,edge_view,
311  SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
312  vertex.bottom,exception);
313  continue;
314  }
315  if (fabs(edge.right-background_factor) < MagickEpsilon)
316  {
317  /*
318  Trim right edge.
319  */
320  vertex.right++;
321  bounds.width--;
322  edge.right=GetEdgeBackgroundFactor(edge_image,edge_view,
323  NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
324  vertex.top,exception);
325  edge.top=GetEdgeBackgroundFactor(edge_image,edge_view,
326  NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
327  vertex.top,exception);
328  edge.bottom=GetEdgeBackgroundFactor(edge_image,edge_view,
329  SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
330  vertex.bottom,exception);
331  continue;
332  }
333  if (fabs(edge.top-background_factor) < MagickEpsilon)
334  {
335  /*
336  Trim top edge.
337  */
338  vertex.top++;
339  bounds.height--;
340  edge.left=GetEdgeBackgroundFactor(edge_image,edge_view,
341  NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
342  vertex.top,exception);
343  edge.right=GetEdgeBackgroundFactor(edge_image,edge_view,
344  NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
345  vertex.top,exception);
346  edge.top=GetEdgeBackgroundFactor(edge_image,edge_view,
347  NorthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
348  vertex.top,exception);
349  continue;
350  }
351  if (fabs(edge.bottom-background_factor) < MagickEpsilon)
352  {
353  /*
354  Trim bottom edge.
355  */
356  vertex.bottom++;
357  bounds.height--;
358  edge.left=GetEdgeBackgroundFactor(edge_image,edge_view,
359  NorthWestGravity,1,bounds.height,(ssize_t) vertex.left,(ssize_t)
360  vertex.top,exception);
361  edge.right=GetEdgeBackgroundFactor(edge_image,edge_view,
362  NorthEastGravity,1,bounds.height,(ssize_t) vertex.right,(ssize_t)
363  vertex.top,exception);
364  edge.bottom=GetEdgeBackgroundFactor(edge_image,edge_view,
365  SouthWestGravity,bounds.width,1,(ssize_t) vertex.left,(ssize_t)
366  vertex.bottom,exception);
367  continue;
368  }
369  }
370  edge_view=DestroyCacheView(edge_view);
371  edge_image=DestroyImage(edge_image);
372  bounds.x=(ssize_t) vertex.left;
373  bounds.y=(ssize_t) vertex.top;
374  if ((bounds.width == 0) || (bounds.height == 0))
376  "GeometryDoesNotContainImage","`%s'",image->filename);
377  return(bounds);
378 }
379 
380 /*
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 % %
383 % %
384 % %
385 % G e t I m a g e D e p t h %
386 % %
387 % %
388 % %
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 %
391 % GetImageDepth() returns the depth of a particular image channel.
392 %
393 % The format of the GetImageDepth method is:
394 %
395 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
396 %
397 % A description of each parameter follows:
398 %
399 % o image: the image.
400 %
401 % o exception: return any errors or warnings in this structure.
402 %
403 */
404 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
405 {
406  CacheView
407  *image_view;
408 
410  status;
411 
412  register ssize_t
413  i;
414 
415  size_t
416  *current_depth,
417  depth,
418  number_threads;
419 
420  ssize_t
421  y;
422 
423  /*
424  Compute image depth.
425  */
426  assert(image != (Image *) NULL);
427  assert(image->signature == MagickCoreSignature);
428  if (image->debug != MagickFalse)
429  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
430  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
431  current_depth=(size_t *) AcquireQuantumMemory(number_threads,
432  sizeof(*current_depth));
433  if (current_depth == (size_t *) NULL)
434  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
435  status=MagickTrue;
436  for (i=0; i < (ssize_t) number_threads; i++)
437  current_depth[i]=1;
438  if ((image->storage_class == PseudoClass) &&
439  (image->alpha_trait == UndefinedPixelTrait))
440  {
441  for (i=0; i < (ssize_t) image->colors; i++)
442  {
443  const int
444  id = GetOpenMPThreadId();
445 
446  while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
447  {
449  atDepth;
450 
451  QuantumAny
452  range;
453 
454  atDepth=MagickTrue;
455  range=GetQuantumRange(current_depth[id]);
456  if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
457  if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].red),range) == MagickFalse)
458  atDepth=MagickFalse;
459  if ((atDepth != MagickFalse) &&
460  (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
461  if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].green),range) == MagickFalse)
462  atDepth=MagickFalse;
463  if ((atDepth != MagickFalse) &&
464  (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
465  if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].blue),range) == MagickFalse)
466  atDepth=MagickFalse;
467  if ((atDepth != MagickFalse))
468  break;
469  current_depth[id]++;
470  }
471  }
472  depth=current_depth[0];
473  for (i=1; i < (ssize_t) number_threads; i++)
474  if (depth < current_depth[i])
475  depth=current_depth[i];
476  current_depth=(size_t *) RelinquishMagickMemory(current_depth);
477  return(depth);
478  }
479  image_view=AcquireVirtualCacheView(image,exception);
480 #if !defined(MAGICKCORE_HDRI_SUPPORT)
481  if ((1UL*QuantumRange) <= MaxMap)
482  {
483  size_t
484  *depth_map;
485 
486  /*
487  Scale pixels to desired (optimized with depth map).
488  */
489  depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
490  if (depth_map == (size_t *) NULL)
491  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
492  for (i=0; i <= (ssize_t) MaxMap; i++)
493  {
494  unsigned int
495  depth;
496 
497  for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
498  {
499  Quantum
500  pixel;
501 
502  QuantumAny
503  range;
504 
505  range=GetQuantumRange(depth);
506  pixel=(Quantum) i;
507  if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
508  break;
509  }
510  depth_map[i]=depth;
511  }
512 #if defined(MAGICKCORE_OPENMP_SUPPORT)
513  #pragma omp parallel for schedule(static) shared(status) \
514  magick_number_threads(image,image,image->rows,1)
515 #endif
516  for (y=0; y < (ssize_t) image->rows; y++)
517  {
518  const int
519  id = GetOpenMPThreadId();
520 
521  register const Quantum
522  *magick_restrict p;
523 
524  register ssize_t
525  x;
526 
527  if (status == MagickFalse)
528  continue;
529  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
530  if (p == (const Quantum *) NULL)
531  continue;
532  for (x=0; x < (ssize_t) image->columns; x++)
533  {
534  register ssize_t
535  i;
536 
537  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
538  {
539  PixelChannel channel = GetPixelChannelChannel(image,i);
540  PixelTrait traits = GetPixelChannelTraits(image,channel);
541  if ((traits & UpdatePixelTrait) == 0)
542  continue;
543  if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
544  current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
545  }
546  p+=GetPixelChannels(image);
547  }
548  if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
549  status=MagickFalse;
550  }
551  image_view=DestroyCacheView(image_view);
552  depth=current_depth[0];
553  for (i=1; i < (ssize_t) number_threads; i++)
554  if (depth < current_depth[i])
555  depth=current_depth[i];
556  depth_map=(size_t *) RelinquishMagickMemory(depth_map);
557  current_depth=(size_t *) RelinquishMagickMemory(current_depth);
558  return(depth);
559  }
560 #endif
561  /*
562  Compute pixel depth.
563  */
564 #if defined(MAGICKCORE_OPENMP_SUPPORT)
565  #pragma omp parallel for schedule(static) shared(status) \
566  magick_number_threads(image,image,image->rows,1)
567 #endif
568  for (y=0; y < (ssize_t) image->rows; y++)
569  {
570  const int
571  id = GetOpenMPThreadId();
572 
573  register const Quantum
574  *magick_restrict p;
575 
576  register ssize_t
577  x;
578 
579  if (status == MagickFalse)
580  continue;
581  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
582  if (p == (const Quantum *) NULL)
583  continue;
584  for (x=0; x < (ssize_t) image->columns; x++)
585  {
586  register ssize_t
587  i;
588 
589  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
590  {
592  channel;
593 
594  PixelTrait
595  traits;
596 
597  channel=GetPixelChannelChannel(image,i);
598  traits=GetPixelChannelTraits(image,channel);
599  if ((traits & UpdatePixelTrait) == 0)
600  continue;
601  while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
602  {
603  QuantumAny
604  range;
605 
606  range=GetQuantumRange(current_depth[id]);
607  if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
608  break;
609  current_depth[id]++;
610  }
611  }
612  p+=GetPixelChannels(image);
613  }
614  if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
615  status=MagickFalse;
616  }
617  image_view=DestroyCacheView(image_view);
618  depth=current_depth[0];
619  for (i=1; i < (ssize_t) number_threads; i++)
620  if (depth < current_depth[i])
621  depth=current_depth[i];
622  current_depth=(size_t *) RelinquishMagickMemory(current_depth);
623  return(depth);
624 }
625 
626 /*
627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628 % %
629 % %
630 % %
631 % G e t I m a g e Q u a n t u m D e p t h %
632 % %
633 % %
634 % %
635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636 %
637 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
638 % quantum depth: 8, 16, or 32.
639 %
640 % The format of the GetImageQuantumDepth method is:
641 %
642 % size_t GetImageQuantumDepth(const Image *image,
643 % const MagickBooleanType constrain)
644 %
645 % A description of each parameter follows:
646 %
647 % o image: the image.
648 %
649 % o constrain: A value other than MagickFalse, constrains the depth to
650 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
651 %
652 */
654  const MagickBooleanType constrain)
655 {
656  size_t
657  depth;
658 
659  depth=image->depth;
660  if (depth <= 8)
661  depth=8;
662  else
663  if (depth <= 16)
664  depth=16;
665  else
666  if (depth <= 32)
667  depth=32;
668  else
669  if (depth <= 64)
670  depth=64;
671  if (constrain != MagickFalse)
672  depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
673  return(depth);
674 }
675 
676 /*
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 % %
679 % %
680 % %
681 % G e t I m a g e T y p e %
682 % %
683 % %
684 % %
685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 %
687 % GetImageType() returns the type of image:
688 %
689 % Bilevel Grayscale GrayscaleMatte
690 % Palette PaletteMatte TrueColor
691 % TrueColorMatte ColorSeparation ColorSeparationMatte
692 %
693 % The format of the GetImageType method is:
694 %
695 % ImageType GetImageType(const Image *image)
696 %
697 % A description of each parameter follows:
698 %
699 % o image: the image.
700 %
701 */
703 {
704  assert(image != (Image *) NULL);
705  assert(image->signature == MagickCoreSignature);
706  if (image->colorspace == CMYKColorspace)
707  {
708  if (image->alpha_trait == UndefinedPixelTrait)
709  return(ColorSeparationType);
710  return(ColorSeparationAlphaType);
711  }
712  if (IsImageMonochrome(image) != MagickFalse)
713  return(BilevelType);
714  if (IsImageGray(image) != MagickFalse)
715  {
716  if (image->alpha_trait != UndefinedPixelTrait)
717  return(GrayscaleAlphaType);
718  return(GrayscaleType);
719  }
720  if (IsPaletteImage(image) != MagickFalse)
721  {
722  if (image->alpha_trait != UndefinedPixelTrait)
723  return(PaletteAlphaType);
724  return(PaletteType);
725  }
726  if (image->alpha_trait != UndefinedPixelTrait)
727  return(TrueColorAlphaType);
728  return(TrueColorType);
729 }
730 
731 /*
732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
733 % %
734 % %
735 % %
736 % I d e n t i f y I m a g e G r a y %
737 % %
738 % %
739 % %
740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
741 %
742 % IdentifyImageGray() returns grayscale if all the pixels in the image have
743 % the same red, green, and blue intensities, and bi-level is the intensity is
744 % either 0 or QuantumRange. Otherwise undefined is returned.
745 %
746 % The format of the IdentifyImageGray method is:
747 %
748 % ImageType IdentifyImageGray(const Image *image,ExceptionInfo *exception)
749 %
750 % A description of each parameter follows:
751 %
752 % o image: the image.
753 %
754 % o exception: return any errors or warnings in this structure.
755 %
756 */
758  ExceptionInfo *exception)
759 {
760  CacheView
761  *image_view;
762 
763  ImageType
764  type;
765 
766  register const Quantum
767  *p;
768 
769  register ssize_t
770  x;
771 
772  ssize_t
773  y;
774 
775  assert(image != (Image *) NULL);
776  assert(image->signature == MagickCoreSignature);
777  if (image->debug != MagickFalse)
778  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
779  if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
780  (image->type == GrayscaleAlphaType))
781  return(image->type);
783  return(UndefinedType);
784  type=BilevelType;
785  image_view=AcquireVirtualCacheView(image,exception);
786  for (y=0; y < (ssize_t) image->rows; y++)
787  {
788  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
789  if (p == (const Quantum *) NULL)
790  break;
791  for (x=0; x < (ssize_t) image->columns; x++)
792  {
793  if (IsPixelGray(image,p) == MagickFalse)
794  {
795  type=UndefinedType;
796  break;
797  }
798  if ((type == BilevelType) &&
799  (IsPixelMonochrome(image,p) == MagickFalse))
800  type=GrayscaleType;
801  p+=GetPixelChannels(image);
802  }
803  if (type == UndefinedType)
804  break;
805  }
806  image_view=DestroyCacheView(image_view);
807  if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
808  type=GrayscaleAlphaType;
809  return(type);
810 }
811 
812 /*
813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 % %
815 % %
816 % %
817 % I d e n t i f y I m a g e M o n o c h r o m e %
818 % %
819 % %
820 % %
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %
823 % IdentifyImageMonochrome() returns MagickTrue if all the pixels in the image
824 % have the same red, green, and blue intensities and the intensity is either
825 % 0 or QuantumRange.
826 %
827 % The format of the IdentifyImageMonochrome method is:
828 %
829 % MagickBooleanType IdentifyImageMonochrome(const Image *image,
830 % ExceptionInfo *exception)
831 %
832 % A description of each parameter follows:
833 %
834 % o image: the image.
835 %
836 % o exception: return any errors or warnings in this structure.
837 %
838 */
840  ExceptionInfo *exception)
841 {
842  CacheView
843  *image_view;
844 
846  bilevel;
847 
848  register ssize_t
849  x;
850 
851  register const Quantum
852  *p;
853 
854  ssize_t
855  y;
856 
857  assert(image != (Image *) NULL);
858  assert(image->signature == MagickCoreSignature);
859  if (image->debug != MagickFalse)
860  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
861  if (image->type == BilevelType)
862  return(MagickTrue);
864  return(MagickFalse);
865  bilevel=MagickTrue;
866  image_view=AcquireVirtualCacheView(image,exception);
867  for (y=0; y < (ssize_t) image->rows; y++)
868  {
869  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
870  if (p == (const Quantum *) NULL)
871  break;
872  for (x=0; x < (ssize_t) image->columns; x++)
873  {
874  if (IsPixelMonochrome(image,p) == MagickFalse)
875  {
876  bilevel=MagickFalse;
877  break;
878  }
879  p+=GetPixelChannels(image);
880  }
881  if (bilevel == MagickFalse)
882  break;
883  }
884  image_view=DestroyCacheView(image_view);
885  return(bilevel);
886 }
887 
888 /*
889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890 % %
891 % %
892 % %
893 % I d e n t i f y I m a g e T y p e %
894 % %
895 % %
896 % %
897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898 %
899 % IdentifyImageType() returns the potential type of image:
900 %
901 % Bilevel Grayscale GrayscaleMatte
902 % Palette PaletteMatte TrueColor
903 % TrueColorMatte ColorSeparation ColorSeparationMatte
904 %
905 % To ensure the image type matches its potential, use SetImageType():
906 %
907 % (void) SetImageType(image,IdentifyImageType(image,exception),exception);
908 %
909 % The format of the IdentifyImageType method is:
910 %
911 % ImageType IdentifyImageType(const Image *image,ExceptionInfo *exception)
912 %
913 % A description of each parameter follows:
914 %
915 % o image: the image.
916 %
917 % o exception: return any errors or warnings in this structure.
918 %
919 */
921  ExceptionInfo *exception)
922 {
923  assert(image != (Image *) NULL);
924  assert(image->signature == MagickCoreSignature);
925  if (image->debug != MagickFalse)
926  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
927  if (image->colorspace == CMYKColorspace)
928  {
929  if (image->alpha_trait == UndefinedPixelTrait)
930  return(ColorSeparationType);
931  return(ColorSeparationAlphaType);
932  }
933  if (IdentifyImageMonochrome(image,exception) != MagickFalse)
934  return(BilevelType);
935  if (IdentifyImageGray(image,exception) != UndefinedType)
936  {
937  if (image->alpha_trait != UndefinedPixelTrait)
938  return(GrayscaleAlphaType);
939  return(GrayscaleType);
940  }
941  if (IdentifyPaletteImage(image,exception) != MagickFalse)
942  {
943  if (image->alpha_trait != UndefinedPixelTrait)
944  return(PaletteAlphaType);
945  return(PaletteType);
946  }
947  if (image->alpha_trait != UndefinedPixelTrait)
948  return(TrueColorAlphaType);
949  return(TrueColorType);
950 }
951 
952 /*
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 % %
955 % %
956 % %
957 % I s I m a g e G r a y %
958 % %
959 % %
960 % %
961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962 %
963 % IsImageGray() returns MagickTrue if the type of the image is grayscale or
964 % bi-level.
965 %
966 % The format of the IsImageGray method is:
967 %
968 % MagickBooleanType IsImageGray(const Image *image)
969 %
970 % A description of each parameter follows:
971 %
972 % o image: the image.
973 %
974 */
976 {
977  assert(image != (Image *) NULL);
978  assert(image->signature == MagickCoreSignature);
979  if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
980  (image->type == GrayscaleAlphaType))
981  return(MagickTrue);
982  return(MagickFalse);
983 }
984 
985 /*
986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 % %
988 % %
989 % %
990 % I s I m a g e M o n o c h r o m e %
991 % %
992 % %
993 % %
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 %
996 % IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
997 %
998 % The format of the IsImageMonochrome method is:
999 %
1000 % MagickBooleanType IsImageMonochrome(const Image *image)
1001 %
1002 % A description of each parameter follows:
1003 %
1004 % o image: the image.
1005 %
1006 */
1008 {
1009  assert(image != (Image *) NULL);
1010  assert(image->signature == MagickCoreSignature);
1011  if (image->type == BilevelType)
1012  return(MagickTrue);
1013  return(MagickFalse);
1014 }
1015 
1016 /*
1017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 % %
1019 % %
1020 % %
1021 % I s I m a g e O p a q u e %
1022 % %
1023 % %
1024 % %
1025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 %
1027 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
1028 % an alpha value other than OpaqueAlpha (QuantumRange).
1029 %
1030 % Will return true immediatally is alpha channel is not available.
1031 %
1032 % The format of the IsImageOpaque method is:
1033 %
1034 % MagickBooleanType IsImageOpaque(const Image *image,
1035 % ExceptionInfo *exception)
1036 %
1037 % A description of each parameter follows:
1038 %
1039 % o image: the image.
1040 %
1041 % o exception: return any errors or warnings in this structure.
1042 %
1043 */
1045  ExceptionInfo *exception)
1046 {
1047  CacheView
1048  *image_view;
1049 
1050  register const Quantum
1051  *p;
1052 
1053  register ssize_t
1054  x;
1055 
1056  ssize_t
1057  y;
1058 
1059  /*
1060  Determine if image is opaque.
1061  */
1062  assert(image != (Image *) NULL);
1063  assert(image->signature == MagickCoreSignature);
1064  if (image->debug != MagickFalse)
1065  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1066  if (image->alpha_trait == UndefinedPixelTrait)
1067  return(MagickTrue);
1068  image_view=AcquireVirtualCacheView(image,exception);
1069  for (y=0; y < (ssize_t) image->rows; y++)
1070  {
1071  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1072  if (p == (const Quantum *) NULL)
1073  break;
1074  for (x=0; x < (ssize_t) image->columns; x++)
1075  {
1076  if (GetPixelAlpha(image,p) != OpaqueAlpha)
1077  break;
1078  p+=GetPixelChannels(image);
1079  }
1080  if (x < (ssize_t) image->columns)
1081  break;
1082  }
1083  image_view=DestroyCacheView(image_view);
1084  return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
1085 }
1086 
1087 /*
1088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1089 % %
1090 % %
1091 % %
1092 % S e t I m a g e D e p t h %
1093 % %
1094 % %
1095 % %
1096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1097 %
1098 % SetImageDepth() sets the depth of the image.
1099 %
1100 % The format of the SetImageDepth method is:
1101 %
1102 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
1103 % ExceptionInfo *exception)
1104 %
1105 % A description of each parameter follows:
1106 %
1107 % o image: the image.
1108 %
1109 % o channel: the channel.
1110 %
1111 % o depth: the image depth.
1112 %
1113 % o exception: return any errors or warnings in this structure.
1114 %
1115 */
1117  const size_t depth,ExceptionInfo *exception)
1118 {
1119  CacheView
1120  *image_view;
1121 
1123  status;
1124 
1125  QuantumAny
1126  range;
1127 
1128  ssize_t
1129  y;
1130 
1131  assert(image != (Image *) NULL);
1132  if (image->debug != MagickFalse)
1133  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1134  assert(image->signature == MagickCoreSignature);
1135  if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1136  {
1137  image->depth=depth;
1138  return(MagickTrue);
1139  }
1140  range=GetQuantumRange(depth);
1141  if (image->storage_class == PseudoClass)
1142  {
1143  register ssize_t
1144  i;
1145 
1146 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1147  #pragma omp parallel for schedule(static) shared(status) \
1148  magick_number_threads(image,image,image->colors,1)
1149 #endif
1150  for (i=0; i < (ssize_t) image->colors; i++)
1151  {
1152  if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
1153  image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1154  ClampPixel(image->colormap[i].red),range),range);
1155  if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
1157  ClampPixel(image->colormap[i].green),range),range);
1158  if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
1159  image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1160  ClampPixel(image->colormap[i].blue),range),range);
1161  if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
1163  ClampPixel(image->colormap[i].alpha),range),range);
1164  }
1165  }
1166  status=MagickTrue;
1167  image_view=AcquireAuthenticCacheView(image,exception);
1168 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1169  if ((1UL*QuantumRange) <= MaxMap)
1170  {
1171  Quantum
1172  *depth_map;
1173 
1174  register ssize_t
1175  i;
1176 
1177  /*
1178  Scale pixels to desired (optimized with depth map).
1179  */
1180  depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
1181  if (depth_map == (Quantum *) NULL)
1182  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1183  for (i=0; i <= (ssize_t) MaxMap; i++)
1184  depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1185  range);
1186 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1187  #pragma omp parallel for schedule(static) shared(status) \
1188  magick_number_threads(image,image,image->rows,1)
1189 #endif
1190  for (y=0; y < (ssize_t) image->rows; y++)
1191  {
1192  register ssize_t
1193  x;
1194 
1195  register Quantum
1196  *magick_restrict q;
1197 
1198  if (status == MagickFalse)
1199  continue;
1200  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1201  exception);
1202  if (q == (Quantum *) NULL)
1203  {
1204  status=MagickFalse;
1205  continue;
1206  }
1207  for (x=0; x < (ssize_t) image->columns; x++)
1208  {
1209  register ssize_t
1210  i;
1211 
1212  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1213  {
1214  PixelChannel
1215  channel;
1216 
1217  PixelTrait
1218  traits;
1219 
1220  channel=GetPixelChannelChannel(image,i);
1221  traits=GetPixelChannelTraits(image,channel);
1222  if ((traits & UpdatePixelTrait) == 0)
1223  continue;
1224  q[i]=depth_map[ScaleQuantumToMap(q[i])];
1225  }
1226  q+=GetPixelChannels(image);
1227  }
1228  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1229  {
1230  status=MagickFalse;
1231  continue;
1232  }
1233  }
1234  image_view=DestroyCacheView(image_view);
1235  depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1236  if (status != MagickFalse)
1237  image->depth=depth;
1238  return(status);
1239  }
1240 #endif
1241  /*
1242  Scale pixels to desired depth.
1243  */
1244 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1245  #pragma omp parallel for schedule(static) shared(status) \
1246  magick_number_threads(image,image,image->rows,1)
1247 #endif
1248  for (y=0; y < (ssize_t) image->rows; y++)
1249  {
1250  register ssize_t
1251  x;
1252 
1253  register Quantum
1254  *magick_restrict q;
1255 
1256  if (status == MagickFalse)
1257  continue;
1258  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1259  if (q == (Quantum *) NULL)
1260  {
1261  status=MagickFalse;
1262  continue;
1263  }
1264  for (x=0; x < (ssize_t) image->columns; x++)
1265  {
1266  register ssize_t
1267  i;
1268 
1269  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1270  {
1271  PixelChannel
1272  channel;
1273 
1274  PixelTrait
1275  traits;
1276 
1277  channel=GetPixelChannelChannel(image,i);
1278  traits=GetPixelChannelTraits(image,channel);
1279  if ((traits & UpdatePixelTrait) == 0)
1280  continue;
1282  q[i]),range),range);
1283  }
1284  q+=GetPixelChannels(image);
1285  }
1286  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1287  {
1288  status=MagickFalse;
1289  continue;
1290  }
1291  }
1292  image_view=DestroyCacheView(image_view);
1293  if (status != MagickFalse)
1294  image->depth=depth;
1295  return(status);
1296 }
1297 
1298 /*
1299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300 % %
1301 % %
1302 % %
1303 % S e t I m a g e T y p e %
1304 % %
1305 % %
1306 % %
1307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1308 %
1309 % SetImageType() sets the type of image. Choose from these types:
1310 %
1311 % Bilevel Grayscale GrayscaleMatte
1312 % Palette PaletteMatte TrueColor
1313 % TrueColorMatte ColorSeparation ColorSeparationMatte
1314 % OptimizeType
1315 %
1316 % The format of the SetImageType method is:
1317 %
1318 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1319 % ExceptionInfo *exception)
1320 %
1321 % A description of each parameter follows:
1322 %
1323 % o image: the image.
1324 %
1325 % o type: Image type.
1326 %
1327 % o exception: return any errors or warnings in this structure.
1328 %
1329 */
1331  ExceptionInfo *exception)
1332 {
1333  const char
1334  *artifact;
1335 
1336  ImageInfo
1337  *image_info;
1338 
1340  status;
1341 
1342  QuantizeInfo
1343  *quantize_info;
1344 
1345  assert(image != (Image *) NULL);
1346  if (image->debug != MagickFalse)
1347  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1348  assert(image->signature == MagickCoreSignature);
1349  status=MagickTrue;
1350  image_info=AcquireImageInfo();
1351  image_info->dither=image->dither;
1352  artifact=GetImageArtifact(image,"dither");
1353  if (artifact != (const char *) NULL)
1354  (void) SetImageOption(image_info,"dither",artifact);
1355  switch (type)
1356  {
1357  case BilevelType:
1358  {
1359  status=TransformImageColorspace(image,GRAYColorspace,exception);
1360  (void) NormalizeImage(image,exception);
1361  quantize_info=AcquireQuantizeInfo(image_info);
1362  quantize_info->number_colors=2;
1363  quantize_info->colorspace=GRAYColorspace;
1364  status=QuantizeImage(quantize_info,image,exception);
1365  quantize_info=DestroyQuantizeInfo(quantize_info);
1367  break;
1368  }
1369  case GrayscaleType:
1370  {
1371  status=TransformImageColorspace(image,GRAYColorspace,exception);
1373  break;
1374  }
1375  case GrayscaleAlphaType:
1376  {
1377  status=TransformImageColorspace(image,GRAYColorspace,exception);
1378  if (image->alpha_trait == UndefinedPixelTrait)
1379  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1380  break;
1381  }
1382  case PaletteType:
1383  {
1384  status=TransformImageColorspace(image,sRGBColorspace,exception);
1385  if ((image->storage_class == DirectClass) || (image->colors > 256))
1386  {
1387  quantize_info=AcquireQuantizeInfo(image_info);
1388  quantize_info->number_colors=256;
1389  status=QuantizeImage(quantize_info,image,exception);
1390  quantize_info=DestroyQuantizeInfo(quantize_info);
1391  }
1393  break;
1394  }
1396  {
1397  ChannelType
1398  channel_mask;
1399 
1400  status=TransformImageColorspace(image,sRGBColorspace,exception);
1401  if (image->alpha_trait == UndefinedPixelTrait)
1402  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1403  channel_mask=SetImageChannelMask(image,AlphaChannel);
1404  (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1405  (void) SetImageChannelMask(image,channel_mask);
1406  quantize_info=AcquireQuantizeInfo(image_info);
1407  status=QuantizeImage(quantize_info,image,exception);
1408  quantize_info=DestroyQuantizeInfo(quantize_info);
1409  break;
1410  }
1411  case PaletteAlphaType:
1412  {
1413  status=TransformImageColorspace(image,sRGBColorspace,exception);
1414  if (image->alpha_trait == UndefinedPixelTrait)
1415  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1416  quantize_info=AcquireQuantizeInfo(image_info);
1417  quantize_info->colorspace=TransparentColorspace;
1418  status=QuantizeImage(quantize_info,image,exception);
1419  quantize_info=DestroyQuantizeInfo(quantize_info);
1420  break;
1421  }
1422  case TrueColorType:
1423  {
1424  status=TransformImageColorspace(image,sRGBColorspace,exception);
1425  if (image->storage_class != DirectClass)
1426  status=SetImageStorageClass(image,DirectClass,exception);
1428  break;
1429  }
1430  case TrueColorAlphaType:
1431  {
1432  status=TransformImageColorspace(image,sRGBColorspace,exception);
1433  if (image->storage_class != DirectClass)
1434  status=SetImageStorageClass(image,DirectClass,exception);
1435  if (image->alpha_trait == UndefinedPixelTrait)
1436  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1437  break;
1438  }
1439  case ColorSeparationType:
1440  {
1441  status=TransformImageColorspace(image,CMYKColorspace,exception);
1442  if (image->storage_class != DirectClass)
1443  status=SetImageStorageClass(image,DirectClass,exception);
1445  break;
1446  }
1448  {
1449  status=TransformImageColorspace(image,CMYKColorspace,exception);
1450  if (image->storage_class != DirectClass)
1451  status=SetImageStorageClass(image,DirectClass,exception);
1452  if (image->alpha_trait == UndefinedPixelTrait)
1453  status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1454  break;
1455  }
1456  case OptimizeType:
1457  case UndefinedType:
1458  break;
1459  }
1460  image_info=DestroyImageInfo(image_info);
1461  if (status == MagickFalse)
1462  return(status);
1463  image->type=type;
1464  return(MagickTrue);
1465 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickDoubleType MagickRealType
Definition: magick-type.h:120
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
double left
Definition: attribute.c:130
PixelInfo * colormap
Definition: image.h:179
static MagickSizeType GetQuantumRange(const size_t depth)
MagickExport ImageInfo * AcquireImageInfo(void)
Definition: image.c:344
ImageType type
Definition: image.h:264
static Quantum GetPixelAlpha(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
static PixelTrait GetPixelRedTraits(const Image *magick_restrict image)
double top
Definition: attribute.c:130
MagickExport MagickBooleanType TransformImageColorspace(Image *image, const ColorspaceType colorspace, ExceptionInfo *exception)
Definition: colorspace.c:1326
static PixelTrait GetPixelAlphaTraits(const Image *magick_restrict image)
ColorspaceType colorspace
Definition: quantize.h:44
MagickExport MagickBooleanType SetImageDepth(Image *image, const size_t depth, ExceptionInfo *exception)
Definition: attribute.c:1116
#define ThrowFatalException(severity, tag)
MagickExport ImageType IdentifyImageGray(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:757
MagickExport MagickStatusType ParseAbsoluteGeometry(const char *geometry, RectangleInfo *region_info)
Definition: geometry.c:703
#define OpaqueAlpha
Definition: image.h:25
MagickExport QuantizeInfo * DestroyQuantizeInfo(QuantizeInfo *quantize_info)
Definition: quantize.c:1384
MagickExport const char * GetImageArtifact(const Image *image, const char *artifact)
Definition: artifact.c:273
MagickRealType red
Definition: pixel.h:191
static double StringToDouble(const char *magick_restrict string, char **magick_restrict sentinal)
static PixelTrait GetPixelChannelTraits(const Image *magick_restrict image, const PixelChannel channel)
static MagickBooleanType IsPixelMonochrome(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
#define MAGICKCORE_QUANTUM_DEPTH
Definition: magick-type.h:28
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
MagickRealType alpha
Definition: pixel.h:191
MagickExport MagickBooleanType IdentifyImageMonochrome(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:839
#define MagickEpsilon
Definition: magick-type.h:110
ClassType storage_class
Definition: image.h:154
size_t width
Definition: geometry.h:130
Definition: log.h:52
MagickExport MagickBooleanType SetImageOption(ImageInfo *image_info, const char *option, const char *value)
Definition: option.c:3237
Definition: image.h:151
MagickExport Image * CropImage(const Image *image, const RectangleInfo *geometry, ExceptionInfo *exception)
Definition: transform.c:535
struct _EdgeInfo EdgeInfo
#define MagickCoreSignature
MagickExport MagickBooleanType SetImageType(Image *image, const ImageType type, ExceptionInfo *exception)
Definition: attribute.c:1330
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
static Quantum ClampPixel(const MagickRealType pixel)
MagickExport MagickBooleanType SetImageAlphaChannel(Image *image, const AlphaChannelOption alpha_type, ExceptionInfo *exception)
Definition: channel.c:974
MagickBooleanType
Definition: magick-type.h:158
static Quantum ScaleAnyToQuantum(const QuantumAny quantum, const QuantumAny range)
static MagickBooleanType IssRGBCompatibleColorspace(const ColorspaceType colorspace)
MagickExport MagickBooleanType NormalizeImage(Image *image, ExceptionInfo *exception)
Definition: enhance.c:4090
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:543
MagickExport ImageType GetImageType(const Image *image)
Definition: attribute.c:702
static int GetOpenMPThreadId(void)
static MagickBooleanType IsPixelAtDepth(const Quantum pixel, const QuantumAny range)
size_t number_colors
Definition: quantize.h:38
RectangleInfo page
Definition: image.h:212
static double GetEdgeBackgroundFactor(const Image *image, const CacheView *image_view, const GravityType gravity, const size_t width, const size_t height, const ssize_t x_offset, const ssize_t y_offset, ExceptionInfo *exception)
Definition: attribute.c:136
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:191
MagickExport MagickBooleanType IdentifyPaletteImage(const Image *image, ExceptionInfo *exception)
Definition: histogram.c:769
MagickExport ChannelType SetImageChannelMask(Image *image, const ChannelType channel_mask)
Definition: image.c:2500
double bottom
Definition: attribute.c:130
GravityType
Definition: geometry.h:77
MagickBooleanType dither
Definition: image.h:267
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1398
MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info, Image *image, ExceptionInfo *exception)
Definition: quantize.c:2648
size_t signature
Definition: image.h:354
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
Definition: resource.c:790
size_t columns
Definition: image.h:172
MagickExport size_t GetImageQuantumDepth(const Image *image, const MagickBooleanType constrain)
Definition: attribute.c:653
ssize_t x
Definition: geometry.h:134
static MagickBooleanType IsPixelGray(const Image *magick_restrict image, const Quantum *magick_restrict pixel)
double right
Definition: attribute.c:130
size_t height
Definition: geometry.h:130
MagickExport ImageType IdentifyImageType(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:920
static PixelTrait GetPixelGreenTraits(const Image *magick_restrict image)
ChannelType
Definition: pixel.h:33
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2616
PixelChannel
Definition: pixel.h:67
#define MaxMap
Definition: magick-type.h:75
#define MagickMax(x, y)
Definition: image-private.h:26
size_t colors
Definition: image.h:172
static size_t GetPixelChannels(const Image *magick_restrict image)
MagickExport MagickBooleanType IsPaletteImage(const Image *image)
Definition: histogram.c:840
MagickExport QuantizeInfo * AcquireQuantizeInfo(const ImageInfo *image_info)
Definition: quantize.c:375
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
static Quantum ClampToQuantum(const MagickRealType value)
Definition: quantum.h:84
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
MagickExport ImageInfo * DestroyImageInfo(ImageInfo *image_info)
Definition: image.c:1251
MagickExport MagickBooleanType IsImageGray(const Image *image)
Definition: attribute.c:975
MagickExport size_t GetImageDepth(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:404
unsigned short Quantum
Definition: magick-type.h:82
MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
Definition: attribute.c:1007
MagickExport RectangleInfo GetImageBoundingBox(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:240
static double GetMinEdgeBackgroundFactor(const EdgeInfo *edge)
Definition: attribute.c:230
MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p, const PixelInfo *q)
Definition: pixel.c:6061
MagickBooleanType dither
Definition: image.h:432
#define MagickMin(x, y)
Definition: image-private.h:27
MagickExport void SetGeometry(const Image *image, RectangleInfo *geometry)
Definition: geometry.c:1686
MagickExport MagickBooleanType BilevelImage(Image *image, const double threshold, ExceptionInfo *exception)
Definition: threshold.c:801
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1069
MagickRealType green
Definition: pixel.h:191
ImageType
Definition: image.h:48
MagickExport void GravityAdjustGeometry(const size_t width, const size_t height, const GravityType gravity, RectangleInfo *region)
Definition: geometry.c:531
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
ssize_t y
Definition: geometry.h:134
MagickExport CacheView * AcquireAuthenticCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:112
PixelTrait
Definition: pixel.h:135
static QuantumAny ScaleQuantumToAny(const Quantum quantum, const QuantumAny range)
MagickSizeType QuantumAny
Definition: magick-type.h:144
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1180
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:795
ColorspaceType colorspace
Definition: image.h:157
MagickExport MagickBooleanType IsImageOpaque(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:1044
#define QuantumRange
Definition: magick-type.h:83
MagickBooleanType debug
Definition: image.h:334
static PixelTrait GetPixelBlueTraits(const Image *magick_restrict image)
size_t depth
Definition: image.h:172