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.
899 MagickExport MagickBooleanType SetImageDepth(Image *image,
900 const size_t depth,ExceptionInfo *exception)
914 assert(image != (Image *) NULL);
915 if (image->debug != MagickFalse)
916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
917 assert(image->signature == MagickSignature);
918 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
923 range=GetQuantumRange(depth);
924 if (image->storage_class == PseudoClass)
929 #if defined(MAGICKCORE_OPENMP_SUPPORT)
930 #pragma omp parallel for schedule(static,4) shared(status) \
931 magick_threads(image,image,1,1)
933 for (i=0; i < (ssize_t) image->colors; i++)
935 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
936 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
937 ClampToQuantum(image->colormap[i].red),range),range);
938 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
939 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
940 ClampToQuantum(image->colormap[i].green),range),range);
941 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
942 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
943 ClampToQuantum(image->colormap[i].blue),range),range);
944 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
945 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
946 ClampToQuantum(image->colormap[i].alpha),range),range);
950 image_view=AcquireAuthenticCacheView(image,exception);
951 #if !defined(MAGICKCORE_HDRI_SUPPORT)
952 if (QuantumRange <= MaxMap)
961 Scale pixels to desired (optimized with depth map).
963 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
964 if (depth_map == (Quantum *) NULL)
965 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
966 for (i=0; i <= (ssize_t) MaxMap; i++)
967 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
969 #if defined(MAGICKCORE_OPENMP_SUPPORT)
970 #pragma omp parallel for schedule(static,4) shared(status) \
971 magick_threads(image,image,image->rows,1)
973 for (y=0; y < (ssize_t) image->rows; y++)
981 if (status == MagickFalse)
983 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
985 if (q == (Quantum *) NULL)
990 for (x=0; x < (ssize_t) image->columns; x++)
995 if (GetPixelReadMask(image,q) == 0)
997 q+=GetPixelChannels(image);
1000 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1008 channel=GetPixelChannelChannel(image,i);
1009 traits=GetPixelChannelTraits(image,channel);
1010 if ((traits == UndefinedPixelTrait) ||
1011 (channel == IndexPixelChannel) || (channel == ReadMaskPixelChannel))
1013 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1015 q+=GetPixelChannels(image);
1017 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1023 image_view=DestroyCacheView(image_view);
1024 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1025 if (status != MagickFalse)
1031 Scale pixels to desired depth.
1033 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1034 #pragma omp parallel for schedule(static,4) shared(status) \
1035 magick_threads(image,image,image->rows,1)
1037 for (y=0; y < (ssize_t) image->rows; y++)
1045 if (status == MagickFalse)
1047 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1048 if (q == (Quantum *) NULL)
1053 for (x=0; x < (ssize_t) image->columns; x++)
1058 if (GetPixelReadMask(image,q) == 0)
1060 q+=GetPixelChannels(image);
1063 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1071 channel=GetPixelChannelChannel(image,i);
1072 traits=GetPixelChannelTraits(image,channel);
1073 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1074 (channel == ReadMaskPixelChannel))
1076 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range);
1078 q+=GetPixelChannels(image);
1080 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1086 image_view=DestroyCacheView(image_view);
1087 if (status != MagickFalse)
1093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1097 % S e t I m a g e T y p e %
1101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103 % SetImageType() sets the type of image. Choose from these types:
1105 % Bilevel Grayscale GrayscaleMatte
1106 % Palette PaletteMatte TrueColor
1107 % TrueColorMatte ColorSeparation ColorSeparationMatte
1110 % The format of the SetImageType method is:
1112 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1113 % ExceptionInfo *exception)
1115 % A description of each parameter follows:
1117 % o image: the image.
1119 % o type: Image type.
1121 % o exception: return any errors or warnings in this structure.
1124 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1125 ExceptionInfo *exception)
1139 assert(image != (Image *) NULL);
1140 if (image->debug != MagickFalse)
1141 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1142 assert(image->signature == MagickSignature);
1144 image_info=AcquireImageInfo();
1145 image_info->dither=image->dither;
1146 artifact=GetImageArtifact(image,"dither");
1147 if (artifact != (const char *) NULL)
1148 (void) SetImageOption(image_info,"dither",artifact);
1153 if (IsImageGray(image,exception) == MagickFalse)
1154 status=TransformImageColorspace(image,GRAYColorspace,exception);
1155 (void) NormalizeImage(image,exception);
1156 if (IsImageMonochrome(image,exception) == MagickFalse)
1158 quantize_info=AcquireQuantizeInfo(image_info);
1159 quantize_info->number_colors=2;
1160 quantize_info->colorspace=GRAYColorspace;
1161 status=QuantizeImage(quantize_info,image,exception);
1162 quantize_info=DestroyQuantizeInfo(quantize_info);
1164 image->alpha_trait=UndefinedPixelTrait;
1169 if (IsImageGray(image,exception) == MagickFalse)
1170 status=TransformImageColorspace(image,GRAYColorspace,exception);
1171 image->alpha_trait=UndefinedPixelTrait;
1174 case GrayscaleMatteType:
1176 if (IsImageGray(image,exception) == MagickFalse)
1177 status=TransformImageColorspace(image,GRAYColorspace,exception);
1178 if (image->alpha_trait != BlendPixelTrait)
1179 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1184 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1185 status=TransformImageColorspace(image,sRGBColorspace,exception);
1186 if ((image->storage_class == DirectClass) || (image->colors > 256))
1188 quantize_info=AcquireQuantizeInfo(image_info);
1189 quantize_info->number_colors=256;
1190 status=QuantizeImage(quantize_info,image,exception);
1191 quantize_info=DestroyQuantizeInfo(quantize_info);
1193 image->alpha_trait=UndefinedPixelTrait;
1196 case PaletteBilevelMatteType:
1201 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1202 status=TransformImageColorspace(image,sRGBColorspace,exception);
1203 if (image->alpha_trait != BlendPixelTrait)
1204 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1205 channel_mask=SetImageChannelMask(image,AlphaChannel);
1206 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1207 (void) SetImageChannelMask(image,channel_mask);
1208 quantize_info=AcquireQuantizeInfo(image_info);
1209 status=QuantizeImage(quantize_info,image,exception);
1210 quantize_info=DestroyQuantizeInfo(quantize_info);
1213 case PaletteMatteType:
1215 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1216 status=TransformImageColorspace(image,sRGBColorspace,exception);
1217 if (image->alpha_trait != BlendPixelTrait)
1218 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1219 quantize_info=AcquireQuantizeInfo(image_info);
1220 quantize_info->colorspace=TransparentColorspace;
1221 status=QuantizeImage(quantize_info,image,exception);
1222 quantize_info=DestroyQuantizeInfo(quantize_info);
1227 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1228 status=TransformImageColorspace(image,sRGBColorspace,exception);
1229 if (image->storage_class != DirectClass)
1230 status=SetImageStorageClass(image,DirectClass,exception);
1231 image->alpha_trait=UndefinedPixelTrait;
1234 case TrueColorMatteType:
1236 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1237 status=TransformImageColorspace(image,sRGBColorspace,exception);
1238 if (image->storage_class != DirectClass)
1239 status=SetImageStorageClass(image,DirectClass,exception);
1240 if (image->alpha_trait != BlendPixelTrait)
1241 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1244 case ColorSeparationType:
1246 if (image->colorspace != CMYKColorspace)
1248 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1249 status=TransformImageColorspace(image,sRGBColorspace,exception);
1250 status=TransformImageColorspace(image,CMYKColorspace,exception);
1252 if (image->storage_class != DirectClass)
1253 status=SetImageStorageClass(image,DirectClass,exception);
1254 image->alpha_trait=UndefinedPixelTrait;
1257 case ColorSeparationMatteType:
1259 if (image->colorspace != CMYKColorspace)
1261 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1262 status=TransformImageColorspace(image,sRGBColorspace,exception);
1263 status=TransformImageColorspace(image,CMYKColorspace,exception);
1265 if (image->storage_class != DirectClass)
1266 status=SetImageStorageClass(image,DirectClass,exception);
1267 if (image->alpha_trait != BlendPixelTrait)
1268 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1275 image_info=DestroyImageInfo(image_info);
1276 if (status == MagickFalse)