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-2017 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://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 == 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,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 == 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 #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(ClampToQuantum(image->colormap[i].red),range) == MagickFalse)
335 if ((atDepth != MagickFalse) &&
336 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
337 if (IsPixelAtDepth(ClampToQuantum(image->colormap[i].green),range) == MagickFalse)
339 if ((atDepth != MagickFalse) &&
340 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
341 if (IsPixelAtDepth(ClampToQuantum(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 ((1UL*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 (GetPixelWriteMask(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 (GetPixelWriteMask(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 type of image:
573 % Bilevel Grayscale GrayscaleMatte
574 % Palette PaletteMatte TrueColor
575 % TrueColorMatte ColorSeparation ColorSeparationMatte
577 % The format of the GetImageType method is:
579 % ImageType GetImageType(const Image *image)
581 % A description of each parameter follows:
583 % o image: the image.
586 MagickExport ImageType GetImageType(const Image *image)
588 assert(image != (Image *) NULL);
589 assert(image->signature == MagickCoreSignature);
590 if (image->colorspace == CMYKColorspace)
592 if (image->alpha_trait == UndefinedPixelTrait)
593 return(ColorSeparationType);
594 return(ColorSeparationAlphaType);
596 if (IsImageMonochrome(image) != MagickFalse)
598 if (IsImageGray(image) != MagickFalse)
600 if (image->alpha_trait != UndefinedPixelTrait)
601 return(GrayscaleAlphaType);
602 return(GrayscaleType);
604 if (IsPaletteImage(image) != MagickFalse)
606 if (image->alpha_trait != UndefinedPixelTrait)
607 return(PaletteAlphaType);
610 if (image->alpha_trait != UndefinedPixelTrait)
611 return(TrueColorAlphaType);
612 return(TrueColorType);
616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
620 % I d e n t i f y I m a g e G r a y %
624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626 % IdentifyImageGray() returns grayscale if all the pixels in the image have
627 % the same red, green, and blue intensities, and bi-level is the intensity is
628 % either 0 or QuantumRange. Otherwise undefined is returned.
630 % The format of the IdentifyImageGray method is:
632 % ImageType IdentifyImageGray(const Image *image,ExceptionInfo *exception)
634 % A description of each parameter follows:
636 % o image: the image.
638 % o exception: return any errors or warnings in this structure.
641 MagickExport ImageType IdentifyImageGray(const Image *image,
642 ExceptionInfo *exception)
650 register const Quantum
659 assert(image != (Image *) NULL);
660 assert(image->signature == MagickCoreSignature);
661 if (image->debug != MagickFalse)
662 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
663 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
664 (image->type == GrayscaleAlphaType))
666 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
667 return(UndefinedType);
669 image_view=AcquireVirtualCacheView(image,exception);
670 for (y=0; y < (ssize_t) image->rows; y++)
672 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
673 if (p == (const Quantum *) NULL)
675 for (x=0; x < (ssize_t) image->columns; x++)
677 if (IsPixelGray(image,p) == MagickFalse)
682 if ((type == BilevelType) &&
683 (IsPixelMonochrome(image,p) == MagickFalse))
685 p+=GetPixelChannels(image);
687 if (type == UndefinedType)
690 image_view=DestroyCacheView(image_view);
691 if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
692 type=GrayscaleAlphaType;
697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701 % I d e n t i f y I m a g e M o n o c h r o m e %
705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 % IdentifyImageMonochrome() returns MagickTrue if all the pixels in the image
708 % have the same red, green, and blue intensities and the intensity is either
711 % The format of the IdentifyImageMonochrome method is:
713 % MagickBooleanType IdentifyImageMonochrome(const Image *image,
714 % ExceptionInfo *exception)
716 % A description of each parameter follows:
718 % o image: the image.
720 % o exception: return any errors or warnings in this structure.
723 MagickExport MagickBooleanType IdentifyImageMonochrome(const Image *image,
724 ExceptionInfo *exception)
735 register const Quantum
741 assert(image != (Image *) NULL);
742 assert(image->signature == MagickCoreSignature);
743 if (image->debug != MagickFalse)
744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
745 if (image->type == BilevelType)
747 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
750 image_view=AcquireVirtualCacheView(image,exception);
751 for (y=0; y < (ssize_t) image->rows; y++)
753 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
754 if (p == (const Quantum *) NULL)
756 for (x=0; x < (ssize_t) image->columns; x++)
758 if (IsPixelMonochrome(image,p) == MagickFalse)
763 p+=GetPixelChannels(image);
765 if (type == UndefinedType)
768 image_view=DestroyCacheView(image_view);
769 if (type == BilevelType)
775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779 % I d e n t i f y I m a g e T y p e %
783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
785 % IdentifyImageType() returns the potential type of image:
787 % Bilevel Grayscale GrayscaleMatte
788 % Palette PaletteMatte TrueColor
789 % TrueColorMatte ColorSeparation ColorSeparationMatte
791 % To ensure the image type matches its potential, use SetImageType():
793 % (void) SetImageType(image,IdentifyImageType(image,exception),exception);
795 % The format of the IdentifyImageType method is:
797 % ImageType IdentifyImageType(const Image *image,ExceptionInfo *exception)
799 % A description of each parameter follows:
801 % o image: the image.
803 % o exception: return any errors or warnings in this structure.
806 MagickExport ImageType IdentifyImageType(const Image *image,
807 ExceptionInfo *exception)
809 assert(image != (Image *) NULL);
810 assert(image->signature == MagickCoreSignature);
811 if (image->debug != MagickFalse)
812 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
813 if (image->colorspace == CMYKColorspace)
815 if (image->alpha_trait == UndefinedPixelTrait)
816 return(ColorSeparationType);
817 return(ColorSeparationAlphaType);
819 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
821 if (IdentifyImageGray(image,exception) != UndefinedType)
823 if (image->alpha_trait != UndefinedPixelTrait)
824 return(GrayscaleAlphaType);
825 return(GrayscaleType);
827 if (IdentifyPaletteImage(image,exception) != MagickFalse)
829 if (image->alpha_trait != UndefinedPixelTrait)
830 return(PaletteAlphaType);
833 if (image->alpha_trait != UndefinedPixelTrait)
834 return(TrueColorAlphaType);
835 return(TrueColorType);
839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843 % I s I m a g e G r a y %
847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849 % IsImageGray() returns MagickTrue if the type of the image is grayscale or
852 % The format of the IsImageGray method is:
854 % MagickBooleanType IsImageGray(const Image *image)
856 % A description of each parameter follows:
858 % o image: the image.
861 MagickExport MagickBooleanType IsImageGray(const Image *image)
863 assert(image != (Image *) NULL);
864 assert(image->signature == MagickCoreSignature);
865 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
866 (image->type == GrayscaleAlphaType))
872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 % I s I m a g e M o n o c h r o m e %
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882 % IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
884 % The format of the IsImageMonochrome method is:
886 % MagickBooleanType IsImageMonochrome(const Image *image)
888 % A description of each parameter follows:
890 % o image: the image.
893 MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
895 assert(image != (Image *) NULL);
896 assert(image->signature == MagickCoreSignature);
897 if (image->type == BilevelType)
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907 % I s I m a g e O p a q u e %
911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
913 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
914 % an alpha value other than OpaqueAlpha (QuantumRange).
916 % Will return true immediatally is alpha channel is not available.
918 % The format of the IsImageOpaque method is:
920 % MagickBooleanType IsImageOpaque(const Image *image,
921 % ExceptionInfo *exception)
923 % A description of each parameter follows:
925 % o image: the image.
927 % o exception: return any errors or warnings in this structure.
930 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
931 ExceptionInfo *exception)
936 register const Quantum
946 Determine if image is opaque.
948 assert(image != (Image *) NULL);
949 assert(image->signature == MagickCoreSignature);
950 if (image->debug != MagickFalse)
951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
952 if (image->alpha_trait == UndefinedPixelTrait)
954 image_view=AcquireVirtualCacheView(image,exception);
955 for (y=0; y < (ssize_t) image->rows; y++)
957 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
958 if (p == (const Quantum *) NULL)
960 for (x=0; x < (ssize_t) image->columns; x++)
962 if (GetPixelAlpha(image,p) != OpaqueAlpha)
964 p+=GetPixelChannels(image);
966 if (x < (ssize_t) image->columns)
969 image_view=DestroyCacheView(image_view);
970 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 % S e t I m a g e D e p t h %
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984 % SetImageDepth() sets the depth of the image.
986 % The format of the SetImageDepth method is:
988 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
989 % ExceptionInfo *exception)
991 % A description of each parameter follows:
993 % o image: the image.
995 % o channel: the channel.
997 % o depth: the image depth.
999 % o exception: return any errors or warnings in this structure.
1002 MagickExport MagickBooleanType SetImageDepth(Image *image,
1003 const size_t depth,ExceptionInfo *exception)
1017 assert(image != (Image *) NULL);
1018 if (image->debug != MagickFalse)
1019 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1020 assert(image->signature == MagickCoreSignature);
1021 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1026 range=GetQuantumRange(depth);
1027 if (image->storage_class == PseudoClass)
1032 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1033 #pragma omp parallel for schedule(static,4) shared(status) \
1034 magick_threads(image,image,1,1)
1036 for (i=0; i < (ssize_t) image->colors; i++)
1038 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
1039 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1040 ClampPixel(image->colormap[i].red),range),range);
1041 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
1042 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1043 ClampPixel(image->colormap[i].green),range),range);
1044 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
1045 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1046 ClampPixel(image->colormap[i].blue),range),range);
1047 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
1048 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1049 ClampPixel(image->colormap[i].alpha),range),range);
1053 image_view=AcquireAuthenticCacheView(image,exception);
1054 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1055 if ((1UL*QuantumRange) <= MaxMap)
1064 Scale pixels to desired (optimized with depth map).
1066 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
1067 if (depth_map == (Quantum *) NULL)
1068 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1069 for (i=0; i <= (ssize_t) MaxMap; i++)
1070 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1072 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1073 #pragma omp parallel for schedule(static,4) shared(status) \
1074 magick_threads(image,image,image->rows,1)
1076 for (y=0; y < (ssize_t) image->rows; y++)
1084 if (status == MagickFalse)
1086 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1088 if (q == (Quantum *) NULL)
1093 for (x=0; x < (ssize_t) image->columns; x++)
1098 if (GetPixelWriteMask(image,q) == 0)
1100 q+=GetPixelChannels(image);
1103 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1111 channel=GetPixelChannelChannel(image,i);
1112 traits=GetPixelChannelTraits(image,channel);
1113 if ((traits == UndefinedPixelTrait) ||
1114 (channel == IndexPixelChannel) ||
1115 (channel == ReadMaskPixelChannel))
1117 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1119 q+=GetPixelChannels(image);
1121 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1127 image_view=DestroyCacheView(image_view);
1128 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1129 if (status != MagickFalse)
1135 Scale pixels to desired depth.
1137 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1138 #pragma omp parallel for schedule(static,4) shared(status) \
1139 magick_threads(image,image,image->rows,1)
1141 for (y=0; y < (ssize_t) image->rows; y++)
1149 if (status == MagickFalse)
1151 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1152 if (q == (Quantum *) NULL)
1157 for (x=0; x < (ssize_t) image->columns; x++)
1162 if (GetPixelWriteMask(image,q) == 0)
1164 q+=GetPixelChannels(image);
1167 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1175 channel=GetPixelChannelChannel(image,i);
1176 traits=GetPixelChannelTraits(image,channel);
1177 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1178 (channel == ReadMaskPixelChannel))
1180 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel((MagickRealType)
1181 q[i]),range),range);
1183 q+=GetPixelChannels(image);
1185 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1191 image_view=DestroyCacheView(image_view);
1192 if (status != MagickFalse)
1198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1202 % S e t I m a g e T y p e %
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1208 % SetImageType() sets the type of image. Choose from these types:
1210 % Bilevel Grayscale GrayscaleMatte
1211 % Palette PaletteMatte TrueColor
1212 % TrueColorMatte ColorSeparation ColorSeparationMatte
1215 % The format of the SetImageType method is:
1217 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1218 % ExceptionInfo *exception)
1220 % A description of each parameter follows:
1222 % o image: the image.
1224 % o type: Image type.
1226 % o exception: return any errors or warnings in this structure.
1229 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1230 ExceptionInfo *exception)
1244 assert(image != (Image *) NULL);
1245 if (image->debug != MagickFalse)
1246 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1247 assert(image->signature == MagickCoreSignature);
1249 image_info=AcquireImageInfo();
1250 image_info->dither=image->dither;
1251 artifact=GetImageArtifact(image,"dither");
1252 if (artifact != (const char *) NULL)
1253 (void) SetImageOption(image_info,"dither",artifact);
1258 if (SetImageMonochrome(image,exception) == MagickFalse)
1260 status=TransformImageColorspace(image,GRAYColorspace,exception);
1261 (void) NormalizeImage(image,exception);
1262 quantize_info=AcquireQuantizeInfo(image_info);
1263 quantize_info->number_colors=2;
1264 quantize_info->colorspace=GRAYColorspace;
1265 status=QuantizeImage(quantize_info,image,exception);
1266 quantize_info=DestroyQuantizeInfo(quantize_info);
1268 image->alpha_trait=UndefinedPixelTrait;
1273 if (SetImageGray(image,exception) == MagickFalse)
1274 status=TransformImageColorspace(image,GRAYColorspace,exception);
1275 image->alpha_trait=UndefinedPixelTrait;
1278 case GrayscaleAlphaType:
1280 if (SetImageGray(image,exception) == MagickFalse)
1281 status=TransformImageColorspace(image,GRAYColorspace,exception);
1282 if (image->alpha_trait == UndefinedPixelTrait)
1283 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1288 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1289 status=TransformImageColorspace(image,sRGBColorspace,exception);
1290 if ((image->storage_class == DirectClass) || (image->colors > 256))
1292 quantize_info=AcquireQuantizeInfo(image_info);
1293 quantize_info->number_colors=256;
1294 status=QuantizeImage(quantize_info,image,exception);
1295 quantize_info=DestroyQuantizeInfo(quantize_info);
1297 image->alpha_trait=UndefinedPixelTrait;
1300 case PaletteBilevelAlphaType:
1305 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1306 status=TransformImageColorspace(image,sRGBColorspace,exception);
1307 if (image->alpha_trait == UndefinedPixelTrait)
1308 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1309 channel_mask=SetImageChannelMask(image,AlphaChannel);
1310 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1311 (void) SetImageChannelMask(image,channel_mask);
1312 quantize_info=AcquireQuantizeInfo(image_info);
1313 status=QuantizeImage(quantize_info,image,exception);
1314 quantize_info=DestroyQuantizeInfo(quantize_info);
1317 case PaletteAlphaType:
1319 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1320 status=TransformImageColorspace(image,sRGBColorspace,exception);
1321 if (image->alpha_trait == UndefinedPixelTrait)
1322 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1323 quantize_info=AcquireQuantizeInfo(image_info);
1324 quantize_info->colorspace=TransparentColorspace;
1325 status=QuantizeImage(quantize_info,image,exception);
1326 quantize_info=DestroyQuantizeInfo(quantize_info);
1331 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1332 status=TransformImageColorspace(image,sRGBColorspace,exception);
1333 if (image->storage_class != DirectClass)
1334 status=SetImageStorageClass(image,DirectClass,exception);
1335 image->alpha_trait=UndefinedPixelTrait;
1338 case TrueColorAlphaType:
1340 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1341 status=TransformImageColorspace(image,sRGBColorspace,exception);
1342 if (image->storage_class != DirectClass)
1343 status=SetImageStorageClass(image,DirectClass,exception);
1344 if (image->alpha_trait == UndefinedPixelTrait)
1345 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1348 case ColorSeparationType:
1350 if (image->colorspace != CMYKColorspace)
1352 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1353 status=TransformImageColorspace(image,sRGBColorspace,exception);
1354 status=TransformImageColorspace(image,CMYKColorspace,exception);
1356 if (image->storage_class != DirectClass)
1357 status=SetImageStorageClass(image,DirectClass,exception);
1358 image->alpha_trait=UndefinedPixelTrait;
1361 case ColorSeparationAlphaType:
1363 if (image->colorspace != CMYKColorspace)
1365 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1366 status=TransformImageColorspace(image,sRGBColorspace,exception);
1367 status=TransformImageColorspace(image,CMYKColorspace,exception);
1369 if (image->storage_class != DirectClass)
1370 status=SetImageStorageClass(image,DirectClass,exception);
1371 if (image->alpha_trait == UndefinedPixelTrait)
1372 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1379 image_info=DestroyImageInfo(image_info);
1380 if (status == MagickFalse)