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