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-2018 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 % https://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 == MagickCoreSignature);
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 r=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
158 if (r == (const Quantum *) NULL)
160 image_view=DestroyCacheView(image_view);
163 GetPixelInfoPixel(image,r,&target[0]);
164 GetPixelInfo(image,&target[1]);
165 r=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
167 if (r != (const Quantum *) NULL)
168 GetPixelInfoPixel(image,r,&target[1]);
169 GetPixelInfo(image,&target[2]);
170 r=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
172 if (r != (const Quantum *) NULL)
173 GetPixelInfoPixel(image,r,&target[2]);
175 GetPixelInfo(image,&zero);
176 #if defined(MAGICKCORE_OPENMP_SUPPORT)
177 #pragma omp parallel for schedule(static) shared(status) \
178 magick_number_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 == MagickCoreSignature);
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 for (i=0; i < (ssize_t) image->colors; i++)
314 id = GetOpenMPThreadId();
316 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
325 range=GetQuantumRange(current_depth[id]);
326 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
327 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].red),range) == MagickFalse)
329 if ((atDepth != MagickFalse) &&
330 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
331 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].green),range) == MagickFalse)
333 if ((atDepth != MagickFalse) &&
334 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
335 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].blue),range) == MagickFalse)
337 if ((atDepth != MagickFalse))
342 depth=current_depth[0];
343 for (i=1; i < (ssize_t) number_threads; i++)
344 if (depth < current_depth[i])
345 depth=current_depth[i];
346 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
349 image_view=AcquireVirtualCacheView(image,exception);
350 #if !defined(MAGICKCORE_HDRI_SUPPORT)
351 if ((1UL*QuantumRange) <= MaxMap)
357 Scale pixels to desired (optimized with depth map).
359 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
360 if (depth_map == (size_t *) NULL)
361 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
362 for (i=0; i <= (ssize_t) MaxMap; i++)
367 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
375 range=GetQuantumRange(depth);
377 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
382 #if defined(MAGICKCORE_OPENMP_SUPPORT)
383 #pragma omp parallel for schedule(static) shared(status) \
384 magick_number_threads(image,image,image->rows,1)
386 for (y=0; y < (ssize_t) image->rows; y++)
389 id = GetOpenMPThreadId();
391 register const Quantum
397 if (status == MagickFalse)
399 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
400 if (p == (const Quantum *) NULL)
402 for (x=0; x < (ssize_t) image->columns; x++)
407 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
409 PixelChannel channel = GetPixelChannelChannel(image,i);
410 PixelTrait traits = GetPixelChannelTraits(image,channel);
411 if ((traits & UpdatePixelTrait) == 0)
413 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
414 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
416 p+=GetPixelChannels(image);
418 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
421 image_view=DestroyCacheView(image_view);
422 depth=current_depth[0];
423 for (i=1; i < (ssize_t) number_threads; i++)
424 if (depth < current_depth[i])
425 depth=current_depth[i];
426 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
427 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
434 #if defined(MAGICKCORE_OPENMP_SUPPORT)
435 #pragma omp parallel for schedule(static) shared(status) \
436 magick_number_threads(image,image,image->rows,1)
438 for (y=0; y < (ssize_t) image->rows; y++)
441 id = GetOpenMPThreadId();
443 register const Quantum
449 if (status == MagickFalse)
451 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
452 if (p == (const Quantum *) NULL)
454 for (x=0; x < (ssize_t) image->columns; x++)
459 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
467 channel=GetPixelChannelChannel(image,i);
468 traits=GetPixelChannelTraits(image,channel);
469 if ((traits & UpdatePixelTrait) == 0)
471 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
476 range=GetQuantumRange(current_depth[id]);
477 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
482 p+=GetPixelChannels(image);
484 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
487 image_view=DestroyCacheView(image_view);
488 depth=current_depth[0];
489 for (i=1; i < (ssize_t) number_threads; i++)
490 if (depth < current_depth[i])
491 depth=current_depth[i];
492 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 % G e t I m a g e Q u a n t u m D e p t h %
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
508 % quantum depth: 8, 16, or 32.
510 % The format of the GetImageQuantumDepth method is:
512 % size_t GetImageQuantumDepth(const Image *image,
513 % const MagickBooleanType constrain)
515 % A description of each parameter follows:
517 % o image: the image.
519 % o constrain: A value other than MagickFalse, constrains the depth to
520 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
523 MagickExport size_t GetImageQuantumDepth(const Image *image,
524 const MagickBooleanType constrain)
541 if (constrain != MagickFalse)
542 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551 % G e t I m a g e T y p e %
555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 % GetImageType() returns the type of image:
559 % Bilevel Grayscale GrayscaleMatte
560 % Palette PaletteMatte TrueColor
561 % TrueColorMatte ColorSeparation ColorSeparationMatte
563 % The format of the GetImageType method is:
565 % ImageType GetImageType(const Image *image)
567 % A description of each parameter follows:
569 % o image: the image.
572 MagickExport ImageType GetImageType(const Image *image)
574 assert(image != (Image *) NULL);
575 assert(image->signature == MagickCoreSignature);
576 if (image->colorspace == CMYKColorspace)
578 if (image->alpha_trait == UndefinedPixelTrait)
579 return(ColorSeparationType);
580 return(ColorSeparationAlphaType);
582 if (IsImageMonochrome(image) != MagickFalse)
584 if (IsImageGray(image) != MagickFalse)
586 if (image->alpha_trait != UndefinedPixelTrait)
587 return(GrayscaleAlphaType);
588 return(GrayscaleType);
590 if (IsPaletteImage(image) != MagickFalse)
592 if (image->alpha_trait != UndefinedPixelTrait)
593 return(PaletteAlphaType);
596 if (image->alpha_trait != UndefinedPixelTrait)
597 return(TrueColorAlphaType);
598 return(TrueColorType);
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 % I d e n t i f y I m a g e G r a y %
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 % IdentifyImageGray() returns grayscale if all the pixels in the image have
613 % the same red, green, and blue intensities, and bi-level is the intensity is
614 % either 0 or QuantumRange. Otherwise undefined is returned.
616 % The format of the IdentifyImageGray method is:
618 % ImageType IdentifyImageGray(const Image *image,ExceptionInfo *exception)
620 % A description of each parameter follows:
622 % o image: the image.
624 % o exception: return any errors or warnings in this structure.
627 MagickExport ImageType IdentifyImageGray(const Image *image,
628 ExceptionInfo *exception)
636 register const Quantum
645 assert(image != (Image *) NULL);
646 assert(image->signature == MagickCoreSignature);
647 if (image->debug != MagickFalse)
648 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
649 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
650 (image->type == GrayscaleAlphaType))
652 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
653 return(UndefinedType);
655 image_view=AcquireVirtualCacheView(image,exception);
656 for (y=0; y < (ssize_t) image->rows; y++)
658 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
659 if (p == (const Quantum *) NULL)
661 for (x=0; x < (ssize_t) image->columns; x++)
663 if (IsPixelGray(image,p) == MagickFalse)
668 if ((type == BilevelType) &&
669 (IsPixelMonochrome(image,p) == MagickFalse))
671 p+=GetPixelChannels(image);
673 if (type == UndefinedType)
676 image_view=DestroyCacheView(image_view);
677 if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
678 type=GrayscaleAlphaType;
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687 % I d e n t i f y I m a g e M o n o c h r o m e %
691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693 % IdentifyImageMonochrome() returns MagickTrue if all the pixels in the image
694 % have the same red, green, and blue intensities and the intensity is either
697 % The format of the IdentifyImageMonochrome method is:
699 % MagickBooleanType IdentifyImageMonochrome(const Image *image,
700 % ExceptionInfo *exception)
702 % A description of each parameter follows:
704 % o image: the image.
706 % o exception: return any errors or warnings in this structure.
709 MagickExport MagickBooleanType IdentifyImageMonochrome(const Image *image,
710 ExceptionInfo *exception)
721 register const Quantum
727 assert(image != (Image *) NULL);
728 assert(image->signature == MagickCoreSignature);
729 if (image->debug != MagickFalse)
730 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
731 if (image->type == BilevelType)
733 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
736 image_view=AcquireVirtualCacheView(image,exception);
737 for (y=0; y < (ssize_t) image->rows; y++)
739 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
740 if (p == (const Quantum *) NULL)
742 for (x=0; x < (ssize_t) image->columns; x++)
744 if (IsPixelMonochrome(image,p) == MagickFalse)
749 p+=GetPixelChannels(image);
751 if (bilevel == MagickFalse)
754 image_view=DestroyCacheView(image_view);
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763 % I d e n t i f y I m a g e T y p e %
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
769 % IdentifyImageType() returns the potential type of image:
771 % Bilevel Grayscale GrayscaleMatte
772 % Palette PaletteMatte TrueColor
773 % TrueColorMatte ColorSeparation ColorSeparationMatte
775 % To ensure the image type matches its potential, use SetImageType():
777 % (void) SetImageType(image,IdentifyImageType(image,exception),exception);
779 % The format of the IdentifyImageType method is:
781 % ImageType IdentifyImageType(const Image *image,ExceptionInfo *exception)
783 % A description of each parameter follows:
785 % o image: the image.
787 % o exception: return any errors or warnings in this structure.
790 MagickExport ImageType IdentifyImageType(const Image *image,
791 ExceptionInfo *exception)
793 assert(image != (Image *) NULL);
794 assert(image->signature == MagickCoreSignature);
795 if (image->debug != MagickFalse)
796 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
797 if (image->colorspace == CMYKColorspace)
799 if (image->alpha_trait == UndefinedPixelTrait)
800 return(ColorSeparationType);
801 return(ColorSeparationAlphaType);
803 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
805 if (IdentifyImageGray(image,exception) != UndefinedType)
807 if (image->alpha_trait != UndefinedPixelTrait)
808 return(GrayscaleAlphaType);
809 return(GrayscaleType);
811 if (IdentifyPaletteImage(image,exception) != MagickFalse)
813 if (image->alpha_trait != UndefinedPixelTrait)
814 return(PaletteAlphaType);
817 if (image->alpha_trait != UndefinedPixelTrait)
818 return(TrueColorAlphaType);
819 return(TrueColorType);
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 % I s I m a g e G r a y %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % IsImageGray() returns MagickTrue if the type of the image is grayscale or
836 % The format of the IsImageGray method is:
838 % MagickBooleanType IsImageGray(const Image *image)
840 % A description of each parameter follows:
842 % o image: the image.
845 MagickExport MagickBooleanType IsImageGray(const Image *image)
847 assert(image != (Image *) NULL);
848 assert(image->signature == MagickCoreSignature);
849 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
850 (image->type == GrayscaleAlphaType))
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860 % I s I m a g e M o n o c h r o m e %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 % IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
868 % The format of the IsImageMonochrome method is:
870 % MagickBooleanType IsImageMonochrome(const Image *image)
872 % A description of each parameter follows:
874 % o image: the image.
877 MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
879 assert(image != (Image *) NULL);
880 assert(image->signature == MagickCoreSignature);
881 if (image->type == BilevelType)
887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 % I s I m a g e O p a q u e %
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
897 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
898 % an alpha value other than OpaqueAlpha (QuantumRange).
900 % Will return true immediatally is alpha channel is not available.
902 % The format of the IsImageOpaque method is:
904 % MagickBooleanType IsImageOpaque(const Image *image,
905 % ExceptionInfo *exception)
907 % A description of each parameter follows:
909 % o image: the image.
911 % o exception: return any errors or warnings in this structure.
914 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
915 ExceptionInfo *exception)
920 register const Quantum
930 Determine if image is opaque.
932 assert(image != (Image *) NULL);
933 assert(image->signature == MagickCoreSignature);
934 if (image->debug != MagickFalse)
935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
936 if (image->alpha_trait == UndefinedPixelTrait)
938 image_view=AcquireVirtualCacheView(image,exception);
939 for (y=0; y < (ssize_t) image->rows; y++)
941 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
942 if (p == (const Quantum *) NULL)
944 for (x=0; x < (ssize_t) image->columns; x++)
946 if (GetPixelAlpha(image,p) != OpaqueAlpha)
948 p+=GetPixelChannels(image);
950 if (x < (ssize_t) image->columns)
953 image_view=DestroyCacheView(image_view);
954 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962 % S e t I m a g e D e p t h %
966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 % SetImageDepth() sets the depth of the image.
970 % The format of the SetImageDepth method is:
972 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
973 % ExceptionInfo *exception)
975 % A description of each parameter follows:
977 % o image: the image.
979 % o channel: the channel.
981 % o depth: the image depth.
983 % o exception: return any errors or warnings in this structure.
986 MagickExport MagickBooleanType SetImageDepth(Image *image,
987 const size_t depth,ExceptionInfo *exception)
1001 assert(image != (Image *) NULL);
1002 if (image->debug != MagickFalse)
1003 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1004 assert(image->signature == MagickCoreSignature);
1005 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1010 range=GetQuantumRange(depth);
1011 if (image->storage_class == PseudoClass)
1016 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1017 #pragma omp parallel for schedule(static) shared(status) \
1018 magick_number_threads(image,image,image->colors,1)
1020 for (i=0; i < (ssize_t) image->colors; i++)
1022 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
1023 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1024 ClampPixel(image->colormap[i].red),range),range);
1025 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
1026 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1027 ClampPixel(image->colormap[i].green),range),range);
1028 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
1029 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1030 ClampPixel(image->colormap[i].blue),range),range);
1031 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
1032 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1033 ClampPixel(image->colormap[i].alpha),range),range);
1037 image_view=AcquireAuthenticCacheView(image,exception);
1038 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1039 if ((1UL*QuantumRange) <= MaxMap)
1048 Scale pixels to desired (optimized with depth map).
1050 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
1051 if (depth_map == (Quantum *) NULL)
1052 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1053 for (i=0; i <= (ssize_t) MaxMap; i++)
1054 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1056 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1057 #pragma omp parallel for schedule(static) shared(status) \
1058 magick_number_threads(image,image,image->rows,1)
1060 for (y=0; y < (ssize_t) image->rows; y++)
1068 if (status == MagickFalse)
1070 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1072 if (q == (Quantum *) NULL)
1077 for (x=0; x < (ssize_t) image->columns; x++)
1082 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1090 channel=GetPixelChannelChannel(image,i);
1091 traits=GetPixelChannelTraits(image,channel);
1092 if ((traits & UpdatePixelTrait) == 0)
1094 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1096 q+=GetPixelChannels(image);
1098 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1104 image_view=DestroyCacheView(image_view);
1105 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1106 if (status != MagickFalse)
1112 Scale pixels to desired depth.
1114 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1115 #pragma omp parallel for schedule(static) shared(status) \
1116 magick_number_threads(image,image,image->rows,1)
1118 for (y=0; y < (ssize_t) image->rows; y++)
1126 if (status == MagickFalse)
1128 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1129 if (q == (Quantum *) NULL)
1134 for (x=0; x < (ssize_t) image->columns; x++)
1139 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1147 channel=GetPixelChannelChannel(image,i);
1148 traits=GetPixelChannelTraits(image,channel);
1149 if ((traits & UpdatePixelTrait) == 0)
1151 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel((MagickRealType)
1152 q[i]),range),range);
1154 q+=GetPixelChannels(image);
1156 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1162 image_view=DestroyCacheView(image_view);
1163 if (status != MagickFalse)
1169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1173 % S e t I m a g e T y p e %
1177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179 % SetImageType() sets the type of image. Choose from these types:
1181 % Bilevel Grayscale GrayscaleMatte
1182 % Palette PaletteMatte TrueColor
1183 % TrueColorMatte ColorSeparation ColorSeparationMatte
1186 % The format of the SetImageType method is:
1188 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1189 % ExceptionInfo *exception)
1191 % A description of each parameter follows:
1193 % o image: the image.
1195 % o type: Image type.
1197 % o exception: return any errors or warnings in this structure.
1200 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1201 ExceptionInfo *exception)
1215 assert(image != (Image *) NULL);
1216 if (image->debug != MagickFalse)
1217 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1218 assert(image->signature == MagickCoreSignature);
1220 image_info=AcquireImageInfo();
1221 image_info->dither=image->dither;
1222 artifact=GetImageArtifact(image,"dither");
1223 if (artifact != (const char *) NULL)
1224 (void) SetImageOption(image_info,"dither",artifact);
1229 status=TransformImageColorspace(image,GRAYColorspace,exception);
1230 (void) NormalizeImage(image,exception);
1231 quantize_info=AcquireQuantizeInfo(image_info);
1232 quantize_info->number_colors=2;
1233 quantize_info->colorspace=GRAYColorspace;
1234 status=QuantizeImage(quantize_info,image,exception);
1235 quantize_info=DestroyQuantizeInfo(quantize_info);
1236 image->alpha_trait=UndefinedPixelTrait;
1241 status=TransformImageColorspace(image,GRAYColorspace,exception);
1242 image->alpha_trait=UndefinedPixelTrait;
1245 case GrayscaleAlphaType:
1247 status=TransformImageColorspace(image,GRAYColorspace,exception);
1248 if (image->alpha_trait == UndefinedPixelTrait)
1249 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1254 status=TransformImageColorspace(image,sRGBColorspace,exception);
1255 if ((image->storage_class == DirectClass) || (image->colors > 256))
1257 quantize_info=AcquireQuantizeInfo(image_info);
1258 quantize_info->number_colors=256;
1259 status=QuantizeImage(quantize_info,image,exception);
1260 quantize_info=DestroyQuantizeInfo(quantize_info);
1262 image->alpha_trait=UndefinedPixelTrait;
1265 case PaletteBilevelAlphaType:
1270 status=TransformImageColorspace(image,sRGBColorspace,exception);
1271 if (image->alpha_trait == UndefinedPixelTrait)
1272 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1273 channel_mask=SetImageChannelMask(image,AlphaChannel);
1274 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1275 (void) SetImageChannelMask(image,channel_mask);
1276 quantize_info=AcquireQuantizeInfo(image_info);
1277 status=QuantizeImage(quantize_info,image,exception);
1278 quantize_info=DestroyQuantizeInfo(quantize_info);
1281 case PaletteAlphaType:
1283 status=TransformImageColorspace(image,sRGBColorspace,exception);
1284 if (image->alpha_trait == UndefinedPixelTrait)
1285 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1286 quantize_info=AcquireQuantizeInfo(image_info);
1287 quantize_info->colorspace=TransparentColorspace;
1288 status=QuantizeImage(quantize_info,image,exception);
1289 quantize_info=DestroyQuantizeInfo(quantize_info);
1294 status=TransformImageColorspace(image,sRGBColorspace,exception);
1295 if (image->storage_class != DirectClass)
1296 status=SetImageStorageClass(image,DirectClass,exception);
1297 image->alpha_trait=UndefinedPixelTrait;
1300 case TrueColorAlphaType:
1302 status=TransformImageColorspace(image,sRGBColorspace,exception);
1303 if (image->storage_class != DirectClass)
1304 status=SetImageStorageClass(image,DirectClass,exception);
1305 if (image->alpha_trait == UndefinedPixelTrait)
1306 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1309 case ColorSeparationType:
1311 status=TransformImageColorspace(image,CMYKColorspace,exception);
1312 if (image->storage_class != DirectClass)
1313 status=SetImageStorageClass(image,DirectClass,exception);
1314 image->alpha_trait=UndefinedPixelTrait;
1317 case ColorSeparationAlphaType:
1319 status=TransformImageColorspace(image,CMYKColorspace,exception);
1320 if (image->storage_class != DirectClass)
1321 status=SetImageStorageClass(image,DirectClass,exception);
1322 if (image->alpha_trait == UndefinedPixelTrait)
1323 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1330 image_info=DestroyImageInfo(image_info);
1331 if (status == MagickFalse)