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-view.h"
50 #include "MagickCore/client.h"
51 #include "MagickCore/color.h"
52 #include "MagickCore/color-private.h"
53 #include "MagickCore/colormap.h"
54 #include "MagickCore/colormap-private.h"
55 #include "MagickCore/colorspace.h"
56 #include "MagickCore/colorspace-private.h"
57 #include "MagickCore/composite.h"
58 #include "MagickCore/composite-private.h"
59 #include "MagickCore/constitute.h"
60 #include "MagickCore/draw.h"
61 #include "MagickCore/draw-private.h"
62 #include "MagickCore/effect.h"
63 #include "MagickCore/enhance.h"
64 #include "MagickCore/exception.h"
65 #include "MagickCore/exception-private.h"
66 #include "MagickCore/geometry.h"
67 #include "MagickCore/histogram.h"
68 #include "MagickCore/identify.h"
69 #include "MagickCore/image.h"
70 #include "MagickCore/image-private.h"
71 #include "MagickCore/list.h"
72 #include "MagickCore/log.h"
73 #include "MagickCore/memory_.h"
74 #include "MagickCore/magick.h"
75 #include "MagickCore/monitor.h"
76 #include "MagickCore/monitor-private.h"
77 #include "MagickCore/option.h"
78 #include "MagickCore/paint.h"
79 #include "MagickCore/pixel.h"
80 #include "MagickCore/pixel-accessor.h"
81 #include "MagickCore/property.h"
82 #include "MagickCore/quantize.h"
83 #include "MagickCore/quantum-private.h"
84 #include "MagickCore/random_.h"
85 #include "MagickCore/resource_.h"
86 #include "MagickCore/semaphore.h"
87 #include "MagickCore/segment.h"
88 #include "MagickCore/splay-tree.h"
89 #include "MagickCore/string_.h"
90 #include "MagickCore/thread-private.h"
91 #include "MagickCore/threshold.h"
92 #include "MagickCore/transform.h"
93 #include "MagickCore/utility.h"
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100 + G e t I m a g e B o u n d i n g B o x %
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 % GetImageBoundingBox() returns the bounding box of an image canvas.
108 % The format of the GetImageBoundingBox method is:
110 % RectangleInfo GetImageBoundingBox(const Image *image,
111 % ExceptionInfo *exception)
113 % A description of each parameter follows:
115 % o bounds: Method GetImageBoundingBox returns the bounding box of an
118 % o image: the image.
120 % o exception: return any errors or warnings in this structure.
123 MagickExport RectangleInfo GetImageBoundingBox(const Image *image,
124 ExceptionInfo *exception)
139 register const Quantum
145 assert(image != (Image *) NULL);
146 assert(image->signature == MagickSignature);
147 if (image->debug != MagickFalse)
148 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
151 bounds.x=(ssize_t) image->columns;
152 bounds.y=(ssize_t) image->rows;
153 GetPixelInfo(image,&target[0]);
154 image_view=AcquireVirtualCacheView(image,exception);
155 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
156 if (p == (const Quantum *) NULL)
158 image_view=DestroyCacheView(image_view);
161 GetPixelInfoPixel(image,p,&target[0]);
162 GetPixelInfo(image,&target[1]);
163 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
165 GetPixelInfoPixel(image,p,&target[1]);
166 GetPixelInfo(image,&target[2]);
167 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
169 GetPixelInfoPixel(image,p,&target[2]);
171 GetPixelInfo(image,&zero);
172 #if defined(MAGICKCORE_OPENMP_SUPPORT)
173 #pragma omp parallel for schedule(static,4) shared(status) \
174 dynamic_number_threads(image,image->columns,image->rows,1)
176 for (y=0; y < (ssize_t) image->rows; y++)
184 register const Quantum
190 if (status == MagickFalse)
192 #if defined(MAGICKCORE_OPENMP_SUPPORT)
193 # pragma omp critical (MagickCore_GetImageBoundingBox)
196 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
197 if (p == (const Quantum *) NULL)
203 for (x=0; x < (ssize_t) image->columns; x++)
205 GetPixelInfoPixel(image,p,&pixel);
206 if ((x < bounding_box.x) &&
207 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
209 if ((x > (ssize_t) bounding_box.width) &&
210 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
211 bounding_box.width=(size_t) x;
212 if ((y < bounding_box.y) &&
213 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
215 if ((y > (ssize_t) bounding_box.height) &&
216 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
217 bounding_box.height=(size_t) y;
218 p+=GetPixelChannels(image);
220 #if defined(MAGICKCORE_OPENMP_SUPPORT)
221 # pragma omp critical (MagickCore_GetImageBoundingBox)
224 if (bounding_box.x < bounds.x)
225 bounds.x=bounding_box.x;
226 if (bounding_box.y < bounds.y)
227 bounds.y=bounding_box.y;
228 if (bounding_box.width > bounds.width)
229 bounds.width=bounding_box.width;
230 if (bounding_box.height > bounds.height)
231 bounds.height=bounding_box.height;
234 image_view=DestroyCacheView(image_view);
235 if ((bounds.width == 0) || (bounds.height == 0))
236 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
237 "GeometryDoesNotContainImage","'%s'",image->filename);
240 bounds.width-=(bounds.x-1);
241 bounds.height-=(bounds.y-1);
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251 % G e t I m a g e D e p t h %
255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 % GetImageDepth() returns the depth of a particular image channel.
259 % The format of the GetImageDepth method is:
261 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
263 % A description of each parameter follows:
265 % o image: the image.
267 % o exception: return any errors or warnings in this structure.
270 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
292 assert(image != (Image *) NULL);
293 assert(image->signature == MagickSignature);
294 if (image->debug != MagickFalse)
295 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
296 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
297 current_depth=(size_t *) AcquireQuantumMemory(number_threads,
298 sizeof(*current_depth));
299 if (current_depth == (size_t *) NULL)
300 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
302 for (id=0; id < (ssize_t) number_threads; id++)
304 if ((image->storage_class == PseudoClass) && (image->alpha_trait != BlendPixelTrait))
309 #if defined(MAGICKCORE_OPENMP_SUPPORT)
310 #pragma omp parallel for schedule(static,4) shared(status) \
311 if ((image->colors) > 256) \
312 num_threads(GetMagickResourceLimit(ThreadResource))
314 for (i=0; i < (ssize_t) image->colors; i++)
317 id = GetOpenMPThreadId();
319 if (status == MagickFalse)
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 dynamic_number_threads(image,image->columns,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 (GetPixelMask(image,p) != 0)
418 p+=GetPixelChannels(image);
421 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
429 channel=GetPixelChannelChannel(image,i);
430 traits=GetPixelChannelTraits(image,channel);
431 if ((traits == UndefinedPixelTrait) ||
432 (channel == IndexPixelChannel) || (channel == MaskPixelChannel))
434 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
435 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
437 p+=GetPixelChannels(image);
439 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
442 image_view=DestroyCacheView(image_view);
443 depth=current_depth[0];
444 for (id=1; id < (ssize_t) number_threads; id++)
445 if (depth < current_depth[id])
446 depth=current_depth[id];
447 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
448 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
455 #if defined(MAGICKCORE_OPENMP_SUPPORT)
456 #pragma omp parallel for schedule(static,4) shared(status) \
457 dynamic_number_threads(image,image->columns,image->rows,1)
459 for (y=0; y < (ssize_t) image->rows; y++)
462 id = GetOpenMPThreadId();
464 register const Quantum
470 if (status == MagickFalse)
472 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
473 if (p == (const Quantum *) NULL)
475 for (x=0; x < (ssize_t) image->columns; x++)
480 if (GetPixelMask(image,p) != 0)
482 p+=GetPixelChannels(image);
485 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
493 channel=GetPixelChannelChannel(image,i);
494 traits=GetPixelChannelTraits(image,channel);
495 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
496 (channel == MaskPixelChannel))
498 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
503 range=GetQuantumRange(current_depth[id]);
504 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
509 p+=GetPixelChannels(image);
511 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
514 image_view=DestroyCacheView(image_view);
515 depth=current_depth[0];
516 for (id=1; id < (ssize_t) number_threads; id++)
517 if (depth < current_depth[id])
518 depth=current_depth[id];
519 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528 % G e t I m a g e Q u a n t u m D e p t h %
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
535 % quantum depth: 8, 16, or 32.
537 % The format of the GetImageQuantumDepth method is:
539 % size_t GetImageQuantumDepth(const Image *image,
540 % const MagickBooleanType constrain)
542 % A description of each parameter follows:
544 % o image: the image.
546 % o constrain: A value other than MagickFalse, constrains the depth to
547 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
551 static inline double MagickMin(const double x,const double y)
558 MagickExport size_t GetImageQuantumDepth(const Image *image,
559 const MagickBooleanType constrain)
576 if (constrain != MagickFalse)
577 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 % G e t I m a g e T y p e %
590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 % GetImageType() returns the potential type of image:
594 % Bilevel Grayscale GrayscaleMatte
595 % Palette PaletteMatte TrueColor
596 % TrueColorMatte ColorSeparation ColorSeparationMatte
598 % To ensure the image type matches its potential, use SetImageType():
600 % (void) SetImageType(image,GetImageType(image));
602 % The format of the GetImageType method is:
604 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
606 % A description of each parameter follows:
608 % o image: the image.
610 % o exception: return any errors or warnings in this structure.
613 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
615 assert(image != (Image *) NULL);
616 assert(image->signature == MagickSignature);
617 if (image->debug != MagickFalse)
618 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
619 if (image->colorspace == CMYKColorspace)
621 if (image->alpha_trait != BlendPixelTrait)
622 return(ColorSeparationType);
623 return(ColorSeparationMatteType);
625 if (IsImageMonochrome(image,exception) != MagickFalse)
627 if (IsImageGray(image,exception) != MagickFalse)
629 if (image->alpha_trait == BlendPixelTrait)
630 return(GrayscaleMatteType);
631 return(GrayscaleType);
633 if (IsPaletteImage(image,exception) != MagickFalse)
635 if (image->alpha_trait == BlendPixelTrait)
636 return(PaletteMatteType);
639 if (image->alpha_trait == BlendPixelTrait)
640 return(TrueColorMatteType);
641 return(TrueColorType);
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % I s I m a g e G r a y %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655 % IsImageGray() returns MagickTrue if all the pixels in the image have the
656 % same red, green, and blue intensities.
658 % The format of the IsImageGray method is:
660 % MagickBooleanType IsImageGray(const Image *image,
661 % ExceptionInfo *exception)
663 % A description of each parameter follows:
665 % o image: the image.
667 % o exception: return any errors or warnings in this structure.
670 MagickExport MagickBooleanType IsImageGray(const Image *image,
671 ExceptionInfo *exception)
679 register const Quantum
688 assert(image != (Image *) NULL);
689 assert(image->signature == MagickSignature);
690 if (image->debug != MagickFalse)
691 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
692 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
693 (image->type == GrayscaleMatteType))
695 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
696 (IsRGBColorspace(image->colorspace) == MagickFalse))
699 image_view=AcquireVirtualCacheView(image,exception);
700 for (y=0; y < (ssize_t) image->rows; y++)
702 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
703 if (p == (const Quantum *) NULL)
705 for (x=0; x < (ssize_t) image->columns; x++)
707 if (IsPixelGray(image,p) == MagickFalse)
712 if ((type == BilevelType) &&
713 (IsPixelMonochrome(image,p) == MagickFalse))
715 p+=GetPixelChannels(image);
717 if (type == UndefinedType)
720 image_view=DestroyCacheView(image_view);
721 if (type == UndefinedType)
723 ((Image *) image)->type=type;
724 if ((type == GrayscaleType) && (image->alpha_trait == BlendPixelTrait))
725 ((Image *) image)->type=GrayscaleMatteType;
730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
734 % I s I m a g e M o n o c h r o m e %
738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
740 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have
741 % the same red, green, and blue intensities and the intensity is either
744 % The format of the IsImageMonochrome method is:
746 % MagickBooleanType IsImageMonochrome(const Image *image,
747 % ExceptionInfo *exception)
749 % A description of each parameter follows:
751 % o image: the image.
753 % o exception: return any errors or warnings in this structure.
756 MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
757 ExceptionInfo *exception)
768 register const Quantum
774 assert(image != (Image *) NULL);
775 assert(image->signature == MagickSignature);
776 if (image->debug != MagickFalse)
777 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
778 if (image->type == BilevelType)
780 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
781 (IsRGBColorspace(image->colorspace) == MagickFalse))
784 image_view=AcquireVirtualCacheView(image,exception);
785 for (y=0; y < (ssize_t) image->rows; y++)
787 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
788 if (p == (const Quantum *) NULL)
790 for (x=0; x < (ssize_t) image->columns; x++)
792 if (IsPixelMonochrome(image,p) == MagickFalse)
797 p+=GetPixelChannels(image);
799 if (type == UndefinedType)
802 image_view=DestroyCacheView(image_view);
803 if (type == UndefinedType)
805 ((Image *) image)->type=type;
810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 % I s I m a g e O p a q u e %
818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
821 % an alpha value other than OpaqueAlpha (QuantumRange).
823 % Will return true immediatally is alpha channel is not available.
825 % The format of the IsImageOpaque method is:
827 % MagickBooleanType IsImageOpaque(const Image *image,
828 % ExceptionInfo *exception)
830 % A description of each parameter follows:
832 % o image: the image.
834 % o exception: return any errors or warnings in this structure.
837 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
838 ExceptionInfo *exception)
843 register const Quantum
853 Determine if image is opaque.
855 assert(image != (Image *) NULL);
856 assert(image->signature == MagickSignature);
857 if (image->debug != MagickFalse)
858 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
859 if (image->alpha_trait != BlendPixelTrait)
861 image_view=AcquireVirtualCacheView(image,exception);
862 for (y=0; y < (ssize_t) image->rows; y++)
864 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
865 if (p == (const Quantum *) NULL)
867 for (x=0; x < (ssize_t) image->columns; x++)
869 if (GetPixelAlpha(image,p) != OpaqueAlpha)
871 p+=GetPixelChannels(image);
873 if (x < (ssize_t) image->columns)
876 image_view=DestroyCacheView(image_view);
877 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885 % S e t I m a g e D e p t h %
889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 % SetImageDepth() sets the depth of the image.
893 % The format of the SetImageDepth method is:
895 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
896 % ExceptionInfo *exception)
898 % A description of each parameter follows:
900 % o image: the image.
902 % o channel: the channel.
904 % o depth: the image depth.
906 % o exception: return any errors or warnings in this structure.
909 MagickExport MagickBooleanType SetImageDepth(Image *image,
910 const size_t depth,ExceptionInfo *exception)
924 assert(image != (Image *) NULL);
925 if (image->debug != MagickFalse)
926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
927 assert(image->signature == MagickSignature);
928 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
933 range=GetQuantumRange(depth);
934 if (image->storage_class == PseudoClass)
939 #if defined(MAGICKCORE_OPENMP_SUPPORT)
940 #pragma omp parallel for schedule(static,4) shared(status) \
941 dynamic_number_threads(image,image->columns,1,1)
943 for (i=0; i < (ssize_t) image->colors; i++)
945 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
946 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
947 ClampToQuantum(image->colormap[i].red),range),range);
948 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
949 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
950 ClampToQuantum(image->colormap[i].green),range),range);
951 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
952 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
953 ClampToQuantum(image->colormap[i].blue),range),range);
954 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
955 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
956 ClampToQuantum(image->colormap[i].alpha),range),range);
960 image_view=AcquireAuthenticCacheView(image,exception);
961 #if !defined(MAGICKCORE_HDRI_SUPPORT)
962 if (QuantumRange <= MaxMap)
971 Scale pixels to desired (optimized with depth map).
973 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
974 if (depth_map == (Quantum *) NULL)
975 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
976 for (i=0; i <= (ssize_t) MaxMap; i++)
977 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
979 #if defined(MAGICKCORE_OPENMP_SUPPORT)
980 #pragma omp parallel for schedule(static,4) shared(status) \
981 dynamic_number_threads(image,image->columns,image->rows,1)
983 for (y=0; y < (ssize_t) image->rows; y++)
991 if (status == MagickFalse)
993 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
995 if (q == (Quantum *) NULL)
1000 for (x=0; x < (ssize_t) image->columns; x++)
1005 if (GetPixelMask(image,q) != 0)
1007 q+=GetPixelChannels(image);
1010 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1018 channel=GetPixelChannelChannel(image,i);
1019 traits=GetPixelChannelTraits(image,channel);
1020 if ((traits == UndefinedPixelTrait) ||
1021 (channel == IndexPixelChannel) || (channel == MaskPixelChannel))
1023 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1025 q+=GetPixelChannels(image);
1027 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1033 image_view=DestroyCacheView(image_view);
1034 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1035 if (status != MagickFalse)
1041 Scale pixels to desired depth.
1043 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1044 #pragma omp parallel for schedule(static,4) shared(status) \
1045 dynamic_number_threads(image,image->columns,image->rows,1)
1047 for (y=0; y < (ssize_t) image->rows; y++)
1055 if (status == MagickFalse)
1057 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1058 if (q == (Quantum *) NULL)
1063 for (x=0; x < (ssize_t) image->columns; x++)
1068 if (GetPixelMask(image,q) != 0)
1070 q+=GetPixelChannels(image);
1073 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1081 channel=GetPixelChannelChannel(image,i);
1082 traits=GetPixelChannelTraits(image,channel);
1083 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1084 (channel == MaskPixelChannel))
1086 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range);
1088 q+=GetPixelChannels(image);
1090 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1096 image_view=DestroyCacheView(image_view);
1097 if (status != MagickFalse)
1103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1107 % S e t I m a g e T y p e %
1111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1113 % SetImageType() sets the type of image. Choose from these types:
1115 % Bilevel Grayscale GrayscaleMatte
1116 % Palette PaletteMatte TrueColor
1117 % TrueColorMatte ColorSeparation ColorSeparationMatte
1120 % The format of the SetImageType method is:
1122 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1123 % ExceptionInfo *exception)
1125 % A description of each parameter follows:
1127 % o image: the image.
1129 % o type: Image type.
1131 % o exception: return any errors or warnings in this structure.
1134 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1135 ExceptionInfo *exception)
1149 assert(image != (Image *) NULL);
1150 if (image->debug != MagickFalse)
1151 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1152 assert(image->signature == MagickSignature);
1154 image_info=AcquireImageInfo();
1155 image_info->dither=image->dither;
1156 artifact=GetImageArtifact(image,"dither");
1157 if (artifact != (const char *) NULL)
1158 (void) SetImageOption(image_info,"dither",artifact);
1163 if (IsImageMonochrome(image,exception) == MagickFalse)
1165 quantize_info=AcquireQuantizeInfo(image_info);
1166 quantize_info->number_colors=2;
1167 quantize_info->colorspace=GRAYColorspace;
1168 status=QuantizeImage(quantize_info,image,exception);
1169 quantize_info=DestroyQuantizeInfo(quantize_info);
1171 image->alpha_trait=UndefinedPixelTrait;
1176 if (IsImageGray(image,exception) == MagickFalse)
1177 status=TransformImageColorspace(image,GRAYColorspace,exception);
1178 image->alpha_trait=UndefinedPixelTrait;
1181 case GrayscaleMatteType:
1183 if (IsImageGray(image,exception) == MagickFalse)
1184 status=TransformImageColorspace(image,GRAYColorspace,exception);
1185 if (image->alpha_trait != BlendPixelTrait)
1186 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1191 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1192 status=TransformImageColorspace(image,sRGBColorspace,exception);
1193 if ((image->storage_class == DirectClass) || (image->colors > 256))
1195 quantize_info=AcquireQuantizeInfo(image_info);
1196 quantize_info->number_colors=256;
1197 status=QuantizeImage(quantize_info,image,exception);
1198 quantize_info=DestroyQuantizeInfo(quantize_info);
1200 image->alpha_trait=UndefinedPixelTrait;
1203 case PaletteBilevelMatteType:
1208 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1209 status=TransformImageColorspace(image,sRGBColorspace,exception);
1210 if (image->alpha_trait != BlendPixelTrait)
1211 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1212 channel_mask=SetImageChannelMask(image,AlphaChannel);
1213 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1214 (void) SetImageChannelMask(image,channel_mask);
1215 quantize_info=AcquireQuantizeInfo(image_info);
1216 status=QuantizeImage(quantize_info,image,exception);
1217 quantize_info=DestroyQuantizeInfo(quantize_info);
1220 case PaletteMatteType:
1222 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1223 status=TransformImageColorspace(image,sRGBColorspace,exception);
1224 if (image->alpha_trait != BlendPixelTrait)
1225 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1226 quantize_info=AcquireQuantizeInfo(image_info);
1227 quantize_info->colorspace=TransparentColorspace;
1228 status=QuantizeImage(quantize_info,image,exception);
1229 quantize_info=DestroyQuantizeInfo(quantize_info);
1234 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1235 status=TransformImageColorspace(image,sRGBColorspace,exception);
1236 if (image->storage_class != DirectClass)
1237 status=SetImageStorageClass(image,DirectClass,exception);
1238 image->alpha_trait=UndefinedPixelTrait;
1241 case TrueColorMatteType:
1243 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1244 status=TransformImageColorspace(image,sRGBColorspace,exception);
1245 if (image->storage_class != DirectClass)
1246 status=SetImageStorageClass(image,DirectClass,exception);
1247 if (image->alpha_trait != BlendPixelTrait)
1248 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1251 case ColorSeparationType:
1253 if (image->colorspace != CMYKColorspace)
1255 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1256 status=TransformImageColorspace(image,sRGBColorspace,exception);
1257 status=TransformImageColorspace(image,CMYKColorspace,exception);
1259 if (image->storage_class != DirectClass)
1260 status=SetImageStorageClass(image,DirectClass,exception);
1261 image->alpha_trait=UndefinedPixelTrait;
1264 case ColorSeparationMatteType:
1266 if (image->colorspace != CMYKColorspace)
1268 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1269 status=TransformImageColorspace(image,sRGBColorspace,exception);
1270 status=TransformImageColorspace(image,CMYKColorspace,exception);
1272 if (image->storage_class != DirectClass)
1273 status=SetImageStorageClass(image,DirectClass,exception);
1274 if (image->alpha_trait != BlendPixelTrait)
1275 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1283 image_info=DestroyImageInfo(image_info);