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 magick_threads(image,image,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 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 (GetPixelMask(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) || (channel == MaskPixelChannel))
428 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
429 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
431 p+=GetPixelChannels(image);
433 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
436 image_view=DestroyCacheView(image_view);
437 depth=current_depth[0];
438 for (id=1; id < (ssize_t) number_threads; id++)
439 if (depth < current_depth[id])
440 depth=current_depth[id];
441 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
442 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
449 #if defined(MAGICKCORE_OPENMP_SUPPORT)
450 #pragma omp parallel for schedule(static,4) shared(status) \
451 magick_threads(image,image,image->rows,1)
453 for (y=0; y < (ssize_t) image->rows; y++)
456 id = GetOpenMPThreadId();
458 register const Quantum
464 if (status == MagickFalse)
466 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
467 if (p == (const Quantum *) NULL)
469 for (x=0; x < (ssize_t) image->columns; x++)
474 if (GetPixelMask(image,p) != 0)
476 p+=GetPixelChannels(image);
479 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
487 channel=GetPixelChannelChannel(image,i);
488 traits=GetPixelChannelTraits(image,channel);
489 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
490 (channel == MaskPixelChannel))
492 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
497 range=GetQuantumRange(current_depth[id]);
498 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
503 p+=GetPixelChannels(image);
505 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
508 image_view=DestroyCacheView(image_view);
509 depth=current_depth[0];
510 for (id=1; id < (ssize_t) number_threads; id++)
511 if (depth < current_depth[id])
512 depth=current_depth[id];
513 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 % G e t I m a g e Q u a n t u m D e p t h %
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
529 % quantum depth: 8, 16, or 32.
531 % The format of the GetImageQuantumDepth method is:
533 % size_t GetImageQuantumDepth(const Image *image,
534 % const MagickBooleanType constrain)
536 % A description of each parameter follows:
538 % o image: the image.
540 % o constrain: A value other than MagickFalse, constrains the depth to
541 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
545 static inline double MagickMin(const double x,const double y)
552 MagickExport size_t GetImageQuantumDepth(const Image *image,
553 const MagickBooleanType constrain)
570 if (constrain != MagickFalse)
571 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 % G e t I m a g e T y p e %
584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 % GetImageType() returns the potential type of image:
588 % Bilevel Grayscale GrayscaleMatte
589 % Palette PaletteMatte TrueColor
590 % TrueColorMatte ColorSeparation ColorSeparationMatte
592 % To ensure the image type matches its potential, use SetImageType():
594 % (void) SetImageType(image,GetImageType(image));
596 % The format of the GetImageType method is:
598 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
600 % A description of each parameter follows:
602 % o image: the image.
604 % o exception: return any errors or warnings in this structure.
607 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
609 assert(image != (Image *) NULL);
610 assert(image->signature == MagickSignature);
611 if (image->debug != MagickFalse)
612 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
613 if (image->colorspace == CMYKColorspace)
615 if (image->alpha_trait != BlendPixelTrait)
616 return(ColorSeparationType);
617 return(ColorSeparationMatteType);
619 if (IsImageMonochrome(image,exception) != MagickFalse)
621 if (IsImageGray(image,exception) != MagickFalse)
623 if (image->alpha_trait == BlendPixelTrait)
624 return(GrayscaleMatteType);
625 return(GrayscaleType);
627 if (IsPaletteImage(image,exception) != MagickFalse)
629 if (image->alpha_trait == BlendPixelTrait)
630 return(PaletteMatteType);
633 if (image->alpha_trait == BlendPixelTrait)
634 return(TrueColorMatteType);
635 return(TrueColorType);
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 % I s I m a g e G r a y %
647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % IsImageGray() returns MagickTrue if all the pixels in the image have the
650 % same red, green, and blue intensities.
652 % The format of the IsImageGray method is:
654 % MagickBooleanType IsImageGray(const Image *image,
655 % ExceptionInfo *exception)
657 % A description of each parameter follows:
659 % o image: the image.
661 % o exception: return any errors or warnings in this structure.
664 MagickExport MagickBooleanType IsImageGray(const Image *image,
665 ExceptionInfo *exception)
673 register const Quantum
682 assert(image != (Image *) NULL);
683 assert(image->signature == MagickSignature);
684 if (image->debug != MagickFalse)
685 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
686 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
687 (image->type == GrayscaleMatteType))
689 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
690 (IsRGBColorspace(image->colorspace) == MagickFalse))
693 image_view=AcquireVirtualCacheView(image,exception);
694 for (y=0; y < (ssize_t) image->rows; y++)
696 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
697 if (p == (const Quantum *) NULL)
699 for (x=0; x < (ssize_t) image->columns; x++)
701 if (IsPixelGray(image,p) == MagickFalse)
706 if ((type == BilevelType) &&
707 (IsPixelMonochrome(image,p) == MagickFalse))
709 p+=GetPixelChannels(image);
711 if (type == UndefinedType)
714 image_view=DestroyCacheView(image_view);
715 if (type == UndefinedType)
717 ((Image *) image)->type=type;
718 if ((type == GrayscaleType) && (image->alpha_trait == BlendPixelTrait))
719 ((Image *) image)->type=GrayscaleMatteType;
724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
728 % I s I m a g e M o n o c h r o m e %
732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
734 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have
735 % the same red, green, and blue intensities and the intensity is either
738 % The format of the IsImageMonochrome method is:
740 % MagickBooleanType IsImageMonochrome(const Image *image,
741 % ExceptionInfo *exception)
743 % A description of each parameter follows:
745 % o image: the image.
747 % o exception: return any errors or warnings in this structure.
750 MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
751 ExceptionInfo *exception)
762 register const Quantum
768 assert(image != (Image *) NULL);
769 assert(image->signature == MagickSignature);
770 if (image->debug != MagickFalse)
771 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
772 if (image->type == BilevelType)
774 if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
775 (IsRGBColorspace(image->colorspace) == MagickFalse))
778 image_view=AcquireVirtualCacheView(image,exception);
779 for (y=0; y < (ssize_t) image->rows; y++)
781 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
782 if (p == (const Quantum *) NULL)
784 for (x=0; x < (ssize_t) image->columns; x++)
786 if (IsPixelMonochrome(image,p) == MagickFalse)
791 p+=GetPixelChannels(image);
793 if (type == UndefinedType)
796 image_view=DestroyCacheView(image_view);
797 if (type == UndefinedType)
799 ((Image *) image)->type=type;
804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 % I s I m a g e O p a q u e %
812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
815 % an alpha value other than OpaqueAlpha (QuantumRange).
817 % Will return true immediatally is alpha channel is not available.
819 % The format of the IsImageOpaque method is:
821 % MagickBooleanType IsImageOpaque(const Image *image,
822 % ExceptionInfo *exception)
824 % A description of each parameter follows:
826 % o image: the image.
828 % o exception: return any errors or warnings in this structure.
831 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
832 ExceptionInfo *exception)
837 register const Quantum
847 Determine if image is opaque.
849 assert(image != (Image *) NULL);
850 assert(image->signature == MagickSignature);
851 if (image->debug != MagickFalse)
852 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
853 if (image->alpha_trait != BlendPixelTrait)
855 image_view=AcquireVirtualCacheView(image,exception);
856 for (y=0; y < (ssize_t) image->rows; y++)
858 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
859 if (p == (const Quantum *) NULL)
861 for (x=0; x < (ssize_t) image->columns; x++)
863 if (GetPixelAlpha(image,p) != OpaqueAlpha)
865 p+=GetPixelChannels(image);
867 if (x < (ssize_t) image->columns)
870 image_view=DestroyCacheView(image_view);
871 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879 % S e t I m a g e D e p t h %
883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885 % SetImageDepth() sets the depth of the image.
887 % The format of the SetImageDepth method is:
889 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
890 % ExceptionInfo *exception)
892 % A description of each parameter follows:
894 % o image: the image.
896 % o channel: the channel.
898 % o depth: the image depth.
900 % o exception: return any errors or warnings in this structure.
903 MagickExport MagickBooleanType SetImageDepth(Image *image,
904 const size_t depth,ExceptionInfo *exception)
918 assert(image != (Image *) NULL);
919 if (image->debug != MagickFalse)
920 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
921 assert(image->signature == MagickSignature);
922 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
927 range=GetQuantumRange(depth);
928 if (image->storage_class == PseudoClass)
933 #if defined(MAGICKCORE_OPENMP_SUPPORT)
934 #pragma omp parallel for schedule(static,4) shared(status) \
935 magick_threads(image,image,1,1)
937 for (i=0; i < (ssize_t) image->colors; i++)
939 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
940 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
941 ClampToQuantum(image->colormap[i].red),range),range);
942 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
943 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
944 ClampToQuantum(image->colormap[i].green),range),range);
945 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
946 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
947 ClampToQuantum(image->colormap[i].blue),range),range);
948 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
949 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
950 ClampToQuantum(image->colormap[i].alpha),range),range);
954 image_view=AcquireAuthenticCacheView(image,exception);
955 #if !defined(MAGICKCORE_HDRI_SUPPORT)
956 if (QuantumRange <= MaxMap)
965 Scale pixels to desired (optimized with depth map).
967 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
968 if (depth_map == (Quantum *) NULL)
969 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
970 for (i=0; i <= (ssize_t) MaxMap; i++)
971 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
973 #if defined(MAGICKCORE_OPENMP_SUPPORT)
974 #pragma omp parallel for schedule(static,4) shared(status) \
975 magick_threads(image,image,image->rows,1)
977 for (y=0; y < (ssize_t) image->rows; y++)
985 if (status == MagickFalse)
987 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
989 if (q == (Quantum *) NULL)
994 for (x=0; x < (ssize_t) image->columns; x++)
999 if (GetPixelMask(image,q) != 0)
1001 q+=GetPixelChannels(image);
1004 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1012 channel=GetPixelChannelChannel(image,i);
1013 traits=GetPixelChannelTraits(image,channel);
1014 if ((traits == UndefinedPixelTrait) ||
1015 (channel == IndexPixelChannel) || (channel == MaskPixelChannel))
1017 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1019 q+=GetPixelChannels(image);
1021 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1027 image_view=DestroyCacheView(image_view);
1028 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1029 if (status != MagickFalse)
1035 Scale pixels to desired depth.
1037 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1038 #pragma omp parallel for schedule(static,4) shared(status) \
1039 magick_threads(image,image,image->rows,1)
1041 for (y=0; y < (ssize_t) image->rows; y++)
1049 if (status == MagickFalse)
1051 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1052 if (q == (Quantum *) NULL)
1057 for (x=0; x < (ssize_t) image->columns; x++)
1062 if (GetPixelMask(image,q) != 0)
1064 q+=GetPixelChannels(image);
1067 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1075 channel=GetPixelChannelChannel(image,i);
1076 traits=GetPixelChannelTraits(image,channel);
1077 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1078 (channel == MaskPixelChannel))
1080 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range);
1082 q+=GetPixelChannels(image);
1084 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1090 image_view=DestroyCacheView(image_view);
1091 if (status != MagickFalse)
1097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101 % S e t I m a g e T y p e %
1105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1107 % SetImageType() sets the type of image. Choose from these types:
1109 % Bilevel Grayscale GrayscaleMatte
1110 % Palette PaletteMatte TrueColor
1111 % TrueColorMatte ColorSeparation ColorSeparationMatte
1114 % The format of the SetImageType method is:
1116 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1117 % ExceptionInfo *exception)
1119 % A description of each parameter follows:
1121 % o image: the image.
1123 % o type: Image type.
1125 % o exception: return any errors or warnings in this structure.
1128 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1129 ExceptionInfo *exception)
1143 assert(image != (Image *) NULL);
1144 if (image->debug != MagickFalse)
1145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1146 assert(image->signature == MagickSignature);
1148 image_info=AcquireImageInfo();
1149 image_info->dither=image->dither;
1150 artifact=GetImageArtifact(image,"dither");
1151 if (artifact != (const char *) NULL)
1152 (void) SetImageOption(image_info,"dither",artifact);
1157 if (IsImageMonochrome(image,exception) == MagickFalse)
1159 quantize_info=AcquireQuantizeInfo(image_info);
1160 quantize_info->number_colors=2;
1161 quantize_info->colorspace=GRAYColorspace;
1162 status=QuantizeImage(quantize_info,image,exception);
1163 quantize_info=DestroyQuantizeInfo(quantize_info);
1165 image->alpha_trait=UndefinedPixelTrait;
1170 if (IsImageGray(image,exception) == MagickFalse)
1171 status=TransformImageColorspace(image,GRAYColorspace,exception);
1172 image->alpha_trait=UndefinedPixelTrait;
1175 case GrayscaleMatteType:
1177 if (IsImageGray(image,exception) == MagickFalse)
1178 status=TransformImageColorspace(image,GRAYColorspace,exception);
1179 if (image->alpha_trait != BlendPixelTrait)
1180 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1185 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1186 status=TransformImageColorspace(image,sRGBColorspace,exception);
1187 if ((image->storage_class == DirectClass) || (image->colors > 256))
1189 quantize_info=AcquireQuantizeInfo(image_info);
1190 quantize_info->number_colors=256;
1191 status=QuantizeImage(quantize_info,image,exception);
1192 quantize_info=DestroyQuantizeInfo(quantize_info);
1194 image->alpha_trait=UndefinedPixelTrait;
1197 case PaletteBilevelMatteType:
1202 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1203 status=TransformImageColorspace(image,sRGBColorspace,exception);
1204 if (image->alpha_trait != BlendPixelTrait)
1205 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1206 channel_mask=SetImageChannelMask(image,AlphaChannel);
1207 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1208 (void) SetImageChannelMask(image,channel_mask);
1209 quantize_info=AcquireQuantizeInfo(image_info);
1210 status=QuantizeImage(quantize_info,image,exception);
1211 quantize_info=DestroyQuantizeInfo(quantize_info);
1214 case PaletteMatteType:
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 quantize_info=AcquireQuantizeInfo(image_info);
1221 quantize_info->colorspace=TransparentColorspace;
1222 status=QuantizeImage(quantize_info,image,exception);
1223 quantize_info=DestroyQuantizeInfo(quantize_info);
1228 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1229 status=TransformImageColorspace(image,sRGBColorspace,exception);
1230 if (image->storage_class != DirectClass)
1231 status=SetImageStorageClass(image,DirectClass,exception);
1232 image->alpha_trait=UndefinedPixelTrait;
1235 case TrueColorMatteType:
1237 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1238 status=TransformImageColorspace(image,sRGBColorspace,exception);
1239 if (image->storage_class != DirectClass)
1240 status=SetImageStorageClass(image,DirectClass,exception);
1241 if (image->alpha_trait != BlendPixelTrait)
1242 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1245 case ColorSeparationType:
1247 if (image->colorspace != CMYKColorspace)
1249 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1250 status=TransformImageColorspace(image,sRGBColorspace,exception);
1251 status=TransformImageColorspace(image,CMYKColorspace,exception);
1253 if (image->storage_class != DirectClass)
1254 status=SetImageStorageClass(image,DirectClass,exception);
1255 image->alpha_trait=UndefinedPixelTrait;
1258 case ColorSeparationMatteType:
1260 if (image->colorspace != CMYKColorspace)
1262 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1263 status=TransformImageColorspace(image,sRGBColorspace,exception);
1264 status=TransformImageColorspace(image,CMYKColorspace,exception);
1266 if (image->storage_class != DirectClass)
1267 status=SetImageStorageClass(image,DirectClass,exception);
1268 if (image->alpha_trait != BlendPixelTrait)
1269 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1277 image_info=DestroyImageInfo(image_info);