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 
381  ExceptionInfo *exception)
382 {
383  CacheView
384  *image_view;
385 
386  const char
387  *artifact;
388 
390  status;
391 
392  PixelInfo
393  target[3],
394  zero;
395 
397  bounds;
398 
399  register const Quantum
400  *p;
401 
402  ssize_t
403  y;
404 
405  assert(image != (Image *) NULL);
406  assert(image->signature == MagickCoreSignature);
407  if (image->debug != MagickFalse)
408  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
409  artifact=GetImageArtifact(image,"trim:percent-background");
410  if (artifact != (const char *) NULL)
411  return(GetEdgeBoundingBox(image,exception));
412  bounds.width=0;
413  bounds.height=0;
414  bounds.x=(ssize_t) image->columns;
415  bounds.y=(ssize_t) image->rows;
416  GetPixelInfo(image,&target[0]);
417  image_view=AcquireVirtualCacheView(image,exception);
418  p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
419  if (p == (const Quantum *) NULL)
420  {
421  image_view=DestroyCacheView(image_view);
422  return(bounds);
423  }
424  GetPixelInfoPixel(image,p,&target[0]);
425  GetPixelInfo(image,&target[1]);
426  p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
427  exception);
428  if (p != (const Quantum *) NULL)
429  GetPixelInfoPixel(image,p,&target[1]);
430  GetPixelInfo(image,&target[2]);
431  p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
432  exception);
433  if (p != (const Quantum *) NULL)
434  GetPixelInfoPixel(image,p,&target[2]);
435  status=MagickTrue;
436  GetPixelInfo(image,&zero);
437 #if defined(MAGICKCORE_OPENMP_SUPPORT)
438  #pragma omp parallel for schedule(static) shared(status) \
439  magick_number_threads(image,image,image->rows,1)
440 #endif
441  for (y=0; y < (ssize_t) image->rows; y++)
442  {
443  PixelInfo
444  pixel;
445 
447  bounding_box;
448 
449  register const Quantum
450  *magick_restrict p;
451 
452  register ssize_t
453  x;
454 
455  if (status == MagickFalse)
456  continue;
457 #if defined(MAGICKCORE_OPENMP_SUPPORT)
458 # pragma omp critical (MagickCore_GetImageBoundingBox)
459 #endif
460  bounding_box=bounds;
461  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
462  if (p == (const Quantum *) NULL)
463  {
464  status=MagickFalse;
465  continue;
466  }
467  pixel=zero;
468  for (x=0; x < (ssize_t) image->columns; x++)
469  {
470  GetPixelInfoPixel(image,p,&pixel);
471  if ((x < bounding_box.x) &&
472  (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
473  bounding_box.x=x;
474  if ((x > (ssize_t) bounding_box.width) &&
475  (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
476  bounding_box.width=(size_t) x;
477  if ((y < bounding_box.y) &&
478  (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
479  bounding_box.y=y;
480  if ((y > (ssize_t) bounding_box.height) &&
481  (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
482  bounding_box.height=(size_t) y;
483  p+=GetPixelChannels(image);
484  }
485 #if defined(MAGICKCORE_OPENMP_SUPPORT)
486 # pragma omp critical (MagickCore_GetImageBoundingBox)
487 #endif
488  {
489  if (bounding_box.x < bounds.x)
490  bounds.x=bounding_box.x;
491  if (bounding_box.y < bounds.y)
492  bounds.y=bounding_box.y;
493  if (bounding_box.width > bounds.width)
494  bounds.width=bounding_box.width;
495  if (bounding_box.height > bounds.height)
496  bounds.height=bounding_box.height;
497  }
498  }
499  image_view=DestroyCacheView(image_view);
500  if ((bounds.width == 0) || (bounds.height == 0))
502  "GeometryDoesNotContainImage","`%s'",image->filename);
503  else
504  {
505  bounds.width-=(bounds.x-1);
506  bounds.height-=(bounds.y-1);
507  }
508  return(bounds);
509 }
510 
511 /*
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 % %
514 % %
515 % %
516 % G e t I m a g e D e p t h %
517 % %
518 % %
519 % %
520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521 %
522 % GetImageDepth() returns the depth of a particular image channel.
523 %
524 % The format of the GetImageDepth method is:
525 %
526 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
527 %
528 % A description of each parameter follows:
529 %
530 % o image: the image.
531 %
532 % o exception: return any errors or warnings in this structure.
533 %
534 */
535 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
536 {
537  CacheView
538  *image_view;
539 
541  status;
542 
543  register ssize_t
544  i;
545 
546  size_t
547  *current_depth,
548  depth,
549  number_threads;
550 
551  ssize_t
552  y;
553 
554  /*
555  Compute image depth.
556  */
557  assert(image != (Image *) NULL);
558  assert(image->signature == MagickCoreSignature);
559  if (image->debug != MagickFalse)
560  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
561  number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
562  current_depth=(size_t *) AcquireQuantumMemory(number_threads,
563  sizeof(*current_depth));
564  if (current_depth == (size_t *) NULL)
565  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
566  status=MagickTrue;
567  for (i=0; i < (ssize_t) number_threads; i++)
568  current_depth[i]=1;
569  if ((image->storage_class == PseudoClass) &&
570  (image->alpha_trait == UndefinedPixelTrait))
571  {
572  for (i=0; i < (ssize_t) image->colors; i++)
573  {
574  const int
575  id = GetOpenMPThreadId();
576 
577  while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
578  {
580  atDepth;
581 
582  QuantumAny
583  range;
584 
585  atDepth=MagickTrue;
586  range=GetQuantumRange(current_depth[id]);
587  if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
588  if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].red),range) == MagickFalse)
589  atDepth=MagickFalse;
590  if ((atDepth != MagickFalse) &&
591  (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
592  if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].green),range) == MagickFalse)
593  atDepth=MagickFalse;
594  if ((atDepth != MagickFalse) &&
595  (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
596  if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].blue),range) == MagickFalse)
597  atDepth=MagickFalse;
598  if ((atDepth != MagickFalse))
599  break;
600  current_depth[id]++;
601  }
602  }
603  depth=current_depth[0];
604  for (i=1; i < (ssize_t) number_threads; i++)
605  if (depth < current_depth[i])
606  depth=current_depth[i];
607  current_depth=(size_t *) RelinquishMagickMemory(current_depth);
608  return(depth);
609  }
610  image_view=AcquireVirtualCacheView(image,exception);
611 #if !defined(MAGICKCORE_HDRI_SUPPORT)
612  if ((1UL*QuantumRange) <= MaxMap)
613  {
614  size_t
615  *depth_map;
616 
617  /*
618  Scale pixels to desired (optimized with depth map).
619  */
620  depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
621  if (depth_map == (size_t *) NULL)
622  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
623  for (i=0; i <= (ssize_t) MaxMap; i++)
624  {
625  unsigned int
626  depth;
627 
628  for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
629  {
630  Quantum
631  pixel;
632 
633  QuantumAny
634  range;
635 
636  range=GetQuantumRange(depth);
637  pixel=(Quantum) i;
638  if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
639  break;
640  }
641  depth_map[i]=depth;
642  }
643 #if defined(MAGICKCORE_OPENMP_SUPPORT)
644  #pragma omp parallel for schedule(static) shared(status) \
645  magick_number_threads(image,image,image->rows,1)
646 #endif
647  for (y=0; y < (ssize_t) image->rows; y++)
648  {
649  const int
650  id = GetOpenMPThreadId();
651 
652  register const Quantum
653  *magick_restrict p;
654 
655  register ssize_t
656  x;
657 
658  if (status == MagickFalse)
659  continue;
660  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
661  if (p == (const Quantum *) NULL)
662  continue;
663  for (x=0; x < (ssize_t) image->columns; x++)
664  {
665  register ssize_t
666  i;
667 
668  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
669  {
670  PixelChannel channel = GetPixelChannelChannel(image,i);
671  PixelTrait traits = GetPixelChannelTraits(image,channel);
672  if ((traits & UpdatePixelTrait) == 0)
673  continue;
674  if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
675  current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
676  }
677  p+=GetPixelChannels(image);
678  }
679  if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
680  status=MagickFalse;
681  }
682  image_view=DestroyCacheView(image_view);
683  depth=current_depth[0];
684  for (i=1; i < (ssize_t) number_threads; i++)
685  if (depth < current_depth[i])
686  depth=current_depth[i];
687  depth_map=(size_t *) RelinquishMagickMemory(depth_map);
688  current_depth=(size_t *) RelinquishMagickMemory(current_depth);
689  return(depth);
690  }
691 #endif
692  /*
693  Compute pixel depth.
694  */
695 #if defined(MAGICKCORE_OPENMP_SUPPORT)
696  #pragma omp parallel for schedule(static) shared(status) \
697  magick_number_threads(image,image,image->rows,1)
698 #endif
699  for (y=0; y < (ssize_t) image->rows; y++)
700  {
701  const int
702  id = GetOpenMPThreadId();
703 
704  register const Quantum
705  *magick_restrict p;
706 
707  register ssize_t
708  x;
709 
710  if (status == MagickFalse)
711  continue;
712  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
713  if (p == (const Quantum *) NULL)
714  continue;
715  for (x=0; x < (ssize_t) image->columns; x++)
716  {
717  register ssize_t
718  i;
719 
720  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
721  {
723  channel;
724 
725  PixelTrait
726  traits;
727 
728  channel=GetPixelChannelChannel(image,i);
729  traits=GetPixelChannelTraits(image,channel);
730  if ((traits & UpdatePixelTrait) == 0)
731  continue;
732  while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
733  {
734  QuantumAny
735  range;
736 
737  range=GetQuantumRange(current_depth[id]);
738  if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
739  break;
740  current_depth[id]++;
741  }
742  }
743  p+=GetPixelChannels(image);
744  }
745  if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
746  status=MagickFalse;
747  }
748  image_view=DestroyCacheView(image_view);
749  depth=current_depth[0];
750  for (i=1; i < (ssize_t) number_threads; i++)
751  if (depth < current_depth[i])
752  depth=current_depth[i];
753  current_depth=(size_t *) RelinquishMagickMemory(current_depth);
754  return(depth);
755 }
756 
757 /*
758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759 % %
760 % %
761 % %
762 % G e t I m a g e Q u a n t u m D e p t h %
763 % %
764 % %
765 % %
766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 %
768 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
769 % quantum depth: 8, 16, or 32.
770 %
771 % The format of the GetImageQuantumDepth method is:
772 %
773 % size_t GetImageQuantumDepth(const Image *image,
774 % const MagickBooleanType constrain)
775 %
776 % A description of each parameter follows:
777 %
778 % o image: the image.
779 %
780 % o constrain: A value other than MagickFalse, constrains the depth to
781 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
782 %
783 */
785  const MagickBooleanType constrain)
786 {
787  size_t
788  depth;
789 
790  depth=image->depth;
791  if (depth <= 8)
792  depth=8;
793  else
794  if (depth <= 16)
795  depth=16;
796  else
797  if (depth <= 32)
798  depth=32;
799  else
800  if (depth <= 64)
801  depth=64;
802  if (constrain != MagickFalse)
803  depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
804  return(depth);
805 }
806 
807 /*
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
809 % %
810 % %
811 % %
812 % G e t I m a g e T y p e %
813 % %
814 % %
815 % %
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %
818 % GetImageType() returns the type of image:
819 %
820 % Bilevel Grayscale GrayscaleMatte
821 % Palette PaletteMatte TrueColor
822 % TrueColorMatte ColorSeparation ColorSeparationMatte
823 %
824 % The format of the GetImageType method is:
825 %
826 % ImageType GetImageType(const Image *image)
827 %
828 % A description of each parameter follows:
829 %
830 % o image: the image.
831 %
832 */
834 {
835  assert(image != (Image *) NULL);
836  assert(image->signature == MagickCoreSignature);
837  if (image->colorspace == CMYKColorspace)
838  {
839  if (image->alpha_trait == UndefinedPixelTrait)
840  return(ColorSeparationType);
841  return(ColorSeparationAlphaType);
842  }
843  if (IsImageMonochrome(image) != MagickFalse)
844  return(BilevelType);
845  if (IsImageGray(image) != MagickFalse)
846  {
847  if (image->alpha_trait != UndefinedPixelTrait)
848  return(GrayscaleAlphaType);
849  return(GrayscaleType);
850  }
851  if (IsPaletteImage(image) != MagickFalse)
852  {
853  if (image->alpha_trait != UndefinedPixelTrait)
854  return(PaletteAlphaType);
855  return(PaletteType);
856  }
857  if (image->alpha_trait != UndefinedPixelTrait)
858  return(TrueColorAlphaType);
859  return(TrueColorType);
860 }
861 
862 /*
863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864 % %
865 % %
866 % %
867 % I d e n t i f y I m a g e G r a y %
868 % %
869 % %
870 % %
871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872 %
873 % IdentifyImageGray() returns grayscale if all the pixels in the image have
874 % the same red, green, and blue intensities, and bi-level is the intensity is
875 % either 0 or QuantumRange. Otherwise undefined is returned.
876 %
877 % The format of the IdentifyImageGray method is:
878 %
879 % ImageType IdentifyImageGray(const Image *image,ExceptionInfo *exception)
880 %
881 % A description of each parameter follows:
882 %
883 % o image: the image.
884 %
885 % o exception: return any errors or warnings in this structure.
886 %
887 */
889  ExceptionInfo *exception)
890 {
891  CacheView
892  *image_view;
893 
894  ImageType
895  type;
896 
897  register const Quantum
898  *p;
899 
900  register ssize_t
901  x;
902 
903  ssize_t
904  y;
905 
906  assert(image != (Image *) NULL);
907  assert(image->signature == MagickCoreSignature);
908  if (image->debug != MagickFalse)
909  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
910  if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
911  (image->type == GrayscaleAlphaType))
912  return(image->type);
914  return(UndefinedType);
915  type=BilevelType;
916  image_view=AcquireVirtualCacheView(image,exception);
917  for (y=0; y < (ssize_t) image->rows; y++)
918  {
919  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
920  if (p == (const Quantum *) NULL)
921  break;
922  for (x=0; x < (ssize_t) image->columns; x++)
923  {
924  if (IsPixelGray(image,p) == MagickFalse)
925  {
926  type=UndefinedType;
927  break;
928  }
929  if ((type == BilevelType) &&
930  (IsPixelMonochrome(image,p) == MagickFalse))
931  type=GrayscaleType;
932  p+=GetPixelChannels(image);
933  }
934  if (type == UndefinedType)
935  break;
936  }
937  image_view=DestroyCacheView(image_view);
938  if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
939  type=GrayscaleAlphaType;
940  return(type);
941 }
942 
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 % %
946 % %
947 % %
948 % I d e n t i f y I m a g e M o n o c h r o m e %
949 % %
950 % %
951 % %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 % IdentifyImageMonochrome() returns MagickTrue if all the pixels in the image
955 % have the same red, green, and blue intensities and the intensity is either
956 % 0 or QuantumRange.
957 %
958 % The format of the IdentifyImageMonochrome method is:
959 %
960 % MagickBooleanType IdentifyImageMonochrome(const Image *image,
961 % ExceptionInfo *exception)
962 %
963 % A description of each parameter follows:
964 %
965 % o image: the image.
966 %
967 % o exception: return any errors or warnings in this structure.
968 %
969 */
971  ExceptionInfo *exception)
972 {
973  CacheView
974  *image_view;
975 
977  bilevel;
978 
979  register ssize_t
980  x;
981 
982  register const Quantum
983  *p;
984 
985  ssize_t
986  y;
987 
988  assert(image != (Image *) NULL);
989  assert(image->signature == MagickCoreSignature);
990  if (image->debug != MagickFalse)
991  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
992  if (image->type == BilevelType)
993  return(MagickTrue);
995  return(MagickFalse);
996  bilevel=MagickTrue;
997  image_view=AcquireVirtualCacheView(image,exception);
998  for (y=0; y < (ssize_t) image->rows; y++)
999  {
1000  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1001  if (p == (const Quantum *) NULL)
1002  break;
1003  for (x=0; x < (ssize_t) image->columns; x++)
1004  {
1005  if (IsPixelMonochrome(image,p) == MagickFalse)
1006  {
1007  bilevel=MagickFalse;
1008  break;
1009  }
1010  p+=GetPixelChannels(image);
1011  }
1012  if (bilevel == MagickFalse)
1013  break;
1014  }
1015  image_view=DestroyCacheView(image_view);
1016  return(bilevel);
1017 }
1018 
1019 /*
1020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1021 % %
1022 % %
1023 % %
1024 % I d e n t i f y I m a g e T y p e %
1025 % %
1026 % %
1027 % %
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029 %
1030 % IdentifyImageType() returns the potential type of image:
1031 %
1032 % Bilevel Grayscale GrayscaleMatte
1033 % Palette PaletteMatte TrueColor
1034 % TrueColorMatte ColorSeparation ColorSeparationMatte
1035 %
1036 % To ensure the image type matches its potential, use SetImageType():
1037 %
1038 % (void) SetImageType(image,IdentifyImageType(image,exception),exception);
1039 %
1040 % The format of the IdentifyImageType method is:
1041 %
1042 % ImageType IdentifyImageType(const Image *image,ExceptionInfo *exception)
1043 %
1044 % A description of each parameter follows:
1045 %
1046 % o image: the image.
1047 %
1048 % o exception: return any errors or warnings in this structure.
1049 %
1050 */
1052  ExceptionInfo *exception)
1053 {
1054  assert(image != (Image *) NULL);
1055  assert(image->signature == MagickCoreSignature);
1056  if (image->debug != MagickFalse)
1057  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1058  if (image->colorspace == CMYKColorspace)
1059  {
1060  if (image->alpha_trait == UndefinedPixelTrait)
1061  return(ColorSeparationType);
1062  return(ColorSeparationAlphaType);
1063  }
1064  if (IdentifyImageMonochrome(image,exception) != MagickFalse)
1065  return(BilevelType);
1066  if (IdentifyImageGray(image,exception) != UndefinedType)
1067  {
1068  if (image->alpha_trait != UndefinedPixelTrait)
1069  return(GrayscaleAlphaType);
1070  return(GrayscaleType);
1071  }
1072  if (IdentifyPaletteImage(image,exception) != MagickFalse)
1073  {
1074  if (image->alpha_trait != UndefinedPixelTrait)
1075  return(PaletteAlphaType);
1076  return(PaletteType);
1077  }
1078  if (image->alpha_trait != UndefinedPixelTrait)
1079  return(TrueColorAlphaType);
1080  return(TrueColorType);
1081 }
1082 
1083 /*
1084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1085 % %
1086 % %
1087 % %
1088 % I s I m a g e G r a y %
1089 % %
1090 % %
1091 % %
1092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093 %
1094 % IsImageGray() returns MagickTrue if the type of the image is grayscale or
1095 % bi-level.
1096 %
1097 % The format of the IsImageGray method is:
1098 %
1099 % MagickBooleanType IsImageGray(const Image *image)
1100 %
1101 % A description of each parameter follows:
1102 %
1103 % o image: the image.
1104 %
1105 */
1107 {
1108  assert(image != (Image *) NULL);
1109  assert(image->signature == MagickCoreSignature);
1110  if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
1111  (image->type == GrayscaleAlphaType))
1112  return(MagickTrue);
1113  return(MagickFalse);
1114 }
1115 
1116 /*
1117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1118 % %
1119 % %
1120 % %
1121 % I s I m a g e M o n o c h r o m e %
1122 % %
1123 % %
1124 % %
1125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1126 %
1127 % IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
1128 %
1129 % The format of the IsImageMonochrome method is:
1130 %
1131 % MagickBooleanType IsImageMonochrome(const Image *image)
1132 %
1133 % A description of each parameter follows:
1134 %
1135 % o image: the image.
1136 %
1137 */
1139 {
1140  assert(image != (Image *) NULL);
1141  assert(image->signature == MagickCoreSignature);
1142  if (image->type == BilevelType)
1143  return(MagickTrue);
1144  return(MagickFalse);
1145 }
1146 
1147 /*
1148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1149 % %
1150 % %
1151 % %
1152 % I s I m a g e O p a q u e %
1153 % %
1154 % %
1155 % %
1156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 %
1158 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
1159 % an alpha value other than OpaqueAlpha (QuantumRange).
1160 %
1161 % Will return true immediatally is alpha channel is not available.
1162 %
1163 % The format of the IsImageOpaque method is:
1164 %
1165 % MagickBooleanType IsImageOpaque(const Image *image,
1166 % ExceptionInfo *exception)
1167 %
1168 % A description of each parameter follows:
1169 %
1170 % o image: the image.
1171 %
1172 % o exception: return any errors or warnings in this structure.
1173 %
1174 */
1176  ExceptionInfo *exception)
1177 {
1178  CacheView
1179  *image_view;
1180 
1181  register const Quantum
1182  *p;
1183 
1184  register ssize_t
1185  x;
1186 
1187  ssize_t
1188  y;
1189 
1190  /*
1191  Determine if image is opaque.
1192  */
1193  assert(image != (Image *) NULL);
1194  assert(image->signature == MagickCoreSignature);
1195  if (image->debug != MagickFalse)
1196  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1197  if (image->alpha_trait == UndefinedPixelTrait)
1198  return(MagickTrue);
1199  image_view=AcquireVirtualCacheView(image,exception);
1200  for (y=0; y < (ssize_t) image->rows; y++)
1201  {
1202  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1203  if (p == (const Quantum *) NULL)
1204  break;
1205  for (x=0; x < (ssize_t) image->columns; x++)
1206  {
1207  if (GetPixelAlpha(image,p) != OpaqueAlpha)
1208  break;
1209  p+=GetPixelChannels(image);
1210  }
1211  if (x < (ssize_t) image->columns)
1212  break;
1213  }
1214  image_view=DestroyCacheView(image_view);
1215  return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
1216 }
1217 
1218 /*
1219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 % %
1221 % %
1222 % %
1223 % S e t I m a g e D e p t h %
1224 % %
1225 % %
1226 % %
1227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1228 %
1229 % SetImageDepth() sets the depth of the image.
1230 %
1231 % The format of the SetImageDepth method is:
1232 %
1233 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
1234 % ExceptionInfo *exception)
1235 %
1236 % A description of each parameter follows:
1237 %
1238 % o image: the image.
1239 %
1240 % o channel: the channel.
1241 %
1242 % o depth: the image depth.
1243 %
1244 % o exception: return any errors or warnings in this structure.
1245 %
1246 */
1248  const size_t depth,ExceptionInfo *exception)
1249 {
1250  CacheView
1251  *image_view;
1252 
1254  status;
1255 
1256  QuantumAny
1257  range;
1258 
1259  ssize_t
1260  y;
1261 
1262  assert(image != (Image *) NULL);
1263  if (image->debug != MagickFalse)
1264  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1265  assert(image->signature == MagickCoreSignature);
1266  if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1267  {
1268  image->depth=depth;
1269  return(MagickTrue);
1270  }
1271  range=GetQuantumRange(depth);
1272  if (image->storage_class == PseudoClass)
1273  {
1274  register ssize_t
1275  i;
1276 
1277 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1278  #pragma omp parallel for schedule(static) shared(status) \
1279  magick_number_threads(image,image,image->colors,1)
1280 #endif
1281  for (i=0; i < (ssize_t) image->colors; i++)
1282  {
1283  if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
1284  image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1285  ClampPixel(image->colormap[i].red),range),range);
1286  if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
1288  ClampPixel(image->colormap[i].green),range),range);
1289  if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
1290  image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1291  ClampPixel(image->colormap[i].blue),range),range);
1292  if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
1294  ClampPixel(image->colormap[i].alpha),range),range);
1295  }
1296  }
1297  status=MagickTrue;
1298  image_view=AcquireAuthenticCacheView(image,exception);
1299 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1300  if ((1UL*QuantumRange) <= MaxMap)
1301  {
1302  Quantum
1303  *depth_map;
1304 
1305  register ssize_t
1306  i;
1307 
1308  /*
1309  Scale pixels to desired (optimized with depth map).
1310  */
1311  depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
1312  if (depth_map == (Quantum *) NULL)
1313  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1314  for (i=0; i <= (ssize_t) MaxMap; i++)
1315  depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1316  range);
1317 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1318  #pragma omp parallel for schedule(static) shared(status) \
1319  magick_number_threads(image,image,image->rows,1)
1320 #endif
1321  for (y=0; y < (ssize_t) image->rows; y++)
1322  {
1323  register ssize_t
1324  x;
1325 
1326  register Quantum
1327  *magick_restrict q;
1328 
1329  if (status == MagickFalse)
1330  continue;
1331  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1332  exception);
1333  if (q == (Quantum *) NULL)
1334  {
1335  status=MagickFalse;
1336  continue;
1337  }
1338  for (x=0; x < (ssize_t) image->columns; x++)
1339  {
1340  register ssize_t
1341  i;
1342 
1343  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1344  {
1345  PixelChannel
1346  channel;
1347 
1348  PixelTrait
1349  traits;
1350 
1351  channel=GetPixelChannelChannel(image,i);
1352  traits=GetPixelChannelTraits(image,channel);
1353  if ((traits & UpdatePixelTrait) == 0)
1354  continue;
1355  q[i]=depth_map[ScaleQuantumToMap(q[i])];
1356  }
1357  q+=GetPixelChannels(image);
1358  }
1359  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1360  {
1361  status=MagickFalse;
1362  continue;
1363  }
1364  }
1365  image_view=DestroyCacheView(image_view);
1366  depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1367  if (status != MagickFalse)
1368  image->depth=depth;
1369  return(status);
1370  }
1371 #endif
1372  /*
1373  Scale pixels to desired depth.
1374  */
1375 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1376  #pragma omp parallel for schedule(static) shared(status) \
1377  magick_number_threads(image,image,image->rows,1)
1378 #endif
1379  for (y=0; y < (ssize_t) image->rows; y++)
1380  {
1381  register ssize_t
1382  x;
1383 
1384  register Quantum
1385  *magick_restrict q;
1386 
1387  if (status == MagickFalse)
1388  continue;
1389  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1390  if (q == (Quantum *) NULL)
1391  {
1392  status=MagickFalse;
1393  continue;
1394  }
1395  for (x=0; x < (ssize_t) image->columns; x++)
1396  {
1397  register ssize_t
1398  i;
1399 
1400  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1401  {
1402  PixelChannel
1403  channel;
1404 
1405  PixelTrait
1406  traits;
1407 
1408  channel=GetPixelChannelChannel(image,i);
1409  traits=GetPixelChannelTraits(image,channel);
1410  if ((traits & UpdatePixelTrait) == 0)
1411  continue;
1413  q[i]),range),range);
1414  }
1415  q+=GetPixelChannels(image);
1416  }
1417  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1418  {
1419  status=MagickFalse;
1420  continue;
1421  }
1422  }
1423  image_view=DestroyCacheView(image_view);
1424  if (status != MagickFalse)
1425  image->depth=depth;
1426  return(status);
1427 }
1428 
1429 /*
1430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431 % %
1432 % %
1433 % %
1434 % S e t I m a g e T y p e %
1435 % %
1436 % %
1437 % %
1438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439 %
1440 % SetImageType() sets the type of image. Choose from these types:
1441 %
1442 % Bilevel Grayscale GrayscaleMatte
1443 % Palette PaletteMatte TrueColor
1444 % TrueColorMatte ColorSeparation ColorSeparationMatte
1445 % OptimizeType
1446 %
1447 % The format of the SetImageType method is:
1448 %
1449 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1450 % ExceptionInfo *exception)
1451 %
1452 % A description of each parameter follows:
1453 %
1454 % o image: the image.
1455 %
1456 % o type: Image type.
1457 %
1458 % o exception: return any errors or warnings in this structure.
1459 %
1460 */
1462  ExceptionInfo *exception)
1463 {
1464  const char
1465  *artifact;
1466 
1467  ImageInfo
1468  *image_info;
1469 
1471  status;
1472 
1473  QuantizeInfo
1474  *quantize_info;
1475 
1476  assert(image != (Image *) NULL);
1477  if (image->debug != MagickFalse)
1478  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1479  assert(image->signature == MagickCoreSignature);
1480  status=MagickTrue;
1481  image_info=AcquireImageInfo();
1482  image_info->dither=image->dither;
1483  artifact=GetImageArtifact(image,"dither");
1484  if (artifact != (const char *) NULL)
1485  (void) SetImageOption(image_info,"dither",artifact);
1486  switch (type)
1487  {
1488  case BilevelType:
1489  {
1490  status=TransformImageColorspace(image,GRAYColorspace,exception);
1491  (void) NormalizeImage(image,exception);
1492  quantize_info=AcquireQuantizeInfo(image_info);
1493  quantize_info->number_colors=2;
1494  quantize_info->colorspace=GRAYColorspace;
1495  quantize_info->dither_method=NoDitherMethod;
1496  status=QuantizeImage(quantize_info,image,exception);
1497  quantize_info=DestroyQuantizeInfo(quantize_info);
1499  break;
1500  }
1501  case GrayscaleType:
1502  {
1503  status=TransformImageColorspace(image,GRAYColorspace,exception);
1505  break;
1506  }
1507  case GrayscaleAlphaType:
1508  {
1509  status=TransformImageColorspace(image,GRAYColorspace,exception);
1510  if (image->alpha_trait == UndefinedPixelTrait)
1511  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1512  break;
1513  }
1514  case PaletteType:
1515  {
1516  status=TransformImageColorspace(image,sRGBColorspace,exception);
1517  if ((image->storage_class == DirectClass) || (image->colors > 256))
1518  {
1519  quantize_info=AcquireQuantizeInfo(image_info);
1520  quantize_info->number_colors=256;
1521  status=QuantizeImage(quantize_info,image,exception);
1522  quantize_info=DestroyQuantizeInfo(quantize_info);
1523  }
1525  break;
1526  }
1528  {
1529  ChannelType
1530  channel_mask;
1531 
1532  status=TransformImageColorspace(image,sRGBColorspace,exception);
1533  if (image->alpha_trait == UndefinedPixelTrait)
1534  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1535  channel_mask=SetImageChannelMask(image,AlphaChannel);
1536  (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1537  (void) SetImageChannelMask(image,channel_mask);
1538  quantize_info=AcquireQuantizeInfo(image_info);
1539  status=QuantizeImage(quantize_info,image,exception);
1540  quantize_info=DestroyQuantizeInfo(quantize_info);
1541  break;
1542  }
1543  case PaletteAlphaType:
1544  {
1545  status=TransformImageColorspace(image,sRGBColorspace,exception);
1546  if (image->alpha_trait == UndefinedPixelTrait)
1547  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1548  quantize_info=AcquireQuantizeInfo(image_info);
1549  quantize_info->colorspace=TransparentColorspace;
1550  status=QuantizeImage(quantize_info,image,exception);
1551  quantize_info=DestroyQuantizeInfo(quantize_info);
1552  break;
1553  }
1554  case TrueColorType:
1555  {
1556  status=TransformImageColorspace(image,sRGBColorspace,exception);
1557  if (image->storage_class != DirectClass)
1558  status=SetImageStorageClass(image,DirectClass,exception);
1560  break;
1561  }
1562  case TrueColorAlphaType:
1563  {
1564  status=TransformImageColorspace(image,sRGBColorspace,exception);
1565  if (image->storage_class != DirectClass)
1566  status=SetImageStorageClass(image,DirectClass,exception);
1567  if (image->alpha_trait == UndefinedPixelTrait)
1568  (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1569  break;
1570  }
1571  case ColorSeparationType:
1572  {
1573  status=TransformImageColorspace(image,CMYKColorspace,exception);
1574  if (image->storage_class != DirectClass)
1575  status=SetImageStorageClass(image,DirectClass,exception);
1577  break;
1578  }
1580  {
1581  status=TransformImageColorspace(image,CMYKColorspace,exception);
1582  if (image->storage_class != DirectClass)
1583  status=SetImageStorageClass(image,DirectClass,exception);
1584  if (image->alpha_trait == UndefinedPixelTrait)
1585  status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1586  break;
1587  }
1588  case OptimizeType:
1589  case UndefinedType:
1590  break;
1591  }
1592  image_info=DestroyImageInfo(image_info);
1593  if (status == MagickFalse)
1594  return(status);
1595  image->type=type;
1596  return(MagickTrue);
1597 }
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:345
static RectangleInfo GetEdgeBoundingBox(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:240
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:1247
#define ThrowFatalException(severity, tag)
MagickExport ImageType IdentifyImageGray(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:888
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:190
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:190
MagickExport MagickBooleanType IdentifyImageMonochrome(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:970
#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 void GetPixelInfo(const Image *image, PixelInfo *pixel)
Definition: pixel.c:2170
MagickExport MagickBooleanType SetImageOption(ImageInfo *image_info, const char *option, const char *value)
Definition: option.c:3238
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:1461
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:833
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:190
MagickExport MagickBooleanType IdentifyPaletteImage(const Image *image, ExceptionInfo *exception)
Definition: histogram.c:769
MagickExport ChannelType SetImageChannelMask(Image *image, const ChannelType channel_mask)
Definition: image.c:2499
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:1413
MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info, Image *image, ExceptionInfo *exception)
Definition: quantize.c:2644
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:784
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:1051
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:2615
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:1252
DitherMethod dither_method
Definition: quantize.h:47
MagickExport MagickBooleanType IsImageGray(const Image *image)
Definition: attribute.c:1106
MagickExport size_t GetImageDepth(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:535
unsigned short Quantum
Definition: magick-type.h:82
MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
Definition: attribute.c:1138
MagickExport RectangleInfo GetImageBoundingBox(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:380
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:1683
MagickExport MagickBooleanType BilevelImage(Image *image, const double threshold, ExceptionInfo *exception)
Definition: threshold.c:800
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1069
MagickRealType green
Definition: pixel.h:190
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:134
static QuantumAny ScaleQuantumToAny(const Quantum quantum, const QuantumAny range)
MagickSizeType QuantumAny
Definition: magick-type.h:144
MagickExport Image * DestroyImage(Image *image)
Definition: image.c:1181
MagickExport Image * CloneImage(const Image *image, const size_t columns, const size_t rows, const MagickBooleanType detach, ExceptionInfo *exception)
Definition: image.c:796
ColorspaceType colorspace
Definition: image.h:157
MagickExport MagickBooleanType IsImageOpaque(const Image *image, ExceptionInfo *exception)
Definition: attribute.c:1175
#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