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 GetPixelInfoPixel(image,p,&target[1]);
168 GetPixelInfo(image,&target[2]);
169 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
171 GetPixelInfoPixel(image,p,&target[2]);
173 GetPixelInfo(image,&zero);
174 #if defined(MAGICKCORE_OPENMP_SUPPORT)
175 #pragma omp parallel for schedule(static,4) shared(status) \
176 magick_threads(image,image,image->rows,1)
178 for (y=0; y < (ssize_t) image->rows; y++)
186 register const Quantum
192 if (status == MagickFalse)
194 #if defined(MAGICKCORE_OPENMP_SUPPORT)
195 # pragma omp critical (MagickCore_GetImageBoundingBox)
198 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
199 if (p == (const Quantum *) NULL)
205 for (x=0; x < (ssize_t) image->columns; x++)
207 GetPixelInfoPixel(image,p,&pixel);
208 if ((x < bounding_box.x) &&
209 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
211 if ((x > (ssize_t) bounding_box.width) &&
212 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
213 bounding_box.width=(size_t) x;
214 if ((y < bounding_box.y) &&
215 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
217 if ((y > (ssize_t) bounding_box.height) &&
218 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
219 bounding_box.height=(size_t) y;
220 p+=GetPixelChannels(image);
222 #if defined(MAGICKCORE_OPENMP_SUPPORT)
223 # pragma omp critical (MagickCore_GetImageBoundingBox)
226 if (bounding_box.x < bounds.x)
227 bounds.x=bounding_box.x;
228 if (bounding_box.y < bounds.y)
229 bounds.y=bounding_box.y;
230 if (bounding_box.width > bounds.width)
231 bounds.width=bounding_box.width;
232 if (bounding_box.height > bounds.height)
233 bounds.height=bounding_box.height;
236 image_view=DestroyCacheView(image_view);
237 if ((bounds.width == 0) || (bounds.height == 0))
238 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
239 "GeometryDoesNotContainImage","`%s'",image->filename);
242 bounds.width-=(bounds.x-1);
243 bounds.height-=(bounds.y-1);
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % G e t I m a g e D e p t h %
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
259 % GetImageDepth() returns the depth of a particular image channel.
261 % The format of the GetImageDepth method is:
263 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
265 % A description of each parameter follows:
267 % o image: the image.
269 % o exception: return any errors or warnings in this structure.
272 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
294 assert(image != (Image *) NULL);
295 assert(image->signature == MagickSignature);
296 if (image->debug != MagickFalse)
297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
298 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
299 current_depth=(size_t *) AcquireQuantumMemory(number_threads,
300 sizeof(*current_depth));
301 if (current_depth == (size_t *) NULL)
302 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
304 for (i=0; i < (ssize_t) number_threads; i++)
306 if ((image->storage_class == PseudoClass) && (image->alpha_trait != BlendPixelTrait))
308 #if defined(MAGICKCORE_OPENMP_SUPPORT)
309 #pragma omp parallel for schedule(static,4) shared(status) \
310 if ((image->colors) > 256) \
311 num_threads(GetMagickResourceLimit(ThreadResource))
313 for (i=0; i < (ssize_t) image->colors; i++)
316 id = GetOpenMPThreadId();
318 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
327 range=GetQuantumRange(current_depth[id]);
328 if ((atDepth != MagickFalse) &&
329 (GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
330 if (IsPixelAtDepth(image->colormap[i].red,range) == MagickFalse)
332 if ((atDepth != MagickFalse) &&
333 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
334 if (IsPixelAtDepth(image->colormap[i].green,range) == MagickFalse)
336 if ((atDepth != MagickFalse) &&
337 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
338 if (IsPixelAtDepth(image->colormap[i].blue,range) == MagickFalse)
340 if ((atDepth != MagickFalse))
345 depth=current_depth[0];
346 for (i=1; i < (ssize_t) number_threads; i++)
347 if (depth < current_depth[i])
348 depth=current_depth[i];
349 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
352 image_view=AcquireVirtualCacheView(image,exception);
353 #if !defined(MAGICKCORE_HDRI_SUPPORT)
354 if (QuantumRange <= MaxMap)
360 Scale pixels to desired (optimized with depth map).
362 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
363 if (depth_map == (size_t *) NULL)
364 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
365 for (i=0; i <= (ssize_t) MaxMap; i++)
370 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
378 range=GetQuantumRange(depth);
380 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
385 #if defined(MAGICKCORE_OPENMP_SUPPORT)
386 #pragma omp parallel for schedule(static,4) shared(status) \
387 magick_threads(image,image,image->rows,1)
389 for (y=0; y < (ssize_t) image->rows; y++)
392 id = GetOpenMPThreadId();
394 register const Quantum
400 if (status == MagickFalse)
402 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
403 if (p == (const Quantum *) NULL)
405 for (x=0; x < (ssize_t) image->columns; x++)
407 if (GetPixelReadMask(image,p) == 0)
409 p+=GetPixelChannels(image);
412 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
414 PixelChannel channel=GetPixelChannelChannel(image,i);
415 PixelTrait traits=GetPixelChannelTraits(image,channel);
416 if ((traits == UndefinedPixelTrait) ||
417 (channel == IndexPixelChannel) ||
418 (channel == ReadMaskPixelChannel) ||
419 (channel == MetaPixelChannel))
421 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
422 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
424 p+=GetPixelChannels(image);
426 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
429 image_view=DestroyCacheView(image_view);
430 depth=current_depth[0];
431 for (i=1; i < (ssize_t) number_threads; i++)
432 if (depth < current_depth[i])
433 depth=current_depth[i];
434 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
435 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
442 #if defined(MAGICKCORE_OPENMP_SUPPORT)
443 #pragma omp parallel for schedule(static,4) shared(status) \
444 magick_threads(image,image,image->rows,1)
446 for (y=0; y < (ssize_t) image->rows; y++)
449 id = GetOpenMPThreadId();
451 register const Quantum
457 if (status == MagickFalse)
459 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
460 if (p == (const Quantum *) NULL)
462 for (x=0; x < (ssize_t) image->columns; x++)
464 if (GetPixelReadMask(image,p) == 0)
466 p+=GetPixelChannels(image);
469 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
477 channel=GetPixelChannelChannel(image,i);
478 traits=GetPixelChannelTraits(image,channel);
479 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
480 (channel == ReadMaskPixelChannel))
482 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
487 range=GetQuantumRange(current_depth[id]);
488 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
493 p+=GetPixelChannels(image);
495 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
498 image_view=DestroyCacheView(image_view);
499 depth=current_depth[0];
500 for (i=1; i < (ssize_t) number_threads; i++)
501 if (depth < current_depth[i])
502 depth=current_depth[i];
503 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 % G e t I m a g e Q u a n t u m D e p t h %
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
519 % quantum depth: 8, 16, or 32.
521 % The format of the GetImageQuantumDepth method is:
523 % size_t GetImageQuantumDepth(const Image *image,
524 % const MagickBooleanType constrain)
526 % A description of each parameter follows:
528 % o image: the image.
530 % o constrain: A value other than MagickFalse, constrains the depth to
531 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
535 static inline double MagickMin(const double x,const double y)
542 MagickExport size_t GetImageQuantumDepth(const Image *image,
543 const MagickBooleanType constrain)
560 if (constrain != MagickFalse)
561 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 % G e t I m a g e T y p e %
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 % GetImageType() returns the potential type of image:
578 % Bilevel Grayscale GrayscaleMatte
579 % Palette PaletteMatte TrueColor
580 % TrueColorMatte ColorSeparation ColorSeparationMatte
582 % To ensure the image type matches its potential, use SetImageType():
584 % (void) SetImageType(image,GetImageType(image));
586 % The format of the GetImageType method is:
588 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
590 % A description of each parameter follows:
592 % o image: the image.
594 % o exception: return any errors or warnings in this structure.
597 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
599 assert(image != (Image *) NULL);
600 assert(image->signature == MagickSignature);
601 if (image->debug != MagickFalse)
602 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
603 if (image->colorspace == CMYKColorspace)
605 if (image->alpha_trait != BlendPixelTrait)
606 return(ColorSeparationType);
607 return(ColorSeparationMatteType);
609 if (IsImageMonochrome(image,exception) != MagickFalse)
611 if (IsImageGray(image,exception) != MagickFalse)
613 if (image->alpha_trait == BlendPixelTrait)
614 return(GrayscaleMatteType);
615 return(GrayscaleType);
617 if (IsPaletteImage(image,exception) != MagickFalse)
619 if (image->alpha_trait == BlendPixelTrait)
620 return(PaletteMatteType);
623 if (image->alpha_trait == BlendPixelTrait)
624 return(TrueColorMatteType);
625 return(TrueColorType);
629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633 % I s I m a g e G r a y %
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 % IsImageGray() returns MagickTrue if all the pixels in the image have the
640 % same red, green, and blue intensities.
642 % The format of the IsImageGray method is:
644 % MagickBooleanType IsImageGray(const Image *image,
645 % ExceptionInfo *exception)
647 % A description of each parameter follows:
649 % o image: the image.
651 % o exception: return any errors or warnings in this structure.
654 MagickExport MagickBooleanType IsImageGray(const Image *image,
655 ExceptionInfo *exception)
663 register const Quantum
672 assert(image != (Image *) NULL);
673 assert(image->signature == MagickSignature);
674 if (image->debug != MagickFalse)
675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
676 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
677 (image->type == GrayscaleMatteType))
679 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
680 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
683 image_view=AcquireVirtualCacheView(image,exception);
684 for (y=0; y < (ssize_t) image->rows; y++)
686 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
687 if (p == (const Quantum *) NULL)
689 for (x=0; x < (ssize_t) image->columns; x++)
691 if (IsPixelGray(image,p) == MagickFalse)
696 if ((type == BilevelType) &&
697 (IsPixelMonochrome(image,p) == MagickFalse))
699 p+=GetPixelChannels(image);
701 if (type == UndefinedType)
704 image_view=DestroyCacheView(image_view);
705 if (type == UndefinedType)
707 ((Image *) image)->colorspace=GRAYColorspace;
708 if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
710 ((Image *) image)->type=type;
711 if ((type == GrayscaleType) && (image->alpha_trait == BlendPixelTrait))
712 ((Image *) image)->type=GrayscaleMatteType;
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % I s I m a g e M o n o c h r o m e %
725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have
728 % the same red, green, and blue intensities and the intensity is either
731 % The format of the IsImageMonochrome method is:
733 % MagickBooleanType IsImageMonochrome(const Image *image,
734 % ExceptionInfo *exception)
736 % A description of each parameter follows:
738 % o image: the image.
740 % o exception: return any errors or warnings in this structure.
743 MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
744 ExceptionInfo *exception)
755 register const Quantum
761 assert(image != (Image *) NULL);
762 assert(image->signature == MagickSignature);
763 if (image->debug != MagickFalse)
764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
765 if (image->type == BilevelType)
767 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
768 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
771 image_view=AcquireVirtualCacheView(image,exception);
772 for (y=0; y < (ssize_t) image->rows; y++)
774 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
775 if (p == (const Quantum *) NULL)
777 for (x=0; x < (ssize_t) image->columns; x++)
779 if (IsPixelMonochrome(image,p) == MagickFalse)
784 p+=GetPixelChannels(image);
786 if (type == UndefinedType)
789 image_view=DestroyCacheView(image_view);
790 if (type == UndefinedType)
792 ((Image *) image)->colorspace=GRAYColorspace;
793 if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
795 ((Image *) image)->type=type;
800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 % I s I m a g e O p a q u e %
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
810 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
811 % an alpha value other than OpaqueAlpha (QuantumRange).
813 % Will return true immediatally is alpha channel is not available.
815 % The format of the IsImageOpaque method is:
817 % MagickBooleanType IsImageOpaque(const Image *image,
818 % ExceptionInfo *exception)
820 % A description of each parameter follows:
822 % o image: the image.
824 % o exception: return any errors or warnings in this structure.
827 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
828 ExceptionInfo *exception)
833 register const Quantum
843 Determine if image is opaque.
845 assert(image != (Image *) NULL);
846 assert(image->signature == MagickSignature);
847 if (image->debug != MagickFalse)
848 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
849 if (image->alpha_trait != BlendPixelTrait)
851 image_view=AcquireVirtualCacheView(image,exception);
852 for (y=0; y < (ssize_t) image->rows; y++)
854 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
855 if (p == (const Quantum *) NULL)
857 for (x=0; x < (ssize_t) image->columns; x++)
859 if (GetPixelAlpha(image,p) != OpaqueAlpha)
861 p+=GetPixelChannels(image);
863 if (x < (ssize_t) image->columns)
866 image_view=DestroyCacheView(image_view);
867 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875 % S e t I m a g e D e p t h %
879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 % SetImageDepth() sets the depth of the image.
883 % The format of the SetImageDepth method is:
885 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
886 % ExceptionInfo *exception)
888 % A description of each parameter follows:
890 % o image: the image.
892 % o channel: the channel.
894 % o depth: the image depth.
896 % o exception: return any errors or warnings in this structure.
900 static inline Quantum ClampPixel(const MagickRealType value)
902 #if !defined(MAGICKCORE_HDRI_SUPPORT)
903 return((Quantum) value);
907 if (value >= (MagickRealType) QuantumRange)
908 return((Quantum) QuantumRange);
913 MagickExport MagickBooleanType SetImageDepth(Image *image,
914 const size_t depth,ExceptionInfo *exception)
928 assert(image != (Image *) NULL);
929 if (image->debug != MagickFalse)
930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
931 assert(image->signature == MagickSignature);
932 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
937 range=GetQuantumRange(depth);
938 if (image->storage_class == PseudoClass)
943 #if defined(MAGICKCORE_OPENMP_SUPPORT)
944 #pragma omp parallel for schedule(static,4) shared(status) \
945 magick_threads(image,image,1,1)
947 for (i=0; i < (ssize_t) image->colors; i++)
949 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
950 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
951 ClampPixel(image->colormap[i].red),range),range);
952 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
953 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
954 ClampPixel(image->colormap[i].green),range),range);
955 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
956 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
957 ClampPixel(image->colormap[i].blue),range),range);
958 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
959 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
960 ClampPixel(image->colormap[i].alpha),range),range);
964 image_view=AcquireAuthenticCacheView(image,exception);
965 #if !defined(MAGICKCORE_HDRI_SUPPORT)
966 if (QuantumRange <= MaxMap)
975 Scale pixels to desired (optimized with depth map).
977 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
978 if (depth_map == (Quantum *) NULL)
979 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
980 for (i=0; i <= (ssize_t) MaxMap; i++)
981 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
983 #if defined(MAGICKCORE_OPENMP_SUPPORT)
984 #pragma omp parallel for schedule(static,4) shared(status) \
985 magick_threads(image,image,image->rows,1)
987 for (y=0; y < (ssize_t) image->rows; y++)
995 if (status == MagickFalse)
997 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
999 if (q == (Quantum *) NULL)
1004 for (x=0; x < (ssize_t) image->columns; x++)
1009 if (GetPixelReadMask(image,q) == 0)
1011 q+=GetPixelChannels(image);
1014 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1022 channel=GetPixelChannelChannel(image,i);
1023 traits=GetPixelChannelTraits(image,channel);
1024 if ((traits == UndefinedPixelTrait) ||
1025 (channel == IndexPixelChannel) ||
1026 (channel == ReadMaskPixelChannel))
1028 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1030 q+=GetPixelChannels(image);
1032 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1038 image_view=DestroyCacheView(image_view);
1039 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1040 if (status != MagickFalse)
1046 Scale pixels to desired depth.
1048 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1049 #pragma omp parallel for schedule(static,4) shared(status) \
1050 magick_threads(image,image,image->rows,1)
1052 for (y=0; y < (ssize_t) image->rows; y++)
1060 if (status == MagickFalse)
1062 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1063 if (q == (Quantum *) NULL)
1068 for (x=0; x < (ssize_t) image->columns; x++)
1073 if (GetPixelReadMask(image,q) == 0)
1075 q+=GetPixelChannels(image);
1078 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1086 channel=GetPixelChannelChannel(image,i);
1087 traits=GetPixelChannelTraits(image,channel);
1088 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1089 (channel == ReadMaskPixelChannel))
1091 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(q[i]),range),range);
1093 q+=GetPixelChannels(image);
1095 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1101 image_view=DestroyCacheView(image_view);
1102 if (status != MagickFalse)
1108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112 % S e t I m a g e T y p e %
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1118 % SetImageType() sets the type of image. Choose from these types:
1120 % Bilevel Grayscale GrayscaleMatte
1121 % Palette PaletteMatte TrueColor
1122 % TrueColorMatte ColorSeparation ColorSeparationMatte
1125 % The format of the SetImageType method is:
1127 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1128 % ExceptionInfo *exception)
1130 % A description of each parameter follows:
1132 % o image: the image.
1134 % o type: Image type.
1136 % o exception: return any errors or warnings in this structure.
1139 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1140 ExceptionInfo *exception)
1154 assert(image != (Image *) NULL);
1155 if (image->debug != MagickFalse)
1156 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1157 assert(image->signature == MagickSignature);
1159 image_info=AcquireImageInfo();
1160 image_info->dither=image->dither;
1161 artifact=GetImageArtifact(image,"dither");
1162 if (artifact != (const char *) NULL)
1163 (void) SetImageOption(image_info,"dither",artifact);
1168 if (IsImageGray(image,exception) == MagickFalse)
1169 status=TransformImageColorspace(image,GRAYColorspace,exception);
1170 (void) NormalizeImage(image,exception);
1171 if (IsImageMonochrome(image,exception) == MagickFalse)
1173 quantize_info=AcquireQuantizeInfo(image_info);
1174 quantize_info->number_colors=2;
1175 quantize_info->colorspace=GRAYColorspace;
1176 status=QuantizeImage(quantize_info,image,exception);
1177 quantize_info=DestroyQuantizeInfo(quantize_info);
1179 image->alpha_trait=UndefinedPixelTrait;
1184 if (IsImageGray(image,exception) == MagickFalse)
1185 status=TransformImageColorspace(image,GRAYColorspace,exception);
1186 image->alpha_trait=UndefinedPixelTrait;
1189 case GrayscaleMatteType:
1191 if (IsImageGray(image,exception) == MagickFalse)
1192 status=TransformImageColorspace(image,GRAYColorspace,exception);
1193 if (image->alpha_trait != BlendPixelTrait)
1194 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1199 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1200 status=TransformImageColorspace(image,sRGBColorspace,exception);
1201 if ((image->storage_class == DirectClass) || (image->colors > 256))
1203 quantize_info=AcquireQuantizeInfo(image_info);
1204 quantize_info->number_colors=256;
1205 status=QuantizeImage(quantize_info,image,exception);
1206 quantize_info=DestroyQuantizeInfo(quantize_info);
1208 image->alpha_trait=UndefinedPixelTrait;
1211 case PaletteBilevelMatteType:
1216 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1217 status=TransformImageColorspace(image,sRGBColorspace,exception);
1218 if (image->alpha_trait != BlendPixelTrait)
1219 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1220 channel_mask=SetImageChannelMask(image,AlphaChannel);
1221 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1222 (void) SetImageChannelMask(image,channel_mask);
1223 quantize_info=AcquireQuantizeInfo(image_info);
1224 status=QuantizeImage(quantize_info,image,exception);
1225 quantize_info=DestroyQuantizeInfo(quantize_info);
1228 case PaletteMatteType:
1230 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1231 status=TransformImageColorspace(image,sRGBColorspace,exception);
1232 if (image->alpha_trait != BlendPixelTrait)
1233 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1234 quantize_info=AcquireQuantizeInfo(image_info);
1235 quantize_info->colorspace=TransparentColorspace;
1236 status=QuantizeImage(quantize_info,image,exception);
1237 quantize_info=DestroyQuantizeInfo(quantize_info);
1242 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1243 status=TransformImageColorspace(image,sRGBColorspace,exception);
1244 if (image->storage_class != DirectClass)
1245 status=SetImageStorageClass(image,DirectClass,exception);
1246 image->alpha_trait=UndefinedPixelTrait;
1249 case TrueColorMatteType:
1251 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1252 status=TransformImageColorspace(image,sRGBColorspace,exception);
1253 if (image->storage_class != DirectClass)
1254 status=SetImageStorageClass(image,DirectClass,exception);
1255 if (image->alpha_trait != BlendPixelTrait)
1256 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1259 case ColorSeparationType:
1261 if (image->colorspace != CMYKColorspace)
1263 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1264 status=TransformImageColorspace(image,sRGBColorspace,exception);
1265 status=TransformImageColorspace(image,CMYKColorspace,exception);
1267 if (image->storage_class != DirectClass)
1268 status=SetImageStorageClass(image,DirectClass,exception);
1269 image->alpha_trait=UndefinedPixelTrait;
1272 case ColorSeparationMatteType:
1274 if (image->colorspace != CMYKColorspace)
1276 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1277 status=TransformImageColorspace(image,sRGBColorspace,exception);
1278 status=TransformImageColorspace(image,CMYKColorspace,exception);
1280 if (image->storage_class != DirectClass)
1281 status=SetImageStorageClass(image,DirectClass,exception);
1282 if (image->alpha_trait != BlendPixelTrait)
1283 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1290 image_info=DestroyImageInfo(image_info);
1291 if (status == MagickFalse)