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-2013 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 (id=0; id < (ssize_t) number_threads; id++)
306 if ((image->storage_class == PseudoClass) && (image->alpha_trait != BlendPixelTrait))
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 ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
332 status&=ClampToQuantum(image->colormap[i].red) !=
333 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum(
334 image->colormap[i].red),range),range);
335 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
336 status&=ClampToQuantum(image->colormap[i].green) !=
337 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum(
338 image->colormap[i].green),range),range);
339 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
340 status&=ClampToQuantum(image->colormap[i].blue) !=
341 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum(
342 image->colormap[i].blue),range),range);
348 depth=current_depth[0];
349 for (id=1; id < (ssize_t) number_threads; id++)
350 if (depth < current_depth[id])
351 depth=current_depth[id];
352 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
355 image_view=AcquireVirtualCacheView(image,exception);
356 #if !defined(MAGICKCORE_HDRI_SUPPORT)
357 if (QuantumRange <= MaxMap)
366 Scale pixels to desired (optimized with depth map).
368 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
369 if (depth_map == (size_t *) NULL)
370 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
371 for (i=0; i <= (ssize_t) MaxMap; i++)
376 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
384 range=GetQuantumRange(depth);
386 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
391 #if defined(MAGICKCORE_OPENMP_SUPPORT)
392 #pragma omp parallel for schedule(static,4) shared(status) \
393 magick_threads(image,image,image->rows,1)
395 for (y=0; y < (ssize_t) image->rows; y++)
398 id = GetOpenMPThreadId();
400 register const Quantum
406 if (status == MagickFalse)
408 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
409 if (p == (const Quantum *) NULL)
411 for (x=0; x < (ssize_t) image->columns; x++)
416 if (GetPixelReadMask(image,p) == 0)
418 p+=GetPixelChannels(image);
421 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
423 PixelChannel channel=GetPixelChannelChannel(image,i);
424 PixelTrait traits=GetPixelChannelTraits(image,channel);
425 if ((traits == UndefinedPixelTrait) ||
426 (channel == IndexPixelChannel) ||
427 (channel == ReadMaskPixelChannel) ||
428 (channel == MetaPixelChannel))
430 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
431 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
433 p+=GetPixelChannels(image);
435 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
438 image_view=DestroyCacheView(image_view);
439 depth=current_depth[0];
440 for (id=1; id < (ssize_t) number_threads; id++)
441 if (depth < current_depth[id])
442 depth=current_depth[id];
443 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
444 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
451 #if defined(MAGICKCORE_OPENMP_SUPPORT)
452 #pragma omp parallel for schedule(static,4) shared(status) \
453 magick_threads(image,image,image->rows,1)
455 for (y=0; y < (ssize_t) image->rows; y++)
458 id = GetOpenMPThreadId();
460 register const Quantum
466 if (status == MagickFalse)
468 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
469 if (p == (const Quantum *) NULL)
471 for (x=0; x < (ssize_t) image->columns; x++)
476 if (GetPixelReadMask(image,p) == 0)
478 p+=GetPixelChannels(image);
481 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
489 channel=GetPixelChannelChannel(image,i);
490 traits=GetPixelChannelTraits(image,channel);
491 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
492 (channel == ReadMaskPixelChannel))
494 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
499 range=GetQuantumRange(current_depth[id]);
500 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
505 p+=GetPixelChannels(image);
507 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
510 image_view=DestroyCacheView(image_view);
511 depth=current_depth[0];
512 for (id=1; id < (ssize_t) number_threads; id++)
513 if (depth < current_depth[id])
514 depth=current_depth[id];
515 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 % G e t I m a g e Q u a n t u m D e p t h %
528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
531 % quantum depth: 8, 16, or 32.
533 % The format of the GetImageQuantumDepth method is:
535 % size_t GetImageQuantumDepth(const Image *image,
536 % const MagickBooleanType constrain)
538 % A description of each parameter follows:
540 % o image: the image.
542 % o constrain: A value other than MagickFalse, constrains the depth to
543 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
547 static inline double MagickMin(const double x,const double y)
554 MagickExport size_t GetImageQuantumDepth(const Image *image,
555 const MagickBooleanType constrain)
572 if (constrain != MagickFalse)
573 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 % G e t I m a g e T y p e %
586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 % GetImageType() returns the potential type of image:
590 % Bilevel Grayscale GrayscaleMatte
591 % Palette PaletteMatte TrueColor
592 % TrueColorMatte ColorSeparation ColorSeparationMatte
594 % To ensure the image type matches its potential, use SetImageType():
596 % (void) SetImageType(image,GetImageType(image));
598 % The format of the GetImageType method is:
600 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
602 % A description of each parameter follows:
604 % o image: the image.
606 % o exception: return any errors or warnings in this structure.
609 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
611 assert(image != (Image *) NULL);
612 assert(image->signature == MagickSignature);
613 if (image->debug != MagickFalse)
614 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
615 if (image->colorspace == CMYKColorspace)
617 if (image->alpha_trait != BlendPixelTrait)
618 return(ColorSeparationType);
619 return(ColorSeparationMatteType);
621 if (IsImageMonochrome(image,exception) != MagickFalse)
623 if (IsImageGray(image,exception) != MagickFalse)
625 if (image->alpha_trait == BlendPixelTrait)
626 return(GrayscaleMatteType);
627 return(GrayscaleType);
629 if (IsPaletteImage(image,exception) != MagickFalse)
631 if (image->alpha_trait == BlendPixelTrait)
632 return(PaletteMatteType);
635 if (image->alpha_trait == BlendPixelTrait)
636 return(TrueColorMatteType);
637 return(TrueColorType);
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645 % I s I m a g e G r a y %
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 % IsImageGray() returns MagickTrue if all the pixels in the image have the
652 % same red, green, and blue intensities.
654 % The format of the IsImageGray method is:
656 % MagickBooleanType IsImageGray(const Image *image,
657 % ExceptionInfo *exception)
659 % A description of each parameter follows:
661 % o image: the image.
663 % o exception: return any errors or warnings in this structure.
666 MagickExport MagickBooleanType IsImageGray(const Image *image,
667 ExceptionInfo *exception)
675 register const Quantum
684 assert(image != (Image *) NULL);
685 assert(image->signature == MagickSignature);
686 if (image->debug != MagickFalse)
687 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
688 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
689 (image->type == GrayscaleMatteType))
691 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
692 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
695 image_view=AcquireVirtualCacheView(image,exception);
696 for (y=0; y < (ssize_t) image->rows; y++)
698 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
699 if (p == (const Quantum *) NULL)
701 for (x=0; x < (ssize_t) image->columns; x++)
703 if (IsPixelGray(image,p) == MagickFalse)
708 if ((type == BilevelType) &&
709 (IsPixelMonochrome(image,p) == MagickFalse))
711 p+=GetPixelChannels(image);
713 if (type == UndefinedType)
716 image_view=DestroyCacheView(image_view);
717 if (type == UndefinedType)
719 ((Image *) image)->colorspace=GRAYColorspace;
720 ((Image *) image)->type=type;
721 if ((type == GrayscaleType) && (image->alpha_trait == BlendPixelTrait))
722 ((Image *) image)->type=GrayscaleMatteType;
723 return(SyncImagePixelCache((Image *) image,exception));
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731 % I s I m a g e M o n o c h r o m e %
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have
738 % the same red, green, and blue intensities and the intensity is either
741 % The format of the IsImageMonochrome method is:
743 % MagickBooleanType IsImageMonochrome(const Image *image,
744 % ExceptionInfo *exception)
746 % A description of each parameter follows:
748 % o image: the image.
750 % o exception: return any errors or warnings in this structure.
753 MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
754 ExceptionInfo *exception)
765 register const Quantum
771 assert(image != (Image *) NULL);
772 assert(image->signature == MagickSignature);
773 if (image->debug != MagickFalse)
774 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
775 if (image->type == BilevelType)
777 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
778 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
781 image_view=AcquireVirtualCacheView(image,exception);
782 for (y=0; y < (ssize_t) image->rows; y++)
784 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
785 if (p == (const Quantum *) NULL)
787 for (x=0; x < (ssize_t) image->columns; x++)
789 if (IsPixelMonochrome(image,p) == MagickFalse)
794 p+=GetPixelChannels(image);
796 if (type == UndefinedType)
799 image_view=DestroyCacheView(image_view);
800 if (type == UndefinedType)
802 ((Image *) image)->colorspace=GRAYColorspace;
803 ((Image *) image)->type=type;
804 return(SyncImagePixelCache((Image *) image,exception));
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812 % I s I m a g e O p a q u e %
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
818 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
819 % an alpha value other than OpaqueAlpha (QuantumRange).
821 % Will return true immediatally is alpha channel is not available.
823 % The format of the IsImageOpaque method is:
825 % MagickBooleanType IsImageOpaque(const Image *image,
826 % ExceptionInfo *exception)
828 % A description of each parameter follows:
830 % o image: the image.
832 % o exception: return any errors or warnings in this structure.
835 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
836 ExceptionInfo *exception)
841 register const Quantum
851 Determine if image is opaque.
853 assert(image != (Image *) NULL);
854 assert(image->signature == MagickSignature);
855 if (image->debug != MagickFalse)
856 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
857 if (image->alpha_trait != BlendPixelTrait)
859 image_view=AcquireVirtualCacheView(image,exception);
860 for (y=0; y < (ssize_t) image->rows; y++)
862 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
863 if (p == (const Quantum *) NULL)
865 for (x=0; x < (ssize_t) image->columns; x++)
867 if (GetPixelAlpha(image,p) != OpaqueAlpha)
869 p+=GetPixelChannels(image);
871 if (x < (ssize_t) image->columns)
874 image_view=DestroyCacheView(image_view);
875 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883 % S e t I m a g e D e p t h %
887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889 % SetImageDepth() sets the depth of the image.
891 % The format of the SetImageDepth method is:
893 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
894 % ExceptionInfo *exception)
896 % A description of each parameter follows:
898 % o image: the image.
900 % o channel: the channel.
902 % o depth: the image depth.
904 % o exception: return any errors or warnings in this structure.
907 MagickExport MagickBooleanType SetImageDepth(Image *image,
908 const size_t depth,ExceptionInfo *exception)
922 assert(image != (Image *) NULL);
923 if (image->debug != MagickFalse)
924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
925 assert(image->signature == MagickSignature);
926 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
931 range=GetQuantumRange(depth);
932 if (image->storage_class == PseudoClass)
937 #if defined(MAGICKCORE_OPENMP_SUPPORT)
938 #pragma omp parallel for schedule(static,4) shared(status) \
939 magick_threads(image,image,1,1)
941 for (i=0; i < (ssize_t) image->colors; i++)
943 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
944 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
945 ClampToQuantum(image->colormap[i].red),range),range);
946 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
947 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
948 ClampToQuantum(image->colormap[i].green),range),range);
949 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
950 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
951 ClampToQuantum(image->colormap[i].blue),range),range);
952 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
953 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
954 ClampToQuantum(image->colormap[i].alpha),range),range);
958 image_view=AcquireAuthenticCacheView(image,exception);
959 #if !defined(MAGICKCORE_HDRI_SUPPORT)
960 if (QuantumRange <= MaxMap)
969 Scale pixels to desired (optimized with depth map).
971 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
972 if (depth_map == (Quantum *) NULL)
973 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
974 for (i=0; i <= (ssize_t) MaxMap; i++)
975 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
977 #if defined(MAGICKCORE_OPENMP_SUPPORT)
978 #pragma omp parallel for schedule(static,4) shared(status) \
979 magick_threads(image,image,image->rows,1)
981 for (y=0; y < (ssize_t) image->rows; y++)
989 if (status == MagickFalse)
991 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
993 if (q == (Quantum *) NULL)
998 for (x=0; x < (ssize_t) image->columns; x++)
1003 if (GetPixelReadMask(image,q) == 0)
1005 q+=GetPixelChannels(image);
1008 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1016 channel=GetPixelChannelChannel(image,i);
1017 traits=GetPixelChannelTraits(image,channel);
1018 if ((traits == UndefinedPixelTrait) ||
1019 (channel == IndexPixelChannel) || (channel == ReadMaskPixelChannel))
1021 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1023 q+=GetPixelChannels(image);
1025 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1031 image_view=DestroyCacheView(image_view);
1032 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1033 if (status != MagickFalse)
1039 Scale pixels to desired depth.
1041 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1042 #pragma omp parallel for schedule(static,4) shared(status) \
1043 magick_threads(image,image,image->rows,1)
1045 for (y=0; y < (ssize_t) image->rows; y++)
1053 if (status == MagickFalse)
1055 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1056 if (q == (Quantum *) NULL)
1061 for (x=0; x < (ssize_t) image->columns; x++)
1066 if (GetPixelReadMask(image,q) == 0)
1068 q+=GetPixelChannels(image);
1071 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1079 channel=GetPixelChannelChannel(image,i);
1080 traits=GetPixelChannelTraits(image,channel);
1081 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1082 (channel == ReadMaskPixelChannel))
1084 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range);
1086 q+=GetPixelChannels(image);
1088 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1094 image_view=DestroyCacheView(image_view);
1095 if (status != MagickFalse)
1101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1105 % S e t I m a g e T y p e %
1109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 % SetImageType() sets the type of image. Choose from these types:
1113 % Bilevel Grayscale GrayscaleMatte
1114 % Palette PaletteMatte TrueColor
1115 % TrueColorMatte ColorSeparation ColorSeparationMatte
1118 % The format of the SetImageType method is:
1120 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1121 % ExceptionInfo *exception)
1123 % A description of each parameter follows:
1125 % o image: the image.
1127 % o type: Image type.
1129 % o exception: return any errors or warnings in this structure.
1132 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1133 ExceptionInfo *exception)
1147 assert(image != (Image *) NULL);
1148 if (image->debug != MagickFalse)
1149 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1150 assert(image->signature == MagickSignature);
1152 image_info=AcquireImageInfo();
1153 image_info->dither=image->dither;
1154 artifact=GetImageArtifact(image,"dither");
1155 if (artifact != (const char *) NULL)
1156 (void) SetImageOption(image_info,"dither",artifact);
1161 if (IsImageMonochrome(image,exception) == MagickFalse)
1163 quantize_info=AcquireQuantizeInfo(image_info);
1164 quantize_info->number_colors=2;
1165 quantize_info->colorspace=GRAYColorspace;
1166 status=QuantizeImage(quantize_info,image,exception);
1167 quantize_info=DestroyQuantizeInfo(quantize_info);
1169 image->alpha_trait=UndefinedPixelTrait;
1174 if (IsImageGray(image,exception) == MagickFalse)
1175 status=TransformImageColorspace(image,GRAYColorspace,exception);
1176 image->alpha_trait=UndefinedPixelTrait;
1179 case GrayscaleMatteType:
1181 if (IsImageGray(image,exception) == MagickFalse)
1182 status=TransformImageColorspace(image,GRAYColorspace,exception);
1183 if (image->alpha_trait != BlendPixelTrait)
1184 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1189 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1190 status=TransformImageColorspace(image,sRGBColorspace,exception);
1191 if ((image->storage_class == DirectClass) || (image->colors > 256))
1193 quantize_info=AcquireQuantizeInfo(image_info);
1194 quantize_info->number_colors=256;
1195 status=QuantizeImage(quantize_info,image,exception);
1196 quantize_info=DestroyQuantizeInfo(quantize_info);
1198 image->alpha_trait=UndefinedPixelTrait;
1201 case PaletteBilevelMatteType:
1206 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1207 status=TransformImageColorspace(image,sRGBColorspace,exception);
1208 if (image->alpha_trait != BlendPixelTrait)
1209 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1210 channel_mask=SetImageChannelMask(image,AlphaChannel);
1211 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1212 (void) SetImageChannelMask(image,channel_mask);
1213 quantize_info=AcquireQuantizeInfo(image_info);
1214 status=QuantizeImage(quantize_info,image,exception);
1215 quantize_info=DestroyQuantizeInfo(quantize_info);
1218 case PaletteMatteType:
1220 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1221 status=TransformImageColorspace(image,sRGBColorspace,exception);
1222 if (image->alpha_trait != BlendPixelTrait)
1223 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1224 quantize_info=AcquireQuantizeInfo(image_info);
1225 quantize_info->colorspace=TransparentColorspace;
1226 status=QuantizeImage(quantize_info,image,exception);
1227 quantize_info=DestroyQuantizeInfo(quantize_info);
1232 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1233 status=TransformImageColorspace(image,sRGBColorspace,exception);
1234 if (image->storage_class != DirectClass)
1235 status=SetImageStorageClass(image,DirectClass,exception);
1236 image->alpha_trait=UndefinedPixelTrait;
1239 case TrueColorMatteType:
1241 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1242 status=TransformImageColorspace(image,sRGBColorspace,exception);
1243 if (image->storage_class != DirectClass)
1244 status=SetImageStorageClass(image,DirectClass,exception);
1245 if (image->alpha_trait != BlendPixelTrait)
1246 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1249 case ColorSeparationType:
1251 if (image->colorspace != CMYKColorspace)
1253 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1254 status=TransformImageColorspace(image,sRGBColorspace,exception);
1255 status=TransformImageColorspace(image,CMYKColorspace,exception);
1257 if (image->storage_class != DirectClass)
1258 status=SetImageStorageClass(image,DirectClass,exception);
1259 image->alpha_trait=UndefinedPixelTrait;
1262 case ColorSeparationMatteType:
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 if (image->alpha_trait != BlendPixelTrait)
1273 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1281 image_info=DestroyImageInfo(image_info);