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-2014 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) && (image->alpha_trait != BlendPixelTrait))
310 #if defined(MAGICKCORE_OPENMP_SUPPORT)
311 #pragma omp parallel for schedule(static,4) shared(status) \
312 if ((image->colors) > 256) \
313 num_threads(GetMagickResourceLimit(ThreadResource))
315 for (i=0; i < (ssize_t) image->colors; i++)
318 id = GetOpenMPThreadId();
320 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
329 range=GetQuantumRange(current_depth[id]);
330 if ((atDepth != MagickFalse) &&
331 (GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
332 if (IsPixelAtDepth(image->colormap[i].red,range) == MagickFalse)
334 if ((atDepth != MagickFalse) &&
335 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
336 if (IsPixelAtDepth(image->colormap[i].green,range) == MagickFalse)
338 if ((atDepth != MagickFalse) &&
339 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
340 if (IsPixelAtDepth(image->colormap[i].blue,range) == MagickFalse)
342 if ((atDepth != MagickFalse))
347 depth=current_depth[0];
348 for (i=1; i < (ssize_t) number_threads; i++)
349 if (depth < current_depth[i])
350 depth=current_depth[i];
351 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
354 image_view=AcquireVirtualCacheView(image,exception);
355 #if !defined(MAGICKCORE_HDRI_SUPPORT)
356 if (QuantumRange <= MaxMap)
362 Scale pixels to desired (optimized with depth map).
364 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
365 if (depth_map == (size_t *) NULL)
366 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
367 for (i=0; i <= (ssize_t) MaxMap; i++)
372 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
380 range=GetQuantumRange(depth);
382 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
387 #if defined(MAGICKCORE_OPENMP_SUPPORT)
388 #pragma omp parallel for schedule(static,4) shared(status) \
389 magick_threads(image,image,image->rows,1)
391 for (y=0; y < (ssize_t) image->rows; y++)
394 id = GetOpenMPThreadId();
396 register const Quantum
402 if (status == MagickFalse)
404 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
405 if (p == (const Quantum *) NULL)
407 for (x=0; x < (ssize_t) image->columns; x++)
409 if (GetPixelReadMask(image,p) == 0)
411 p+=GetPixelChannels(image);
414 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
416 PixelChannel channel=GetPixelChannelChannel(image,i);
417 PixelTrait traits=GetPixelChannelTraits(image,channel);
418 if ((traits == UndefinedPixelTrait) ||
419 (channel == IndexPixelChannel) ||
420 (channel == ReadMaskPixelChannel) ||
421 (channel == MetaPixelChannel))
423 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
424 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
426 p+=GetPixelChannels(image);
428 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
431 image_view=DestroyCacheView(image_view);
432 depth=current_depth[0];
433 for (i=1; i < (ssize_t) number_threads; i++)
434 if (depth < current_depth[i])
435 depth=current_depth[i];
436 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
437 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
444 #if defined(MAGICKCORE_OPENMP_SUPPORT)
445 #pragma omp parallel for schedule(static,4) shared(status) \
446 magick_threads(image,image,image->rows,1)
448 for (y=0; y < (ssize_t) image->rows; y++)
451 id = GetOpenMPThreadId();
453 register const Quantum
459 if (status == MagickFalse)
461 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
462 if (p == (const Quantum *) NULL)
464 for (x=0; x < (ssize_t) image->columns; x++)
466 if (GetPixelReadMask(image,p) == 0)
468 p+=GetPixelChannels(image);
471 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
479 channel=GetPixelChannelChannel(image,i);
480 traits=GetPixelChannelTraits(image,channel);
481 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
482 (channel == ReadMaskPixelChannel))
484 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
489 range=GetQuantumRange(current_depth[id]);
490 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
495 p+=GetPixelChannels(image);
497 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
500 image_view=DestroyCacheView(image_view);
501 depth=current_depth[0];
502 for (i=1; i < (ssize_t) number_threads; i++)
503 if (depth < current_depth[i])
504 depth=current_depth[i];
505 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
514 % G e t I m a g e Q u a n t u m D e p t h %
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
521 % quantum depth: 8, 16, or 32.
523 % The format of the GetImageQuantumDepth method is:
525 % size_t GetImageQuantumDepth(const Image *image,
526 % const MagickBooleanType constrain)
528 % A description of each parameter follows:
530 % o image: the image.
532 % o constrain: A value other than MagickFalse, constrains the depth to
533 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
537 static inline double MagickMin(const double x,const double y)
544 MagickExport size_t GetImageQuantumDepth(const Image *image,
545 const MagickBooleanType constrain)
562 if (constrain != MagickFalse)
563 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572 % G e t I m a g e T y p e %
576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578 % GetImageType() returns the potential type of image:
580 % Bilevel Grayscale GrayscaleMatte
581 % Palette PaletteMatte TrueColor
582 % TrueColorMatte ColorSeparation ColorSeparationMatte
584 % To ensure the image type matches its potential, use SetImageType():
586 % (void) SetImageType(image,GetImageType(image));
588 % The format of the GetImageType method is:
590 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
592 % A description of each parameter follows:
594 % o image: the image.
596 % o exception: return any errors or warnings in this structure.
599 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
601 assert(image != (Image *) NULL);
602 assert(image->signature == MagickSignature);
603 if (image->debug != MagickFalse)
604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
605 if (image->colorspace == CMYKColorspace)
607 if (image->alpha_trait != BlendPixelTrait)
608 return(ColorSeparationType);
609 return(ColorSeparationMatteType);
611 if (IsImageMonochrome(image,exception) != MagickFalse)
613 if (IsImageGray(image,exception) != MagickFalse)
615 if (image->alpha_trait == BlendPixelTrait)
616 return(GrayscaleMatteType);
617 return(GrayscaleType);
619 if (IsPaletteImage(image,exception) != MagickFalse)
621 if (image->alpha_trait == BlendPixelTrait)
622 return(PaletteMatteType);
625 if (image->alpha_trait == BlendPixelTrait)
626 return(TrueColorMatteType);
627 return(TrueColorType);
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 % I s I m a g e G r a y %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641 % IsImageGray() returns MagickTrue if all the pixels in the image have the
642 % same red, green, and blue intensities.
644 % The format of the IsImageGray method is:
646 % MagickBooleanType IsImageGray(const Image *image,
647 % ExceptionInfo *exception)
649 % A description of each parameter follows:
651 % o image: the image.
653 % o exception: return any errors or warnings in this structure.
656 MagickExport MagickBooleanType IsImageGray(const Image *image,
657 ExceptionInfo *exception)
665 register const Quantum
674 assert(image != (Image *) NULL);
675 assert(image->signature == MagickSignature);
676 if (image->debug != MagickFalse)
677 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
678 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
679 (image->type == GrayscaleMatteType))
681 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
682 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
685 image_view=AcquireVirtualCacheView(image,exception);
686 for (y=0; y < (ssize_t) image->rows; y++)
688 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
689 if (p == (const Quantum *) NULL)
691 for (x=0; x < (ssize_t) image->columns; x++)
693 if (IsPixelGray(image,p) == MagickFalse)
698 if ((type == BilevelType) &&
699 (IsPixelMonochrome(image,p) == MagickFalse))
701 p+=GetPixelChannels(image);
703 if (type == UndefinedType)
706 image_view=DestroyCacheView(image_view);
707 if (type == UndefinedType)
709 ((Image *) image)->colorspace=GRAYColorspace;
710 if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
712 ((Image *) image)->type=type;
713 if ((type == GrayscaleType) && (image->alpha_trait == BlendPixelTrait))
714 ((Image *) image)->type=GrayscaleMatteType;
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % I s I m a g e M o n o c h r o m e %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have
730 % the same red, green, and blue intensities and the intensity is either
733 % The format of the IsImageMonochrome method is:
735 % MagickBooleanType IsImageMonochrome(const Image *image,
736 % ExceptionInfo *exception)
738 % A description of each parameter follows:
740 % o image: the image.
742 % o exception: return any errors or warnings in this structure.
745 MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
746 ExceptionInfo *exception)
757 register const Quantum
763 assert(image != (Image *) NULL);
764 assert(image->signature == MagickSignature);
765 if (image->debug != MagickFalse)
766 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
767 if (image->type == BilevelType)
769 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
770 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
773 image_view=AcquireVirtualCacheView(image,exception);
774 for (y=0; y < (ssize_t) image->rows; y++)
776 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
777 if (p == (const Quantum *) NULL)
779 for (x=0; x < (ssize_t) image->columns; x++)
781 if (IsPixelMonochrome(image,p) == MagickFalse)
786 p+=GetPixelChannels(image);
788 if (type == UndefinedType)
791 image_view=DestroyCacheView(image_view);
792 if (type == UndefinedType)
794 ((Image *) image)->colorspace=GRAYColorspace;
795 if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
797 ((Image *) image)->type=type;
802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 % I s I m a g e O p a q u e %
810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
813 % an alpha value other than OpaqueAlpha (QuantumRange).
815 % Will return true immediatally is alpha channel is not available.
817 % The format of the IsImageOpaque method is:
819 % MagickBooleanType IsImageOpaque(const Image *image,
820 % ExceptionInfo *exception)
822 % A description of each parameter follows:
824 % o image: the image.
826 % o exception: return any errors or warnings in this structure.
829 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
830 ExceptionInfo *exception)
835 register const Quantum
845 Determine if image is opaque.
847 assert(image != (Image *) NULL);
848 assert(image->signature == MagickSignature);
849 if (image->debug != MagickFalse)
850 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
851 if (image->alpha_trait != BlendPixelTrait)
853 image_view=AcquireVirtualCacheView(image,exception);
854 for (y=0; y < (ssize_t) image->rows; y++)
856 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
857 if (p == (const Quantum *) NULL)
859 for (x=0; x < (ssize_t) image->columns; x++)
861 if (GetPixelAlpha(image,p) != OpaqueAlpha)
863 p+=GetPixelChannels(image);
865 if (x < (ssize_t) image->columns)
868 image_view=DestroyCacheView(image_view);
869 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877 % S e t I m a g e D e p t h %
881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883 % SetImageDepth() sets the depth of the image.
885 % The format of the SetImageDepth method is:
887 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
888 % ExceptionInfo *exception)
890 % A description of each parameter follows:
892 % o image: the image.
894 % o channel: the channel.
896 % o depth: the image depth.
898 % o exception: return any errors or warnings in this structure.
902 static inline Quantum ClampPixel(const MagickRealType value)
904 #if !defined(MAGICKCORE_HDRI_SUPPORT)
905 return((Quantum) value);
909 if (value >= (MagickRealType) QuantumRange)
910 return((Quantum) QuantumRange);
915 MagickExport MagickBooleanType SetImageDepth(Image *image,
916 const size_t depth,ExceptionInfo *exception)
930 assert(image != (Image *) NULL);
931 if (image->debug != MagickFalse)
932 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
933 assert(image->signature == MagickSignature);
934 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
939 range=GetQuantumRange(depth);
940 if (image->storage_class == PseudoClass)
945 #if defined(MAGICKCORE_OPENMP_SUPPORT)
946 #pragma omp parallel for schedule(static,4) shared(status) \
947 magick_threads(image,image,1,1)
949 for (i=0; i < (ssize_t) image->colors; i++)
951 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
952 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
953 ClampPixel(image->colormap[i].red),range),range);
954 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
955 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
956 ClampPixel(image->colormap[i].green),range),range);
957 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
958 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
959 ClampPixel(image->colormap[i].blue),range),range);
960 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
961 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
962 ClampPixel(image->colormap[i].alpha),range),range);
966 image_view=AcquireAuthenticCacheView(image,exception);
967 #if !defined(MAGICKCORE_HDRI_SUPPORT)
968 if (QuantumRange <= MaxMap)
977 Scale pixels to desired (optimized with depth map).
979 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
980 if (depth_map == (Quantum *) NULL)
981 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
982 for (i=0; i <= (ssize_t) MaxMap; i++)
983 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
985 #if defined(MAGICKCORE_OPENMP_SUPPORT)
986 #pragma omp parallel for schedule(static,4) shared(status) \
987 magick_threads(image,image,image->rows,1)
989 for (y=0; y < (ssize_t) image->rows; y++)
997 if (status == MagickFalse)
999 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1001 if (q == (Quantum *) NULL)
1006 for (x=0; x < (ssize_t) image->columns; x++)
1011 if (GetPixelReadMask(image,q) == 0)
1013 q+=GetPixelChannels(image);
1016 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1024 channel=GetPixelChannelChannel(image,i);
1025 traits=GetPixelChannelTraits(image,channel);
1026 if ((traits == UndefinedPixelTrait) ||
1027 (channel == IndexPixelChannel) ||
1028 (channel == ReadMaskPixelChannel))
1030 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1032 q+=GetPixelChannels(image);
1034 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1040 image_view=DestroyCacheView(image_view);
1041 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1042 if (status != MagickFalse)
1048 Scale pixels to desired depth.
1050 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1051 #pragma omp parallel for schedule(static,4) shared(status) \
1052 magick_threads(image,image,image->rows,1)
1054 for (y=0; y < (ssize_t) image->rows; y++)
1062 if (status == MagickFalse)
1064 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1065 if (q == (Quantum *) NULL)
1070 for (x=0; x < (ssize_t) image->columns; x++)
1075 if (GetPixelReadMask(image,q) == 0)
1077 q+=GetPixelChannels(image);
1080 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1088 channel=GetPixelChannelChannel(image,i);
1089 traits=GetPixelChannelTraits(image,channel);
1090 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1091 (channel == ReadMaskPixelChannel))
1093 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(q[i]),range),range);
1095 q+=GetPixelChannels(image);
1097 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1103 image_view=DestroyCacheView(image_view);
1104 if (status != MagickFalse)
1110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 % S e t I m a g e T y p e %
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120 % SetImageType() sets the type of image. Choose from these types:
1122 % Bilevel Grayscale GrayscaleMatte
1123 % Palette PaletteMatte TrueColor
1124 % TrueColorMatte ColorSeparation ColorSeparationMatte
1127 % The format of the SetImageType method is:
1129 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1130 % ExceptionInfo *exception)
1132 % A description of each parameter follows:
1134 % o image: the image.
1136 % o type: Image type.
1138 % o exception: return any errors or warnings in this structure.
1141 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1142 ExceptionInfo *exception)
1156 assert(image != (Image *) NULL);
1157 if (image->debug != MagickFalse)
1158 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1159 assert(image->signature == MagickSignature);
1161 image_info=AcquireImageInfo();
1162 image_info->dither=image->dither;
1163 artifact=GetImageArtifact(image,"dither");
1164 if (artifact != (const char *) NULL)
1165 (void) SetImageOption(image_info,"dither",artifact);
1170 if (IsImageGray(image,exception) == MagickFalse)
1171 status=TransformImageColorspace(image,GRAYColorspace,exception);
1172 (void) NormalizeImage(image,exception);
1173 if (IsImageMonochrome(image,exception) == MagickFalse)
1175 quantize_info=AcquireQuantizeInfo(image_info);
1176 quantize_info->number_colors=2;
1177 quantize_info->colorspace=GRAYColorspace;
1178 status=QuantizeImage(quantize_info,image,exception);
1179 quantize_info=DestroyQuantizeInfo(quantize_info);
1182 image->alpha_trait=UndefinedPixelTrait;
1187 if (IsImageGray(image,exception) == MagickFalse)
1188 status=TransformImageColorspace(image,GRAYColorspace,exception);
1189 image->alpha_trait=UndefinedPixelTrait;
1192 case GrayscaleMatteType:
1194 if (IsImageGray(image,exception) == MagickFalse)
1195 status=TransformImageColorspace(image,GRAYColorspace,exception);
1196 if (image->alpha_trait != BlendPixelTrait)
1197 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1202 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1203 status=TransformImageColorspace(image,sRGBColorspace,exception);
1204 if ((image->storage_class == DirectClass) || (image->colors > 256))
1206 quantize_info=AcquireQuantizeInfo(image_info);
1207 quantize_info->number_colors=256;
1208 status=QuantizeImage(quantize_info,image,exception);
1209 quantize_info=DestroyQuantizeInfo(quantize_info);
1211 image->alpha_trait=UndefinedPixelTrait;
1214 case PaletteBilevelMatteType:
1219 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1220 status=TransformImageColorspace(image,sRGBColorspace,exception);
1221 if (image->alpha_trait != BlendPixelTrait)
1222 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1223 channel_mask=SetImageChannelMask(image,AlphaChannel);
1224 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1225 (void) SetImageChannelMask(image,channel_mask);
1226 quantize_info=AcquireQuantizeInfo(image_info);
1227 status=QuantizeImage(quantize_info,image,exception);
1228 quantize_info=DestroyQuantizeInfo(quantize_info);
1231 case PaletteMatteType:
1233 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1234 status=TransformImageColorspace(image,sRGBColorspace,exception);
1235 if (image->alpha_trait != BlendPixelTrait)
1236 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1237 quantize_info=AcquireQuantizeInfo(image_info);
1238 quantize_info->colorspace=TransparentColorspace;
1239 status=QuantizeImage(quantize_info,image,exception);
1240 quantize_info=DestroyQuantizeInfo(quantize_info);
1245 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1246 status=TransformImageColorspace(image,sRGBColorspace,exception);
1247 if (image->storage_class != DirectClass)
1248 status=SetImageStorageClass(image,DirectClass,exception);
1249 image->alpha_trait=UndefinedPixelTrait;
1252 case TrueColorMatteType:
1254 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1255 status=TransformImageColorspace(image,sRGBColorspace,exception);
1256 if (image->storage_class != DirectClass)
1257 status=SetImageStorageClass(image,DirectClass,exception);
1258 if (image->alpha_trait != BlendPixelTrait)
1259 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1262 case ColorSeparationType:
1264 if (image->colorspace != CMYKColorspace)
1266 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1267 status=TransformImageColorspace(image,sRGBColorspace,exception);
1268 status=TransformImageColorspace(image,CMYKColorspace,exception);
1270 if (image->storage_class != DirectClass)
1271 status=SetImageStorageClass(image,DirectClass,exception);
1272 image->alpha_trait=UndefinedPixelTrait;
1275 case ColorSeparationMatteType:
1277 if (image->colorspace != CMYKColorspace)
1279 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1280 status=TransformImageColorspace(image,sRGBColorspace,exception);
1281 status=TransformImageColorspace(image,CMYKColorspace,exception);
1283 if (image->storage_class != DirectClass)
1284 status=SetImageStorageClass(image,DirectClass,exception);
1285 if (image->alpha_trait != BlendPixelTrait)
1286 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1293 image_info=DestroyImageInfo(image_info);
1294 if (status == MagickFalse)