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-2012 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/attribute.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/blob-private.h"
47 #include "MagickCore/cache.h"
48 #include "MagickCore/cache-view.h"
49 #include "MagickCore/client.h"
50 #include "MagickCore/color.h"
51 #include "MagickCore/color-private.h"
52 #include "MagickCore/colormap.h"
53 #include "MagickCore/colormap-private.h"
54 #include "MagickCore/colorspace.h"
55 #include "MagickCore/colorspace-private.h"
56 #include "MagickCore/composite.h"
57 #include "MagickCore/composite-private.h"
58 #include "MagickCore/constitute.h"
59 #include "MagickCore/draw.h"
60 #include "MagickCore/draw-private.h"
61 #include "MagickCore/effect.h"
62 #include "MagickCore/enhance.h"
63 #include "MagickCore/exception.h"
64 #include "MagickCore/exception-private.h"
65 #include "MagickCore/geometry.h"
66 #include "MagickCore/histogram.h"
67 #include "MagickCore/identify.h"
68 #include "MagickCore/image.h"
69 #include "MagickCore/image-private.h"
70 #include "MagickCore/list.h"
71 #include "MagickCore/log.h"
72 #include "MagickCore/memory_.h"
73 #include "MagickCore/magick.h"
74 #include "MagickCore/monitor.h"
75 #include "MagickCore/monitor-private.h"
76 #include "MagickCore/paint.h"
77 #include "MagickCore/pixel.h"
78 #include "MagickCore/pixel-accessor.h"
79 #include "MagickCore/property.h"
80 #include "MagickCore/quantize.h"
81 #include "MagickCore/quantum-private.h"
82 #include "MagickCore/random_.h"
83 #include "MagickCore/resource_.h"
84 #include "MagickCore/semaphore.h"
85 #include "MagickCore/segment.h"
86 #include "MagickCore/splay-tree.h"
87 #include "MagickCore/string_.h"
88 #include "MagickCore/thread-private.h"
89 #include "MagickCore/threshold.h"
90 #include "MagickCore/transform.h"
91 #include "MagickCore/utility.h"
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 + G e t I m a g e B o u n d i n g B o x %
102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % GetImageBoundingBox() returns the bounding box of an image canvas.
106 % The format of the GetImageBoundingBox method is:
108 % RectangleInfo GetImageBoundingBox(const Image *image,
109 % ExceptionInfo *exception)
111 % A description of each parameter follows:
113 % o bounds: Method GetImageBoundingBox returns the bounding box of an
116 % o image: the image.
118 % o exception: return any errors or warnings in this structure.
121 MagickExport RectangleInfo GetImageBoundingBox(const Image *image,
122 ExceptionInfo *exception)
137 register const Quantum
143 assert(image != (Image *) NULL);
144 assert(image->signature == MagickSignature);
145 if (image->debug != MagickFalse)
146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
149 bounds.x=(ssize_t) image->columns;
150 bounds.y=(ssize_t) image->rows;
151 GetPixelInfo(image,&target[0]);
152 image_view=AcquireVirtualCacheView(image,exception);
153 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
154 if (p == (const Quantum *) NULL)
156 image_view=DestroyCacheView(image_view);
159 GetPixelInfoPixel(image,p,&target[0]);
160 GetPixelInfo(image,&target[1]);
161 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
163 GetPixelInfoPixel(image,p,&target[1]);
164 GetPixelInfo(image,&target[2]);
165 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
167 GetPixelInfoPixel(image,p,&target[2]);
169 GetPixelInfo(image,&zero);
170 #if defined(MAGICKCORE_OPENMP_SUPPORT)
171 #pragma omp parallel for schedule(static,4) shared(status)
173 for (y=0; y < (ssize_t) image->rows; y++)
181 register const Quantum
187 if (status == MagickFalse)
189 #if defined(MAGICKCORE_OPENMP_SUPPORT)
190 # pragma omp critical (MagickCore_GetImageBoundingBox)
193 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
194 if (p == (const Quantum *) NULL)
200 for (x=0; x < (ssize_t) image->columns; x++)
202 GetPixelInfoPixel(image,p,&pixel);
203 if ((x < bounding_box.x) &&
204 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
206 if ((x > (ssize_t) bounding_box.width) &&
207 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
208 bounding_box.width=(size_t) x;
209 if ((y < bounding_box.y) &&
210 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
212 if ((y > (ssize_t) bounding_box.height) &&
213 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
214 bounding_box.height=(size_t) y;
215 p+=GetPixelChannels(image);
217 #if defined(MAGICKCORE_OPENMP_SUPPORT)
218 # pragma omp critical (MagickCore_GetImageBoundingBox)
221 if (bounding_box.x < bounds.x)
222 bounds.x=bounding_box.x;
223 if (bounding_box.y < bounds.y)
224 bounds.y=bounding_box.y;
225 if (bounding_box.width > bounds.width)
226 bounds.width=bounding_box.width;
227 if (bounding_box.height > bounds.height)
228 bounds.height=bounding_box.height;
231 image_view=DestroyCacheView(image_view);
232 if ((bounds.width == 0) || (bounds.height == 0))
233 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
234 "GeometryDoesNotContainImage","'%s'",image->filename);
237 bounds.width-=(bounds.x-1);
238 bounds.height-=(bounds.y-1);
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 % G e t I m a g e D e p t h %
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % GetImageDepth() returns the depth of a particular image channel.
256 % The format of the GetImageDepth method is:
258 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
260 % A description of each parameter follows:
262 % o image: the image.
264 % o exception: return any errors or warnings in this structure.
267 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
289 assert(image != (Image *) NULL);
290 assert(image->signature == MagickSignature);
291 if (image->debug != MagickFalse)
292 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
293 number_threads=GetOpenMPMaximumThreads();
294 current_depth=(size_t *) AcquireQuantumMemory(number_threads,
295 sizeof(*current_depth));
296 if (current_depth == (size_t *) NULL)
297 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
299 for (id=0; id < (ssize_t) number_threads; id++)
301 if ((image->storage_class == PseudoClass) && (image->matte == MagickFalse))
306 #if defined(MAGICKCORE_OPENMP_SUPPORT)
307 #pragma omp parallel for schedule(static) shared(status)
309 for (i=0; i < (ssize_t) image->colors; i++)
312 id = GetOpenMPThreadId();
314 if (status == MagickFalse)
316 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
325 range=GetQuantumRange(current_depth[id]);
326 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
327 status|=ClampToQuantum(image->colormap[i].red) !=
328 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum(
329 image->colormap[i].red),range),range);
330 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
331 status|=ClampToQuantum(image->colormap[i].green) !=
332 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum(
333 image->colormap[i].green),range),range);
334 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
335 status|=ClampToQuantum(image->colormap[i].blue) !=
336 ScaleAnyToQuantum(ScaleQuantumToAny(ClampToQuantum(
337 image->colormap[i].blue),range),range);
343 depth=current_depth[0];
344 for (id=1; id < (ssize_t) number_threads; id++)
345 if (depth < current_depth[id])
346 depth=current_depth[id];
347 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
350 image_view=AcquireVirtualCacheView(image,exception);
351 #if !defined(MAGICKCORE_HDRI_SUPPORT)
352 if (QuantumRange <= MaxMap)
361 Scale pixels to desired (optimized with depth map).
363 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
364 if (depth_map == (size_t *) NULL)
365 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
366 for (i=0; i <= (ssize_t) MaxMap; i++)
371 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
379 range=GetQuantumRange(depth);
381 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
386 #if defined(MAGICKCORE_OPENMP_SUPPORT)
387 #pragma omp parallel for schedule(static,4) shared(status)
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++)
410 if (GetPixelMask(image,p) != 0)
412 p+=GetPixelChannels(image);
415 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
423 channel=GetPixelChannelMapChannel(image,i);
424 traits=GetPixelChannelMapTraits(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)
452 for (y=0; y < (ssize_t) image->rows; y++)
455 id = GetOpenMPThreadId();
457 register const Quantum
463 if (status == MagickFalse)
465 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
466 if (p == (const Quantum *) NULL)
468 for (x=0; x < (ssize_t) image->columns; x++)
473 if (GetPixelMask(image,p) != 0)
475 p+=GetPixelChannels(image);
478 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
486 channel=GetPixelChannelMapChannel(image,i);
487 traits=GetPixelChannelMapTraits(image,channel);
488 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
489 (channel == MaskPixelChannel))
491 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
496 range=GetQuantumRange(current_depth[id]);
497 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
502 p+=GetPixelChannels(image);
504 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
507 image_view=DestroyCacheView(image_view);
508 depth=current_depth[0];
509 for (id=1; id < (ssize_t) number_threads; id++)
510 if (depth < current_depth[id])
511 depth=current_depth[id];
512 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521 % G e t I m a g e Q u a n t u m D e p t h %
525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
528 % quantum depth: 8, 16, or 32.
530 % The format of the GetImageQuantumDepth method is:
532 % size_t GetImageQuantumDepth(const Image *image,
533 % const MagickBooleanType constrain)
535 % A description of each parameter follows:
537 % o image: the image.
539 % o constrain: A value other than MagickFalse, constrains the depth to
540 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
544 static inline double MagickMin(const double x,const double y)
551 MagickExport size_t GetImageQuantumDepth(const Image *image,
552 const MagickBooleanType constrain)
569 if (constrain != MagickFalse)
570 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579 % G e t I m a g e T y p e %
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585 % GetImageType() returns the potential type of image:
587 % Bilevel Grayscale GrayscaleMatte
588 % Palette PaletteMatte TrueColor
589 % TrueColorMatte ColorSeparation ColorSeparationMatte
591 % To ensure the image type matches its potential, use SetImageType():
593 % (void) SetImageType(image,GetImageType(image));
595 % The format of the GetImageType method is:
597 % ImageType GetImageType(const Image *image,ExceptionInfo *exception)
599 % A description of each parameter follows:
601 % o image: the image.
603 % o exception: return any errors or warnings in this structure.
606 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
608 assert(image != (Image *) NULL);
609 assert(image->signature == MagickSignature);
610 if (image->debug != MagickFalse)
611 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
612 if (image->colorspace == CMYKColorspace)
614 if (image->matte == MagickFalse)
615 return(ColorSeparationType);
616 return(ColorSeparationMatteType);
618 if (IsImageMonochrome(image,exception) != MagickFalse)
620 if (IsImageGray(image,exception) != MagickFalse)
622 if (image->matte != MagickFalse)
623 return(GrayscaleMatteType);
624 return(GrayscaleType);
626 if (IsPaletteImage(image,exception) != MagickFalse)
628 if (image->matte != MagickFalse)
629 return(PaletteMatteType);
632 if (image->matte != MagickFalse)
633 return(TrueColorMatteType);
634 return(TrueColorType);
638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642 % I s I m a g e G r a y %
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 % IsImageGray() returns MagickTrue if all the pixels in the image have the
649 % same red, green, and blue intensities.
651 % The format of the IsImageGray method is:
653 % MagickBooleanType IsImageGray(const Image *image,
654 % ExceptionInfo *exception)
656 % A description of each parameter follows:
658 % o image: the image.
660 % o exception: return any errors or warnings in this structure.
663 MagickExport MagickBooleanType IsImageGray(const Image *image,
664 ExceptionInfo *exception)
672 register const Quantum
681 assert(image != (Image *) NULL);
682 assert(image->signature == MagickSignature);
683 if (image->debug != MagickFalse)
684 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
685 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
686 (image->type == GrayscaleMatteType))
688 if (IssRGBColorspace(image->colorspace) == MagickFalse)
691 image_view=AcquireVirtualCacheView(image,exception);
692 for (y=0; y < (ssize_t) image->rows; y++)
694 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
695 if (p == (const Quantum *) NULL)
697 for (x=0; x < (ssize_t) image->columns; x++)
699 if (IsPixelGray(image,p) == MagickFalse)
704 if ((type == BilevelType) &&
705 (IsPixelMonochrome(image,p) == MagickFalse))
707 p+=GetPixelChannels(image);
709 if (type == UndefinedType)
712 image_view=DestroyCacheView(image_view);
713 if (type == UndefinedType)
715 ((Image *) image)->type=type;
716 if ((type == GrayscaleType) && (image->matte != MagickFalse))
717 ((Image *) image)->type=GrayscaleMatteType;
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
726 % I s I m a g e M o n o c h r o m e %
730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 % IsImageMonochrome() returns MagickTrue if all the pixels in the image have
733 % the same red, green, and blue intensities and the intensity is either
736 % The format of the IsImageMonochrome method is:
738 % MagickBooleanType IsImageMonochrome(const Image *image,
739 % ExceptionInfo *exception)
741 % A description of each parameter follows:
743 % o image: the image.
745 % o exception: return any errors or warnings in this structure.
748 MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
749 ExceptionInfo *exception)
760 register const Quantum
766 assert(image != (Image *) NULL);
767 assert(image->signature == MagickSignature);
768 if (image->debug != MagickFalse)
769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
770 if (image->type == BilevelType)
772 if (IssRGBColorspace(image->colorspace) == MagickFalse)
775 image_view=AcquireVirtualCacheView(image,exception);
776 for (y=0; y < (ssize_t) image->rows; y++)
778 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
779 if (p == (const Quantum *) NULL)
781 for (x=0; x < (ssize_t) image->columns; x++)
783 if (IsPixelMonochrome(image,p) == MagickFalse)
788 p+=GetPixelChannels(image);
790 if (type == UndefinedType)
793 image_view=DestroyCacheView(image_view);
794 if (type == UndefinedType)
796 ((Image *) image)->type=type;
801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805 % I s I m a g e O p a q u e %
809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
811 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
812 % an opacity value other than opaque (0).
814 % The format of the IsImageOpaque method is:
816 % MagickBooleanType IsImageOpaque(const Image *image,
817 % ExceptionInfo *exception)
819 % A description of each parameter follows:
821 % o image: the image.
823 % o exception: return any errors or warnings in this structure.
826 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
827 ExceptionInfo *exception)
832 register const Quantum
842 Determine if image is opaque.
844 assert(image != (Image *) NULL);
845 assert(image->signature == MagickSignature);
846 if (image->debug != MagickFalse)
847 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
848 if (image->matte == MagickFalse)
850 image_view=AcquireVirtualCacheView(image,exception);
851 for (y=0; y < (ssize_t) image->rows; y++)
853 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
854 if (p == (const Quantum *) NULL)
856 for (x=0; x < (ssize_t) image->columns; x++)
858 if (GetPixelAlpha(image,p) != OpaqueAlpha)
860 p+=GetPixelChannels(image);
862 if (x < (ssize_t) image->columns)
865 image_view=DestroyCacheView(image_view);
866 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874 % S e t I m a g e D e p t h %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880 % SetImageDepth() sets the depth of the image.
882 % The format of the SetImageDepth method is:
884 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
885 % ExceptionInfo *exception)
887 % A description of each parameter follows:
889 % o image: the image.
891 % o channel: the channel.
893 % o depth: the image depth.
895 % o exception: return any errors or warnings in this structure.
898 MagickExport MagickBooleanType SetImageDepth(Image *image,
899 const size_t depth,ExceptionInfo *exception)
913 assert(image != (Image *) NULL);
914 if (image->debug != MagickFalse)
915 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
916 assert(image->signature == MagickSignature);
917 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
919 image->depth=MAGICKCORE_QUANTUM_DEPTH;
922 range=GetQuantumRange(depth);
923 if (image->storage_class == PseudoClass)
928 #if defined(MAGICKCORE_OPENMP_SUPPORT)
929 #pragma omp parallel for schedule(static) shared(status)
931 for (i=0; i < (ssize_t) image->colors; i++)
933 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
934 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
935 ClampToQuantum(image->colormap[i].red),range),range);
936 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
937 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny( ClampToQuantum(image->colormap[i].green),range),range);
938 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
939 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
940 ClampToQuantum(image->colormap[i].blue),range),range);
941 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
942 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
943 ClampToQuantum(image->colormap[i].alpha),range),range);
945 status=SyncImage(image,exception);
946 if (status != MagickFalse)
951 image_view=AcquireAuthenticCacheView(image,exception);
952 #if !defined(MAGICKCORE_HDRI_SUPPORT)
953 if (QuantumRange <= MaxMap)
962 Scale pixels to desired (optimized with depth map).
964 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
965 if (depth_map == (Quantum *) NULL)
966 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
967 for (i=0; i <= (ssize_t) MaxMap; i++)
968 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
970 #if defined(MAGICKCORE_OPENMP_SUPPORT)
971 #pragma omp parallel for schedule(static,4) shared(status)
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 (GetPixelMask(image,q) != 0)
997 q+=GetPixelChannels(image);
1000 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1008 channel=GetPixelChannelMapChannel(image,i);
1009 traits=GetPixelChannelMapTraits(image,channel);
1010 if ((traits == UndefinedPixelTrait) ||
1011 (channel == IndexPixelChannel) || (channel == MaskPixelChannel))
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)
1036 for (y=0; y < (ssize_t) image->rows; y++)
1044 if (status == MagickFalse)
1046 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1047 if (q == (Quantum *) NULL)
1052 for (x=0; x < (ssize_t) image->columns; x++)
1057 if (GetPixelMask(image,q) != 0)
1059 q+=GetPixelChannels(image);
1062 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1070 channel=GetPixelChannelMapChannel(image,i);
1071 traits=GetPixelChannelMapTraits(image,channel);
1072 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1073 (channel == MaskPixelChannel))
1075 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(q[i],range),range);
1077 q+=GetPixelChannels(image);
1079 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1085 image_view=DestroyCacheView(image_view);
1086 if (status != MagickFalse)