2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % MagickCore Get / Set Image Attributes %
20 % Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/artifact.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/blob.h"
47 #include "MagickCore/blob-private.h"
48 #include "MagickCore/cache.h"
49 #include "MagickCore/cache-private.h"
50 #include "MagickCore/cache-view.h"
51 #include "MagickCore/channel.h"
52 #include "MagickCore/client.h"
53 #include "MagickCore/color.h"
54 #include "MagickCore/color-private.h"
55 #include "MagickCore/colormap.h"
56 #include "MagickCore/colormap-private.h"
57 #include "MagickCore/colorspace.h"
58 #include "MagickCore/colorspace-private.h"
59 #include "MagickCore/composite.h"
60 #include "MagickCore/composite-private.h"
61 #include "MagickCore/constitute.h"
62 #include "MagickCore/draw.h"
63 #include "MagickCore/draw-private.h"
64 #include "MagickCore/effect.h"
65 #include "MagickCore/enhance.h"
66 #include "MagickCore/exception.h"
67 #include "MagickCore/exception-private.h"
68 #include "MagickCore/geometry.h"
69 #include "MagickCore/histogram.h"
70 #include "MagickCore/identify.h"
71 #include "MagickCore/image.h"
72 #include "MagickCore/image-private.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"
78 #include "MagickCore/monitor-private.h"
79 #include "MagickCore/option.h"
80 #include "MagickCore/paint.h"
81 #include "MagickCore/pixel.h"
82 #include "MagickCore/pixel-accessor.h"
83 #include "MagickCore/property.h"
84 #include "MagickCore/quantize.h"
85 #include "MagickCore/quantum-private.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"
92 #include "MagickCore/thread-private.h"
93 #include "MagickCore/threshold.h"
94 #include "MagickCore/transform.h"
95 #include "MagickCore/utility.h"
98 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 + G e t I m a g e B o u n d i n g B o x %
106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 % GetImageBoundingBox() returns the bounding box of an image canvas.
110 % The format of the GetImageBoundingBox method is:
112 % RectangleInfo GetImageBoundingBox(const Image *image,
113 % ExceptionInfo *exception)
115 % A description of each parameter follows:
117 % o bounds: Method GetImageBoundingBox returns the bounding box of an
120 % o image: the image.
122 % o exception: return any errors or warnings in this structure.
125 MagickExport RectangleInfo GetImageBoundingBox(const Image *image,
126 ExceptionInfo *exception)
141 register const Quantum
147 assert(image != (Image *) NULL);
148 assert(image->signature == MagickSignature);
149 if (image->debug != MagickFalse)
150 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
153 bounds.x=(ssize_t) image->columns;
154 bounds.y=(ssize_t) image->rows;
155 GetPixelInfo(image,&target[0]);
156 image_view=AcquireVirtualCacheView(image,exception);
157 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
158 if (p == (const Quantum *) NULL)
160 image_view=DestroyCacheView(image_view);
163 GetPixelInfoPixel(image,p,&target[0]);
164 GetPixelInfo(image,&target[1]);
165 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
167 if (p != (const Quantum *) NULL)
168 GetPixelInfoPixel(image,p,&target[1]);
169 GetPixelInfo(image,&target[2]);
170 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
172 if (p != (const Quantum *) NULL)
173 GetPixelInfoPixel(image,p,&target[2]);
175 GetPixelInfo(image,&zero);
176 #if defined(MAGICKCORE_OPENMP_SUPPORT)
177 #pragma omp parallel for schedule(static,4) shared(status) \
178 magick_threads(image,image,image->rows,1)
180 for (y=0; y < (ssize_t) image->rows; y++)
188 register const Quantum
194 if (status == MagickFalse)
196 #if defined(MAGICKCORE_OPENMP_SUPPORT)
197 # pragma omp critical (MagickCore_GetImageBoundingBox)
200 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
201 if (p == (const Quantum *) NULL)
207 for (x=0; x < (ssize_t) image->columns; x++)
209 GetPixelInfoPixel(image,p,&pixel);
210 if ((x < bounding_box.x) &&
211 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
213 if ((x > (ssize_t) bounding_box.width) &&
214 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
215 bounding_box.width=(size_t) x;
216 if ((y < bounding_box.y) &&
217 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
219 if ((y > (ssize_t) bounding_box.height) &&
220 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
221 bounding_box.height=(size_t) y;
222 p+=GetPixelChannels(image);
224 #if defined(MAGICKCORE_OPENMP_SUPPORT)
225 # pragma omp critical (MagickCore_GetImageBoundingBox)
228 if (bounding_box.x < bounds.x)
229 bounds.x=bounding_box.x;
230 if (bounding_box.y < bounds.y)
231 bounds.y=bounding_box.y;
232 if (bounding_box.width > bounds.width)
233 bounds.width=bounding_box.width;
234 if (bounding_box.height > bounds.height)
235 bounds.height=bounding_box.height;
238 image_view=DestroyCacheView(image_view);
239 if ((bounds.width == 0) && (bounds.height == 0))
240 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
241 "GeometryDoesNotContainImage","`%s'",image->filename);
244 bounds.width-=(bounds.x-1);
245 bounds.height-=(bounds.y-1);
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 % G e t I m a g e D e p t h %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 % GetImageDepth() returns the depth of a particular image channel.
263 % The format of the GetImageDepth method is:
265 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
267 % A description of each parameter follows:
269 % o image: the image.
271 % o exception: return any errors or warnings in this structure.
274 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
296 assert(image != (Image *) NULL);
297 assert(image->signature == MagickSignature);
298 if (image->debug != MagickFalse)
299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
300 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
301 current_depth=(size_t *) AcquireQuantumMemory(number_threads,
302 sizeof(*current_depth));
303 if (current_depth == (size_t *) NULL)
304 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
306 for (i=0; i < (ssize_t) number_threads; i++)
308 if ((image->storage_class == PseudoClass) &&
309 (image->alpha_trait == UndefinedPixelTrait))
311 #if defined(MAGICKCORE_OPENMP_SUPPORT)
312 #pragma omp parallel for schedule(static,4) shared(status) \
313 if ((image->colors) > 256) \
314 num_threads(GetMagickResourceLimit(ThreadResource))
316 for (i=0; i < (ssize_t) image->colors; i++)
319 id = GetOpenMPThreadId();
321 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
330 range=GetQuantumRange(current_depth[id]);
331 if ((atDepth != MagickFalse) &&
332 (GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
333 if (IsPixelAtDepth(image->colormap[i].red,range) == MagickFalse)
335 if ((atDepth != MagickFalse) &&
336 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
337 if (IsPixelAtDepth(image->colormap[i].green,range) == MagickFalse)
339 if ((atDepth != MagickFalse) &&
340 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
341 if (IsPixelAtDepth(image->colormap[i].blue,range) == MagickFalse)
343 if ((atDepth != MagickFalse))
348 depth=current_depth[0];
349 for (i=1; i < (ssize_t) number_threads; i++)
350 if (depth < current_depth[i])
351 depth=current_depth[i];
352 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
355 image_view=AcquireVirtualCacheView(image,exception);
356 #if !defined(MAGICKCORE_HDRI_SUPPORT)
357 if (QuantumRange <= MaxMap)
363 Scale pixels to desired (optimized with depth map).
365 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
366 if (depth_map == (size_t *) NULL)
367 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
368 for (i=0; i <= (ssize_t) MaxMap; i++)
373 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
381 range=GetQuantumRange(depth);
383 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
388 #if defined(MAGICKCORE_OPENMP_SUPPORT)
389 #pragma omp parallel for schedule(static,4) shared(status) \
390 magick_threads(image,image,image->rows,1)
392 for (y=0; y < (ssize_t) image->rows; y++)
395 id = GetOpenMPThreadId();
397 register const Quantum
403 if (status == MagickFalse)
405 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
406 if (p == (const Quantum *) NULL)
408 for (x=0; x < (ssize_t) image->columns; x++)
410 if (GetPixelReadMask(image,p) == 0)
412 p+=GetPixelChannels(image);
415 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
417 PixelChannel channel=GetPixelChannelChannel(image,i);
418 PixelTrait traits=GetPixelChannelTraits(image,channel);
419 if ((traits == UndefinedPixelTrait) ||
420 (channel == IndexPixelChannel) ||
421 (channel == ReadMaskPixelChannel) ||
422 (channel == MetaPixelChannel))
424 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
425 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
427 p+=GetPixelChannels(image);
429 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
432 image_view=DestroyCacheView(image_view);
433 depth=current_depth[0];
434 for (i=1; i < (ssize_t) number_threads; i++)
435 if (depth < current_depth[i])
436 depth=current_depth[i];
437 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
438 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
445 #if defined(MAGICKCORE_OPENMP_SUPPORT)
446 #pragma omp parallel for schedule(static,4) shared(status) \
447 magick_threads(image,image,image->rows,1)
449 for (y=0; y < (ssize_t) image->rows; y++)
452 id = GetOpenMPThreadId();
454 register const Quantum
460 if (status == MagickFalse)
462 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
463 if (p == (const Quantum *) NULL)
465 for (x=0; x < (ssize_t) image->columns; x++)
467 if (GetPixelReadMask(image,p) == 0)
469 p+=GetPixelChannels(image);
472 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
480 channel=GetPixelChannelChannel(image,i);
481 traits=GetPixelChannelTraits(image,channel);
482 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
483 (channel == ReadMaskPixelChannel))
485 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
490 range=GetQuantumRange(current_depth[id]);
491 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
496 p+=GetPixelChannels(image);
498 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
501 image_view=DestroyCacheView(image_view);
502 depth=current_depth[0];
503 for (i=1; i < (ssize_t) number_threads; i++)
504 if (depth < current_depth[i])
505 depth=current_depth[i];
506 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 % G e t I m a g e Q u a n t u m D e p t h %
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
522 % quantum depth: 8, 16, or 32.
524 % The format of the GetImageQuantumDepth method is:
526 % size_t GetImageQuantumDepth(const Image *image,
527 % const MagickBooleanType constrain)
529 % A description of each parameter follows:
531 % o image: the image.
533 % o constrain: A value other than MagickFalse, constrains the depth to
534 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
537 MagickExport size_t GetImageQuantumDepth(const Image *image,
538 const MagickBooleanType constrain)
555 if (constrain != MagickFalse)
556 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 % G e t I m a g e T y p e %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 % GetImageType() returns the potential type of image:
573 % Bilevel Grayscale GrayscaleMatte
574 % Palette PaletteMatte TrueColor
575 % TrueColorMatte ColorSeparation ColorSeparationMatte
577 % To ensure the image type matches its potential, use SetImageType():
579 % (void) SetImageType(image,GetImageType(image));
581 % The format of the GetImageType method is:
583 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
585 % A description of each parameter follows:
587 % o image: the image.
589 % o exception: return any errors or warnings in this structure.
592 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
594 assert(image != (Image *) NULL);
595 assert(image->signature == MagickSignature);
596 if (image->debug != MagickFalse)
597 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
598 if (image->colorspace == CMYKColorspace)
600 if (image->alpha_trait == UndefinedPixelTrait)
601 return(ColorSeparationType);
602 return(ColorSeparationAlphaType);
604 if (SetImageMonochrome((Image *) image,exception) != MagickFalse)
606 if (SetImageGray((Image *) image,exception) != MagickFalse)
608 if (image->alpha_trait != UndefinedPixelTrait)
609 return(GrayscaleAlphaType);
610 return(GrayscaleType);
612 if (IsPaletteImage(image,exception) != MagickFalse)
614 if (image->alpha_trait != UndefinedPixelTrait)
615 return(PaletteAlphaType);
618 if (image->alpha_trait != UndefinedPixelTrait)
619 return(TrueColorAlphaType);
620 return(TrueColorType);
624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628 % I s I m a g e G r a y %
632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634 % IsImageGray() returns MagickTrue if the type of the image is grayscale or
637 % The format of the IsImageGray method is:
639 % MagickBooleanType IsImageGray(const Image *image)
641 % A description of each parameter follows:
643 % o image: the image.
646 MagickExport MagickBooleanType IsImageGray(const Image *image)
648 assert(image != (Image *) NULL);
649 assert(image->signature == MagickSignature);
650 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
651 (image->type == GrayscaleAlphaType))
657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661 % I s I m a g e M o n o c h r o m e %
665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 % IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
669 % The format of the IsImageMonochrome method is:
671 % MagickBooleanType IsImageMonochrome(const Image *image)
673 % A description of each parameter follows:
675 % o image: the image.
678 MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
680 assert(image != (Image *) NULL);
681 assert(image->signature == MagickSignature);
682 if (image->type == BilevelType)
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 % I s I m a g e O p a q u e %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
699 % an alpha value other than OpaqueAlpha (QuantumRange).
701 % Will return true immediatally is alpha channel is not available.
703 % The format of the IsImageOpaque method is:
705 % MagickBooleanType IsImageOpaque(const Image *image,
706 % ExceptionInfo *exception)
708 % A description of each parameter follows:
710 % o image: the image.
712 % o exception: return any errors or warnings in this structure.
715 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
716 ExceptionInfo *exception)
721 register const Quantum
731 Determine if image is opaque.
733 assert(image != (Image *) NULL);
734 assert(image->signature == MagickSignature);
735 if (image->debug != MagickFalse)
736 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
737 if (image->alpha_trait == UndefinedPixelTrait)
739 image_view=AcquireVirtualCacheView(image,exception);
740 for (y=0; y < (ssize_t) image->rows; y++)
742 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
743 if (p == (const Quantum *) NULL)
745 for (x=0; x < (ssize_t) image->columns; x++)
747 if (GetPixelAlpha(image,p) != OpaqueAlpha)
749 p+=GetPixelChannels(image);
751 if (x < (ssize_t) image->columns)
754 image_view=DestroyCacheView(image_view);
755 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763 % S e t I m a g e D e p t h %
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
769 % SetImageDepth() sets the depth of the image.
771 % The format of the SetImageDepth method is:
773 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
774 % ExceptionInfo *exception)
776 % A description of each parameter follows:
778 % o image: the image.
780 % o channel: the channel.
782 % o depth: the image depth.
784 % o exception: return any errors or warnings in this structure.
787 MagickExport MagickBooleanType SetImageDepth(Image *image,
788 const size_t depth,ExceptionInfo *exception)
802 assert(image != (Image *) NULL);
803 if (image->debug != MagickFalse)
804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
805 assert(image->signature == MagickSignature);
806 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
811 range=GetQuantumRange(depth);
812 if (image->storage_class == PseudoClass)
817 #if defined(MAGICKCORE_OPENMP_SUPPORT)
818 #pragma omp parallel for schedule(static,4) shared(status) \
819 magick_threads(image,image,1,1)
821 for (i=0; i < (ssize_t) image->colors; i++)
823 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
824 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
825 ClampPixel(image->colormap[i].red),range),range);
826 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
827 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
828 ClampPixel(image->colormap[i].green),range),range);
829 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
830 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
831 ClampPixel(image->colormap[i].blue),range),range);
832 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
833 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
834 ClampPixel(image->colormap[i].alpha),range),range);
838 image_view=AcquireAuthenticCacheView(image,exception);
839 #if !defined(MAGICKCORE_HDRI_SUPPORT)
840 if (QuantumRange <= MaxMap)
849 Scale pixels to desired (optimized with depth map).
851 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
852 if (depth_map == (Quantum *) NULL)
853 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
854 for (i=0; i <= (ssize_t) MaxMap; i++)
855 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
857 #if defined(MAGICKCORE_OPENMP_SUPPORT)
858 #pragma omp parallel for schedule(static,4) shared(status) \
859 magick_threads(image,image,image->rows,1)
861 for (y=0; y < (ssize_t) image->rows; y++)
869 if (status == MagickFalse)
871 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
873 if (q == (Quantum *) NULL)
878 for (x=0; x < (ssize_t) image->columns; x++)
883 if (GetPixelReadMask(image,q) == 0)
885 q+=GetPixelChannels(image);
888 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
896 channel=GetPixelChannelChannel(image,i);
897 traits=GetPixelChannelTraits(image,channel);
898 if ((traits == UndefinedPixelTrait) ||
899 (channel == IndexPixelChannel) ||
900 (channel == ReadMaskPixelChannel))
902 q[i]=depth_map[ScaleQuantumToMap(q[i])];
904 q+=GetPixelChannels(image);
906 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
912 image_view=DestroyCacheView(image_view);
913 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
914 if (status != MagickFalse)
920 Scale pixels to desired depth.
922 #if defined(MAGICKCORE_OPENMP_SUPPORT)
923 #pragma omp parallel for schedule(static,4) shared(status) \
924 magick_threads(image,image,image->rows,1)
926 for (y=0; y < (ssize_t) image->rows; y++)
934 if (status == MagickFalse)
936 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
937 if (q == (Quantum *) NULL)
942 for (x=0; x < (ssize_t) image->columns; x++)
947 if (GetPixelReadMask(image,q) == 0)
949 q+=GetPixelChannels(image);
952 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
960 channel=GetPixelChannelChannel(image,i);
961 traits=GetPixelChannelTraits(image,channel);
962 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
963 (channel == ReadMaskPixelChannel))
965 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(q[i]),range),range);
967 q+=GetPixelChannels(image);
969 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
975 image_view=DestroyCacheView(image_view);
976 if (status != MagickFalse)
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986 % S e t I m a g e G r a y %
990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 % SetImageGray() returns MagickTrue if all the pixels in the image have the
993 % same red, green, and blue intensities and changes the type of the image to
994 % bi-level or grayscale.
996 % The format of the SetImageGray method is:
998 % MagickBooleanType SetImageGray(const Image *image,
999 % ExceptionInfo *exception)
1001 % A description of each parameter follows:
1003 % o image: the image.
1005 % o exception: return any errors or warnings in this structure.
1008 MagickExport MagickBooleanType SetImageGray(Image *image,
1009 ExceptionInfo *exception)
1017 register const Quantum
1026 assert(image != (Image *) NULL);
1027 assert(image->signature == MagickSignature);
1028 if (image->debug != MagickFalse)
1029 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1030 if (IsImageGray(image))
1032 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
1033 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1034 return(MagickFalse);
1036 image_view=AcquireVirtualCacheView(image,exception);
1037 for (y=0; y < (ssize_t) image->rows; y++)
1039 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1040 if (p == (const Quantum *) NULL)
1042 for (x=0; x < (ssize_t) image->columns; x++)
1044 if (IsPixelGray(image,p) == MagickFalse)
1049 if ((type == BilevelType) &&
1050 (IsPixelMonochrome(image,p) == MagickFalse))
1052 p+=GetPixelChannels(image);
1054 if (type == UndefinedType)
1057 image_view=DestroyCacheView(image_view);
1058 if (type == UndefinedType)
1059 return(MagickFalse);
1060 image->colorspace=GRAYColorspace;
1061 if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
1062 return(MagickFalse);
1064 if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
1065 image->type=GrayscaleAlphaType;
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1074 % S e t I m a g e M o n o c h r o m e %
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1080 % SetImageMonochrome() returns MagickTrue if all the pixels in the image have
1081 % the same red, green, and blue intensities and the intensity is either
1082 % 0 or QuantumRange and changes the type of the image to bi-level.
1084 % The format of the SetImageMonochrome method is:
1086 % MagickBooleanType SetImageMonochrome(const Image *image,
1087 % ExceptionInfo *exception)
1089 % A description of each parameter follows:
1091 % o image: the image.
1093 % o exception: return any errors or warnings in this structure.
1096 MagickExport MagickBooleanType SetImageMonochrome(Image *image,
1097 ExceptionInfo *exception)
1108 register const Quantum
1114 assert(image != (Image *) NULL);
1115 assert(image->signature == MagickSignature);
1116 if (image->debug != MagickFalse)
1117 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1118 if (image->type == BilevelType)
1120 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
1121 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1122 return(MagickFalse);
1124 image_view=AcquireVirtualCacheView(image,exception);
1125 for (y=0; y < (ssize_t) image->rows; y++)
1127 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1128 if (p == (const Quantum *) NULL)
1130 for (x=0; x < (ssize_t) image->columns; x++)
1132 if (IsPixelMonochrome(image,p) == MagickFalse)
1137 p+=GetPixelChannels(image);
1139 if (type == UndefinedType)
1142 image_view=DestroyCacheView(image_view);
1143 if (type == UndefinedType)
1144 return(MagickFalse);
1145 image->colorspace=GRAYColorspace;
1146 if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
1147 return(MagickFalse);
1153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 % S e t I m a g e T y p e %
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 % SetImageType() sets the type of image. Choose from these types:
1165 % Bilevel Grayscale GrayscaleMatte
1166 % Palette PaletteMatte TrueColor
1167 % TrueColorMatte ColorSeparation ColorSeparationMatte
1170 % The format of the SetImageType method is:
1172 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1173 % ExceptionInfo *exception)
1175 % A description of each parameter follows:
1177 % o image: the image.
1179 % o type: Image type.
1181 % o exception: return any errors or warnings in this structure.
1184 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1185 ExceptionInfo *exception)
1199 assert(image != (Image *) NULL);
1200 if (image->debug != MagickFalse)
1201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1202 assert(image->signature == MagickSignature);
1204 image_info=AcquireImageInfo();
1205 image_info->dither=image->dither;
1206 artifact=GetImageArtifact(image,"dither");
1207 if (artifact != (const char *) NULL)
1208 (void) SetImageOption(image_info,"dither",artifact);
1213 if (SetImageGray(image,exception) == MagickFalse)
1214 status=TransformImageColorspace(image,GRAYColorspace,exception);
1215 (void) NormalizeImage(image,exception);
1216 if (SetImageMonochrome(image,exception) == MagickFalse)
1218 quantize_info=AcquireQuantizeInfo(image_info);
1219 quantize_info->number_colors=2;
1220 quantize_info->colorspace=GRAYColorspace;
1221 status=QuantizeImage(quantize_info,image,exception);
1222 quantize_info=DestroyQuantizeInfo(quantize_info);
1225 image->alpha_trait=UndefinedPixelTrait;
1230 if (SetImageGray(image,exception) == MagickFalse)
1231 status=TransformImageColorspace(image,GRAYColorspace,exception);
1232 image->alpha_trait=UndefinedPixelTrait;
1235 case GrayscaleAlphaType:
1237 if (SetImageGray(image,exception) == MagickFalse)
1238 status=TransformImageColorspace(image,GRAYColorspace,exception);
1239 if (image->alpha_trait == UndefinedPixelTrait)
1240 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1245 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1246 status=TransformImageColorspace(image,sRGBColorspace,exception);
1247 if ((image->storage_class == DirectClass) || (image->colors > 256))
1249 quantize_info=AcquireQuantizeInfo(image_info);
1250 quantize_info->number_colors=256;
1251 status=QuantizeImage(quantize_info,image,exception);
1252 quantize_info=DestroyQuantizeInfo(quantize_info);
1254 image->alpha_trait=UndefinedPixelTrait;
1257 case PaletteBilevelAlphaType:
1262 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1263 status=TransformImageColorspace(image,sRGBColorspace,exception);
1264 if (image->alpha_trait == UndefinedPixelTrait)
1265 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1266 channel_mask=SetImageChannelMask(image,AlphaChannel);
1267 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1268 (void) SetImageChannelMask(image,channel_mask);
1269 quantize_info=AcquireQuantizeInfo(image_info);
1270 status=QuantizeImage(quantize_info,image,exception);
1271 quantize_info=DestroyQuantizeInfo(quantize_info);
1274 case PaletteAlphaType:
1276 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1277 status=TransformImageColorspace(image,sRGBColorspace,exception);
1278 if (image->alpha_trait == UndefinedPixelTrait)
1279 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1280 quantize_info=AcquireQuantizeInfo(image_info);
1281 quantize_info->colorspace=TransparentColorspace;
1282 status=QuantizeImage(quantize_info,image,exception);
1283 quantize_info=DestroyQuantizeInfo(quantize_info);
1288 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1289 status=TransformImageColorspace(image,sRGBColorspace,exception);
1290 if (image->storage_class != DirectClass)
1291 status=SetImageStorageClass(image,DirectClass,exception);
1292 image->alpha_trait=UndefinedPixelTrait;
1295 case TrueColorAlphaType:
1297 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1298 status=TransformImageColorspace(image,sRGBColorspace,exception);
1299 if (image->storage_class != DirectClass)
1300 status=SetImageStorageClass(image,DirectClass,exception);
1301 if (image->alpha_trait == UndefinedPixelTrait)
1302 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1305 case ColorSeparationType:
1307 if (image->colorspace != CMYKColorspace)
1309 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1310 status=TransformImageColorspace(image,sRGBColorspace,exception);
1311 status=TransformImageColorspace(image,CMYKColorspace,exception);
1313 if (image->storage_class != DirectClass)
1314 status=SetImageStorageClass(image,DirectClass,exception);
1315 image->alpha_trait=UndefinedPixelTrait;
1318 case ColorSeparationAlphaType:
1320 if (image->colorspace != CMYKColorspace)
1322 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1323 status=TransformImageColorspace(image,sRGBColorspace,exception);
1324 status=TransformImageColorspace(image,CMYKColorspace,exception);
1326 if (image->storage_class != DirectClass)
1327 status=SetImageStorageClass(image,DirectClass,exception);
1328 if (image->alpha_trait == UndefinedPixelTrait)
1329 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1336 image_info=DestroyImageInfo(image_info);
1337 if (status == MagickFalse)