blob: 12f35e3ef30b9d305d39f2cb85127ddfdaa49b69 [file] [log] [blame]
cristyda06ed12009-10-14 18:36:54 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
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 %
11% %
12% %
13% MagickCore Get / Set Image Attributes %
14% %
15% Software Design %
16% John Cristy %
17% October 2002 %
18% %
19% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
cristyda06ed12009-10-14 18:36:54 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
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. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#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/composite.h"
56#include "MagickCore/composite-private.h"
57#include "MagickCore/constitute.h"
58#include "MagickCore/draw.h"
59#include "MagickCore/draw-private.h"
60#include "MagickCore/effect.h"
61#include "MagickCore/enhance.h"
62#include "MagickCore/exception.h"
63#include "MagickCore/exception-private.h"
64#include "MagickCore/geometry.h"
65#include "MagickCore/histogram.h"
66#include "MagickCore/identify.h"
67#include "MagickCore/image.h"
68#include "MagickCore/image-private.h"
69#include "MagickCore/list.h"
70#include "MagickCore/log.h"
71#include "MagickCore/memory_.h"
72#include "MagickCore/magick.h"
73#include "MagickCore/monitor.h"
74#include "MagickCore/monitor-private.h"
75#include "MagickCore/paint.h"
76#include "MagickCore/pixel.h"
77#include "MagickCore/pixel-accessor.h"
78#include "MagickCore/property.h"
79#include "MagickCore/quantize.h"
80#include "MagickCore/quantum-private.h"
81#include "MagickCore/random_.h"
82#include "MagickCore/resource_.h"
83#include "MagickCore/semaphore.h"
84#include "MagickCore/segment.h"
85#include "MagickCore/splay-tree.h"
86#include "MagickCore/string_.h"
87#include "MagickCore/thread-private.h"
88#include "MagickCore/threshold.h"
89#include "MagickCore/transform.h"
90#include "MagickCore/utility.h"
cristyda06ed12009-10-14 18:36:54 +000091
92/*
93%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94% %
95% %
96% %
97+ G e t I m a g e B o u n d i n g B o x %
98% %
99% %
100% %
101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102%
103% GetImageBoundingBox() returns the bounding box of an image canvas.
104%
105% The format of the GetImageBoundingBox method is:
106%
107% RectangleInfo GetImageBoundingBox(const Image *image,
108% ExceptionInfo *exception)
109%
110% A description of each parameter follows:
111%
112% o bounds: Method GetImageBoundingBox returns the bounding box of an
113% image canvas.
114%
115% o image: the image.
116%
117% o exception: return any errors or warnings in this structure.
118%
119*/
120MagickExport RectangleInfo GetImageBoundingBox(const Image *image,
121 ExceptionInfo *exception)
122{
cristyc4c8d132010-01-07 01:58:38 +0000123 CacheView
124 *image_view;
125
cristyda06ed12009-10-14 18:36:54 +0000126 MagickBooleanType
127 status;
128
cristy4c08aed2011-07-01 19:47:50 +0000129 PixelInfo
cristyda06ed12009-10-14 18:36:54 +0000130 target[3],
131 zero;
132
133 RectangleInfo
134 bounds;
135
cristy4c08aed2011-07-01 19:47:50 +0000136 register const Quantum
cristyda06ed12009-10-14 18:36:54 +0000137 *p;
138
cristy9d314ff2011-03-09 01:30:28 +0000139 ssize_t
140 y;
141
cristyda06ed12009-10-14 18:36:54 +0000142 assert(image != (Image *) NULL);
143 assert(image->signature == MagickSignature);
144 if (image->debug != MagickFalse)
145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
146 bounds.width=0;
147 bounds.height=0;
cristybb503372010-05-27 20:51:26 +0000148 bounds.x=(ssize_t) image->columns;
149 bounds.y=(ssize_t) image->rows;
cristy4c08aed2011-07-01 19:47:50 +0000150 GetPixelInfo(image,&target[0]);
cristyda06ed12009-10-14 18:36:54 +0000151 image_view=AcquireCacheView(image);
152 p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000153 if (p == (const Quantum *) NULL)
cristyda06ed12009-10-14 18:36:54 +0000154 {
155 image_view=DestroyCacheView(image_view);
156 return(bounds);
157 }
cristy4c08aed2011-07-01 19:47:50 +0000158 SetPixelInfo(image,p,&target[0]);
159 GetPixelInfo(image,&target[1]);
cristybb503372010-05-27 20:51:26 +0000160 p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
cristyda06ed12009-10-14 18:36:54 +0000161 exception);
cristy4c08aed2011-07-01 19:47:50 +0000162 SetPixelInfo(image,p,&target[1]);
163 GetPixelInfo(image,&target[2]);
cristy4cb39ab2010-06-07 13:59:16 +0000164 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
165 exception);
cristy4c08aed2011-07-01 19:47:50 +0000166 SetPixelInfo(image,p,&target[2]);
cristyda06ed12009-10-14 18:36:54 +0000167 status=MagickTrue;
cristy4c08aed2011-07-01 19:47:50 +0000168 GetPixelInfo(image,&zero);
cristyb5d5f722009-11-04 03:03:49 +0000169#if defined(MAGICKCORE_OPENMP_SUPPORT)
170 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristyda06ed12009-10-14 18:36:54 +0000171#endif
cristybb503372010-05-27 20:51:26 +0000172 for (y=0; y < (ssize_t) image->rows; y++)
cristyda06ed12009-10-14 18:36:54 +0000173 {
cristy4c08aed2011-07-01 19:47:50 +0000174 PixelInfo
cristyda06ed12009-10-14 18:36:54 +0000175 pixel;
176
177 RectangleInfo
178 bounding_box;
179
cristy4c08aed2011-07-01 19:47:50 +0000180 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +0000181 *restrict p;
cristyda06ed12009-10-14 18:36:54 +0000182
cristybb503372010-05-27 20:51:26 +0000183 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000184 x;
185
186 if (status == MagickFalse)
187 continue;
cristyb5d5f722009-11-04 03:03:49 +0000188#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyda06ed12009-10-14 18:36:54 +0000189# pragma omp critical (MagickCore_GetImageBoundingBox)
190#endif
191 bounding_box=bounds;
192 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000193 if (p == (const Quantum *) NULL)
cristyda06ed12009-10-14 18:36:54 +0000194 {
195 status=MagickFalse;
196 continue;
197 }
cristyda06ed12009-10-14 18:36:54 +0000198 pixel=zero;
cristybb503372010-05-27 20:51:26 +0000199 for (x=0; x < (ssize_t) image->columns; x++)
cristyda06ed12009-10-14 18:36:54 +0000200 {
cristy4c08aed2011-07-01 19:47:50 +0000201 SetPixelInfo(image,p,&pixel);
cristyda06ed12009-10-14 18:36:54 +0000202 if ((x < bounding_box.x) &&
cristy4c08aed2011-07-01 19:47:50 +0000203 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
cristyda06ed12009-10-14 18:36:54 +0000204 bounding_box.x=x;
cristybb503372010-05-27 20:51:26 +0000205 if ((x > (ssize_t) bounding_box.width) &&
cristy4c08aed2011-07-01 19:47:50 +0000206 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
cristybb503372010-05-27 20:51:26 +0000207 bounding_box.width=(size_t) x;
cristyda06ed12009-10-14 18:36:54 +0000208 if ((y < bounding_box.y) &&
cristy4c08aed2011-07-01 19:47:50 +0000209 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
cristyda06ed12009-10-14 18:36:54 +0000210 bounding_box.y=y;
cristybb503372010-05-27 20:51:26 +0000211 if ((y > (ssize_t) bounding_box.height) &&
cristy4c08aed2011-07-01 19:47:50 +0000212 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
cristybb503372010-05-27 20:51:26 +0000213 bounding_box.height=(size_t) y;
cristy4c08aed2011-07-01 19:47:50 +0000214 p+=GetPixelChannels(image);
cristyda06ed12009-10-14 18:36:54 +0000215 }
cristyb5d5f722009-11-04 03:03:49 +0000216#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristyda06ed12009-10-14 18:36:54 +0000217# pragma omp critical (MagickCore_GetImageBoundingBox)
218#endif
219 {
220 if (bounding_box.x < bounds.x)
221 bounds.x=bounding_box.x;
222 if (bounding_box.y < bounds.y)
223 bounds.y=bounding_box.y;
224 if (bounding_box.width > bounds.width)
225 bounds.width=bounding_box.width;
226 if (bounding_box.height > bounds.height)
227 bounds.height=bounding_box.height;
228 }
229 }
230 image_view=DestroyCacheView(image_view);
231 if ((bounds.width == 0) || (bounds.height == 0))
232 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
233 "GeometryDoesNotContainImage","`%s'",image->filename);
234 else
235 {
236 bounds.width-=(bounds.x-1);
237 bounds.height-=(bounds.y-1);
238 }
239 return(bounds);
240}
241
242/*
243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244% %
245% %
246% %
247% G e t I m a g e C h a n n e l D e p t h %
248% %
249% %
250% %
251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252%
253% GetImageChannelDepth() returns the depth of a particular image channel.
254%
255% The format of the GetImageChannelDepth method is:
256%
cristybb503372010-05-27 20:51:26 +0000257% size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
258% size_t GetImageChannelDepth(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000259% const ChannelType channel,ExceptionInfo *exception)
260%
261% A description of each parameter follows:
262%
263% o image: the image.
264%
265% o channel: the channel.
266%
267% o exception: return any errors or warnings in this structure.
268%
269*/
cristye8c25f92010-06-03 00:53:06 +0000270MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
cristyda06ed12009-10-14 18:36:54 +0000271{
cristy9a9230e2011-04-26 14:56:14 +0000272 return(GetImageChannelDepth(image,CompositeChannels,exception));
cristyda06ed12009-10-14 18:36:54 +0000273}
274
cristybb503372010-05-27 20:51:26 +0000275MagickExport size_t GetImageChannelDepth(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000276 const ChannelType channel,ExceptionInfo *exception)
277{
cristyc4c8d132010-01-07 01:58:38 +0000278 CacheView
279 *image_view;
280
cristyda06ed12009-10-14 18:36:54 +0000281 MagickBooleanType
282 status;
283
cristybb503372010-05-27 20:51:26 +0000284 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000285 id;
286
cristybb503372010-05-27 20:51:26 +0000287 size_t
cristyda06ed12009-10-14 18:36:54 +0000288 *current_depth,
289 depth,
290 number_threads;
291
cristy9d314ff2011-03-09 01:30:28 +0000292 ssize_t
293 y;
294
cristyda06ed12009-10-14 18:36:54 +0000295 /*
296 Compute image depth.
297 */
298 assert(image != (Image *) NULL);
299 assert(image->signature == MagickSignature);
300 if (image->debug != MagickFalse)
301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
302 number_threads=GetOpenMPMaximumThreads();
cristybb503372010-05-27 20:51:26 +0000303 current_depth=(size_t *) AcquireQuantumMemory(number_threads,
cristyda06ed12009-10-14 18:36:54 +0000304 sizeof(*current_depth));
cristybb503372010-05-27 20:51:26 +0000305 if (current_depth == (size_t *) NULL)
cristyda06ed12009-10-14 18:36:54 +0000306 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
307 status=MagickTrue;
cristybb503372010-05-27 20:51:26 +0000308 for (id=0; id < (ssize_t) number_threads; id++)
cristyda06ed12009-10-14 18:36:54 +0000309 current_depth[id]=1;
310 if ((image->storage_class == PseudoClass) && (image->matte == MagickFalse))
311 {
312 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000313 *restrict p;
cristyda06ed12009-10-14 18:36:54 +0000314
cristybb503372010-05-27 20:51:26 +0000315 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000316 i;
317
318 p=image->colormap;
cristyb5d5f722009-11-04 03:03:49 +0000319#if defined(MAGICKCORE_OPENMP_SUPPORT)
320 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristyda06ed12009-10-14 18:36:54 +0000321#endif
cristybb503372010-05-27 20:51:26 +0000322 for (i=0; i < (ssize_t) image->colors; i++)
cristyda06ed12009-10-14 18:36:54 +0000323 {
cristy5c9e6f22010-09-17 17:31:01 +0000324 const int
325 id = GetOpenMPThreadId();
326
cristyda06ed12009-10-14 18:36:54 +0000327 if (status == MagickFalse)
328 continue;
cristyda06ed12009-10-14 18:36:54 +0000329 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
330 {
331 MagickStatusType
332 status;
333
334 QuantumAny
cristyb6d6f7c2010-06-09 13:17:57 +0000335 range;
cristyda06ed12009-10-14 18:36:54 +0000336
337 status=0;
cristyb6d6f7c2010-06-09 13:17:57 +0000338 range=GetQuantumRange(current_depth[id]);
cristyda06ed12009-10-14 18:36:54 +0000339 if ((channel & RedChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000340 status|=p->red != ScaleAnyToQuantum(ScaleQuantumToAny(p->red,
cristyb6d6f7c2010-06-09 13:17:57 +0000341 range),range);
cristyda06ed12009-10-14 18:36:54 +0000342 if ((channel & GreenChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000343 status|=p->green != ScaleAnyToQuantum(ScaleQuantumToAny(p->green,
cristyb6d6f7c2010-06-09 13:17:57 +0000344 range),range);
cristyda06ed12009-10-14 18:36:54 +0000345 if ((channel & BlueChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000346 status|=p->blue != ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,
cristyb6d6f7c2010-06-09 13:17:57 +0000347 range),range);
cristyda06ed12009-10-14 18:36:54 +0000348 if (status == 0)
349 break;
350 current_depth[id]++;
351 }
352 p++;
353 }
354 depth=current_depth[0];
cristybb503372010-05-27 20:51:26 +0000355 for (id=1; id < (ssize_t) number_threads; id++)
cristyda06ed12009-10-14 18:36:54 +0000356 if (depth < current_depth[id])
357 depth=current_depth[id];
cristybb503372010-05-27 20:51:26 +0000358 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
cristyda06ed12009-10-14 18:36:54 +0000359 return(depth);
360 }
361 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +0000362#if defined(MAGICKCORE_OPENMP_SUPPORT)
363 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristyda06ed12009-10-14 18:36:54 +0000364#endif
cristybb503372010-05-27 20:51:26 +0000365 for (y=0; y < (ssize_t) image->rows; y++)
cristyda06ed12009-10-14 18:36:54 +0000366 {
cristy5c9e6f22010-09-17 17:31:01 +0000367 const int
368 id = GetOpenMPThreadId();
cristy6ebe97c2010-07-03 01:17:28 +0000369
cristy4c08aed2011-07-01 19:47:50 +0000370 register const Quantum
cristyc47d1f82009-11-26 01:44:43 +0000371 *restrict p;
cristyda06ed12009-10-14 18:36:54 +0000372
cristybb503372010-05-27 20:51:26 +0000373 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000374 x;
375
376 if (status == MagickFalse)
377 continue;
cristyda06ed12009-10-14 18:36:54 +0000378 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000379 if (p == (const Quantum *) NULL)
cristyda06ed12009-10-14 18:36:54 +0000380 continue;
cristybb503372010-05-27 20:51:26 +0000381 for (x=0; x < (ssize_t) image->columns; x++)
cristyda06ed12009-10-14 18:36:54 +0000382 {
383 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
384 {
385 MagickStatusType
386 status;
387
388 QuantumAny
cristyb6d6f7c2010-06-09 13:17:57 +0000389 range;
cristyda06ed12009-10-14 18:36:54 +0000390
391 status=0;
cristyb6d6f7c2010-06-09 13:17:57 +0000392 range=GetQuantumRange(current_depth[id]);
cristyda06ed12009-10-14 18:36:54 +0000393 if ((channel & RedChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000394 status|=GetPixelRed(image,p) != ScaleAnyToQuantum(ScaleQuantumToAny(
395 GetPixelRed(image,p),range),range);
cristyda06ed12009-10-14 18:36:54 +0000396 if ((channel & GreenChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000397 status|=GetPixelGreen(image,p) != ScaleAnyToQuantum(ScaleQuantumToAny(
398 GetPixelGreen(image,p),range),range);
cristyda06ed12009-10-14 18:36:54 +0000399 if ((channel & BlueChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000400 status|=GetPixelBlue(image,p) != ScaleAnyToQuantum(ScaleQuantumToAny(
401 GetPixelBlue(image,p),range),range);
402 if (((channel & AlphaChannel) != 0) && (image->matte != MagickFalse))
403 status|=GetPixelAlpha(image,p) != ScaleAnyToQuantum(ScaleQuantumToAny(
404 GetPixelAlpha(image,p),range),range);
405 if (((channel & BlackChannel) != 0) &&
cristyda06ed12009-10-14 18:36:54 +0000406 (image->colorspace == CMYKColorspace))
cristy4c08aed2011-07-01 19:47:50 +0000407 status|=GetPixelBlack(image,p) != ScaleAnyToQuantum(ScaleQuantumToAny(
408 GetPixelBlack(image,p),range),range);
cristyda06ed12009-10-14 18:36:54 +0000409 if (status == 0)
410 break;
411 current_depth[id]++;
412 }
cristy4c08aed2011-07-01 19:47:50 +0000413 p+=GetPixelChannels(image);
cristyda06ed12009-10-14 18:36:54 +0000414 }
415 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
416 status=MagickFalse;
417 }
418 image_view=DestroyCacheView(image_view);
419 depth=current_depth[0];
cristybb503372010-05-27 20:51:26 +0000420 for (id=1; id < (ssize_t) number_threads; id++)
cristyda06ed12009-10-14 18:36:54 +0000421 if (depth < current_depth[id])
422 depth=current_depth[id];
cristybb503372010-05-27 20:51:26 +0000423 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
cristyda06ed12009-10-14 18:36:54 +0000424 return(depth);
425}
426
427/*
428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429% %
430% %
431% %
432% G e t I m a g e Q u a n t u m D e p t h %
433% %
434% %
435% %
436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437%
438% GetImageQuantumDepth() returns the depth of the image rounded to a legal
439% quantum depth: 8, 16, or 32.
440%
441% The format of the GetImageQuantumDepth method is:
442%
cristybb503372010-05-27 20:51:26 +0000443% size_t GetImageQuantumDepth(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000444% const MagickBooleanType constrain)
445%
446% A description of each parameter follows:
447%
448% o image: the image.
449%
450% o constrain: A value other than MagickFalse, constrains the depth to
451% a maximum of MAGICKCORE_QUANTUM_DEPTH.
452%
453*/
454
455static inline double MagickMin(const double x,const double y)
456{
457 if (x < y)
458 return(x);
459 return(y);
460}
461
cristybb503372010-05-27 20:51:26 +0000462MagickExport size_t GetImageQuantumDepth(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000463 const MagickBooleanType constrain)
464{
cristybb503372010-05-27 20:51:26 +0000465 size_t
cristyda06ed12009-10-14 18:36:54 +0000466 depth;
467
468 depth=image->depth;
469 if (depth <= 8)
470 depth=8;
471 else
472 if (depth <= 16)
473 depth=16;
474 else
475 if (depth <= 32)
476 depth=32;
477 else
478 if (depth <= 64)
479 depth=64;
480 if (constrain != MagickFalse)
cristybb503372010-05-27 20:51:26 +0000481 depth=(size_t) MagickMin((double) depth,(double)
cristyda06ed12009-10-14 18:36:54 +0000482 MAGICKCORE_QUANTUM_DEPTH);
483 return(depth);
484}
485
486/*
487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488% %
489% %
490% %
491% G e t I m a g e T y p e %
492% %
493% %
494% %
495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496%
497% GetImageType() returns the potential type of image:
498%
499% Bilevel Grayscale GrayscaleMatte
500% Palette PaletteMatte TrueColor
501% TrueColorMatte ColorSeparation ColorSeparationMatte
502%
503% To ensure the image type matches its potential, use SetImageType():
504%
505% (void) SetImageType(image,GetImageType(image));
506%
507% The format of the GetImageType method is:
508%
509% ImageType GetImageType(const Image *image,ExceptionInfo *exception)
510%
511% A description of each parameter follows:
512%
513% o image: the image.
514%
515% o exception: return any errors or warnings in this structure.
516%
517*/
518MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
519{
520 assert(image != (Image *) NULL);
521 assert(image->signature == MagickSignature);
522 if (image->debug != MagickFalse)
523 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
524 if (image->colorspace == CMYKColorspace)
525 {
526 if (image->matte == MagickFalse)
527 return(ColorSeparationType);
528 return(ColorSeparationMatteType);
529 }
cristy4c08aed2011-07-01 19:47:50 +0000530 if (IsImageMonochrome(image,exception) != MagickFalse)
cristyda06ed12009-10-14 18:36:54 +0000531 return(BilevelType);
cristy4c08aed2011-07-01 19:47:50 +0000532 if (IsImageGray(image,exception) != MagickFalse)
cristyda06ed12009-10-14 18:36:54 +0000533 {
534 if (image->matte != MagickFalse)
535 return(GrayscaleMatteType);
536 return(GrayscaleType);
537 }
538 if (IsPaletteImage(image,exception) != MagickFalse)
539 {
540 if (image->matte != MagickFalse)
541 return(PaletteMatteType);
542 return(PaletteType);
543 }
544 if (image->matte != MagickFalse)
545 return(TrueColorMatteType);
546 return(TrueColorType);
547}
548
549/*
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551% %
552% %
553% %
cristy4c08aed2011-07-01 19:47:50 +0000554% I s I m a g e G r a y %
cristyda06ed12009-10-14 18:36:54 +0000555% %
556% %
557% %
558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559%
cristy4c08aed2011-07-01 19:47:50 +0000560% IsImageGray() returns MagickTrue if all the pixels in the image have the
cristyda06ed12009-10-14 18:36:54 +0000561% same red, green, and blue intensities.
562%
cristy4c08aed2011-07-01 19:47:50 +0000563% The format of the IsImageGray method is:
cristyda06ed12009-10-14 18:36:54 +0000564%
cristy4c08aed2011-07-01 19:47:50 +0000565% MagickBooleanType IsImageGray(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000566% ExceptionInfo *exception)
567%
568% A description of each parameter follows:
569%
570% o image: the image.
571%
572% o exception: return any errors or warnings in this structure.
573%
574*/
cristy4c08aed2011-07-01 19:47:50 +0000575MagickExport MagickBooleanType IsImageGray(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000576 ExceptionInfo *exception)
577{
cristy0910f242010-04-01 18:55:09 +0000578 CacheView
579 *image_view;
580
cristyda06ed12009-10-14 18:36:54 +0000581 ImageType
582 type;
583
cristy4c08aed2011-07-01 19:47:50 +0000584 register const Quantum
cristyda06ed12009-10-14 18:36:54 +0000585 *p;
586
cristybb503372010-05-27 20:51:26 +0000587 register ssize_t
cristy0910f242010-04-01 18:55:09 +0000588 x;
589
cristy95802a72010-09-05 19:07:17 +0000590 ssize_t
591 y;
592
cristyda06ed12009-10-14 18:36:54 +0000593 assert(image != (Image *) NULL);
594 assert(image->signature == MagickSignature);
595 if (image->debug != MagickFalse)
596 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
597 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
598 (image->type == GrayscaleMatteType))
599 return(MagickTrue);
600 if (image->colorspace == CMYKColorspace)
601 return(MagickFalse);
602 type=BilevelType;
cristy0910f242010-04-01 18:55:09 +0000603 image_view=AcquireCacheView(image);
cristybb503372010-05-27 20:51:26 +0000604 for (y=0; y < (ssize_t) image->rows; y++)
cristyda06ed12009-10-14 18:36:54 +0000605 {
cristy0910f242010-04-01 18:55:09 +0000606 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000607 if (p == (const Quantum *) NULL)
cristy0910f242010-04-01 18:55:09 +0000608 break;
cristybb503372010-05-27 20:51:26 +0000609 for (x=0; x < (ssize_t) image->columns; x++)
cristyda06ed12009-10-14 18:36:54 +0000610 {
cristy4c08aed2011-07-01 19:47:50 +0000611 if (IsPixelGray(image,p) == MagickFalse)
cristyda06ed12009-10-14 18:36:54 +0000612 {
cristy5f1c1ff2010-12-23 21:38:06 +0000613 type=UndefinedType;
cristyda06ed12009-10-14 18:36:54 +0000614 break;
cristy0910f242010-04-01 18:55:09 +0000615 }
cristy4c08aed2011-07-01 19:47:50 +0000616 if ((type == BilevelType) &&
617 (IsPixelMonochrome(image,p) == MagickFalse))
cristy0910f242010-04-01 18:55:09 +0000618 type=GrayscaleType;
cristy4c08aed2011-07-01 19:47:50 +0000619 p+=GetPixelChannels(image);
cristyda06ed12009-10-14 18:36:54 +0000620 }
cristy5f1c1ff2010-12-23 21:38:06 +0000621 if (type == UndefinedType)
cristyda06ed12009-10-14 18:36:54 +0000622 break;
cristyda06ed12009-10-14 18:36:54 +0000623 }
cristy0910f242010-04-01 18:55:09 +0000624 image_view=DestroyCacheView(image_view);
cristy5f1c1ff2010-12-23 21:38:06 +0000625 if (type == UndefinedType)
cristyda06ed12009-10-14 18:36:54 +0000626 return(MagickFalse);
627 ((Image *) image)->type=type;
628 if ((type == GrayscaleType) && (image->matte != MagickFalse))
629 ((Image *) image)->type=GrayscaleMatteType;
630 return(MagickTrue);
631}
632
633/*
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635% %
636% %
637% %
cristy4c08aed2011-07-01 19:47:50 +0000638% I s I m a g e M o n o c h r o m e %
cristyda06ed12009-10-14 18:36:54 +0000639% %
640% %
641% %
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%
cristy4c08aed2011-07-01 19:47:50 +0000644% IsImageMonochrome() returns MagickTrue if all the pixels in the image have
cristyda06ed12009-10-14 18:36:54 +0000645% the same red, green, and blue intensities and the intensity is either
646% 0 or QuantumRange.
647%
cristy4c08aed2011-07-01 19:47:50 +0000648% The format of the IsImageMonochrome method is:
cristyda06ed12009-10-14 18:36:54 +0000649%
cristy4c08aed2011-07-01 19:47:50 +0000650% MagickBooleanType IsImageMonochrome(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000651% ExceptionInfo *exception)
652%
653% A description of each parameter follows:
654%
655% o image: the image.
656%
657% o exception: return any errors or warnings in this structure.
658%
659*/
cristy4c08aed2011-07-01 19:47:50 +0000660MagickExport MagickBooleanType IsImageMonochrome(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000661 ExceptionInfo *exception)
662{
cristy0910f242010-04-01 18:55:09 +0000663 CacheView
664 *image_view;
665
cristyda06ed12009-10-14 18:36:54 +0000666 ImageType
667 type;
668
cristybb503372010-05-27 20:51:26 +0000669 register ssize_t
cristy0910f242010-04-01 18:55:09 +0000670 x;
671
cristy4c08aed2011-07-01 19:47:50 +0000672 register const Quantum
cristyda06ed12009-10-14 18:36:54 +0000673 *p;
674
cristy9d314ff2011-03-09 01:30:28 +0000675 ssize_t
676 y;
677
cristyda06ed12009-10-14 18:36:54 +0000678 assert(image != (Image *) NULL);
679 assert(image->signature == MagickSignature);
680 if (image->debug != MagickFalse)
681 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
682 if (image->type == BilevelType)
683 return(MagickTrue);
684 if (image->colorspace == CMYKColorspace)
685 return(MagickFalse);
686 type=BilevelType;
cristy0910f242010-04-01 18:55:09 +0000687 image_view=AcquireCacheView(image);
cristybb503372010-05-27 20:51:26 +0000688 for (y=0; y < (ssize_t) image->rows; y++)
cristyda06ed12009-10-14 18:36:54 +0000689 {
cristy0910f242010-04-01 18:55:09 +0000690 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000691 if (p == (const Quantum *) NULL)
cristy0910f242010-04-01 18:55:09 +0000692 break;
cristybb503372010-05-27 20:51:26 +0000693 for (x=0; x < (ssize_t) image->columns; x++)
cristyda06ed12009-10-14 18:36:54 +0000694 {
cristy4c08aed2011-07-01 19:47:50 +0000695 if (IsPixelMonochrome(image,p) == MagickFalse)
cristyda06ed12009-10-14 18:36:54 +0000696 {
cristy5f1c1ff2010-12-23 21:38:06 +0000697 type=UndefinedType;
cristyda06ed12009-10-14 18:36:54 +0000698 break;
cristy0910f242010-04-01 18:55:09 +0000699 }
cristy4c08aed2011-07-01 19:47:50 +0000700 p+=GetPixelChannels(image);
cristyda06ed12009-10-14 18:36:54 +0000701 }
cristy5f1c1ff2010-12-23 21:38:06 +0000702 if (type == UndefinedType)
cristyda06ed12009-10-14 18:36:54 +0000703 break;
cristyda06ed12009-10-14 18:36:54 +0000704 }
cristy0910f242010-04-01 18:55:09 +0000705 image_view=DestroyCacheView(image_view);
cristy5f1c1ff2010-12-23 21:38:06 +0000706 if (type == UndefinedType)
cristyda06ed12009-10-14 18:36:54 +0000707 return(MagickFalse);
708 ((Image *) image)->type=type;
709 return(MagickTrue);
710}
711
712/*
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714% %
715% %
716% %
cristy4c08aed2011-07-01 19:47:50 +0000717% I s I m a g e O p a q u e %
cristyda06ed12009-10-14 18:36:54 +0000718% %
719% %
720% %
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722%
cristy4c08aed2011-07-01 19:47:50 +0000723% IsImageOpaque() returns MagickTrue if none of the pixels in the image have
cristyda06ed12009-10-14 18:36:54 +0000724% an opacity value other than opaque (0).
725%
cristy4c08aed2011-07-01 19:47:50 +0000726% The format of the IsImageOpaque method is:
cristyda06ed12009-10-14 18:36:54 +0000727%
cristy4c08aed2011-07-01 19:47:50 +0000728% MagickBooleanType IsImageOpaque(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000729% ExceptionInfo *exception)
730%
731% A description of each parameter follows:
732%
733% o image: the image.
734%
735% o exception: return any errors or warnings in this structure.
736%
737*/
cristy4c08aed2011-07-01 19:47:50 +0000738MagickExport MagickBooleanType IsImageOpaque(const Image *image,
cristyda06ed12009-10-14 18:36:54 +0000739 ExceptionInfo *exception)
740{
cristyc4c8d132010-01-07 01:58:38 +0000741 CacheView
742 *image_view;
743
cristy4c08aed2011-07-01 19:47:50 +0000744 register const Quantum
cristyda06ed12009-10-14 18:36:54 +0000745 *p;
746
cristybb503372010-05-27 20:51:26 +0000747 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000748 x;
749
cristy9d314ff2011-03-09 01:30:28 +0000750 ssize_t
751 y;
752
cristyda06ed12009-10-14 18:36:54 +0000753 /*
754 Determine if image is opaque.
755 */
756 assert(image != (Image *) NULL);
757 assert(image->signature == MagickSignature);
758 if (image->debug != MagickFalse)
759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
760 if (image->matte == MagickFalse)
761 return(MagickTrue);
762 image_view=AcquireCacheView(image);
cristybb503372010-05-27 20:51:26 +0000763 for (y=0; y < (ssize_t) image->rows; y++)
cristyda06ed12009-10-14 18:36:54 +0000764 {
765 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000766 if (p == (const Quantum *) NULL)
cristyda06ed12009-10-14 18:36:54 +0000767 break;
cristybb503372010-05-27 20:51:26 +0000768 for (x=0; x < (ssize_t) image->columns; x++)
cristyda06ed12009-10-14 18:36:54 +0000769 {
cristy4c08aed2011-07-01 19:47:50 +0000770 if (GetPixelAlpha(image,p) != OpaqueAlpha)
cristyda06ed12009-10-14 18:36:54 +0000771 break;
cristy4c08aed2011-07-01 19:47:50 +0000772 p+=GetPixelChannels(image);
cristyda06ed12009-10-14 18:36:54 +0000773 }
cristybb503372010-05-27 20:51:26 +0000774 if (x < (ssize_t) image->columns)
cristyda06ed12009-10-14 18:36:54 +0000775 break;
776 }
777 image_view=DestroyCacheView(image_view);
cristybb503372010-05-27 20:51:26 +0000778 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
cristyda06ed12009-10-14 18:36:54 +0000779}
780
781/*
782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783% %
784% %
785% %
786% S e t I m a g e C h a n n e l D e p t h %
787% %
788% %
789% %
790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
791%
792% SetImageChannelDepth() sets the depth of the image.
793%
794% The format of the SetImageChannelDepth method is:
795%
cristybb503372010-05-27 20:51:26 +0000796% MagickBooleanType SetImageDepth(Image *image,const size_t depth)
cristyda06ed12009-10-14 18:36:54 +0000797% MagickBooleanType SetImageChannelDepth(Image *image,
cristybb503372010-05-27 20:51:26 +0000798% const ChannelType channel,const size_t depth)
cristyda06ed12009-10-14 18:36:54 +0000799%
800% A description of each parameter follows:
801%
802% o image: the image.
803%
804% o channel: the channel.
805%
806% o depth: the image depth.
807%
808*/
cristyda06ed12009-10-14 18:36:54 +0000809MagickExport MagickBooleanType SetImageDepth(Image *image,
cristybb503372010-05-27 20:51:26 +0000810 const size_t depth)
cristyda06ed12009-10-14 18:36:54 +0000811{
cristy9a9230e2011-04-26 14:56:14 +0000812 return(SetImageChannelDepth(image,CompositeChannels,depth));
cristyda06ed12009-10-14 18:36:54 +0000813}
814
815MagickExport MagickBooleanType SetImageChannelDepth(Image *image,
cristybb503372010-05-27 20:51:26 +0000816 const ChannelType channel,const size_t depth)
cristyda06ed12009-10-14 18:36:54 +0000817{
cristyc4c8d132010-01-07 01:58:38 +0000818 CacheView
819 *image_view;
820
cristyda06ed12009-10-14 18:36:54 +0000821 ExceptionInfo
822 *exception;
823
cristyda06ed12009-10-14 18:36:54 +0000824 MagickBooleanType
825 status;
826
827 QuantumAny
cristyb6d6f7c2010-06-09 13:17:57 +0000828 range;
cristyda06ed12009-10-14 18:36:54 +0000829
cristy9d314ff2011-03-09 01:30:28 +0000830 ssize_t
831 y;
832
cristyda06ed12009-10-14 18:36:54 +0000833 assert(image != (Image *) NULL);
834 if (image->debug != MagickFalse)
835 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
836 assert(image->signature == MagickSignature);
cristybb503372010-05-27 20:51:26 +0000837 if (GetImageDepth(image,&image->exception) <= (size_t)
cristyda06ed12009-10-14 18:36:54 +0000838 MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH))
839 {
840 image->depth=depth;
841 return(MagickTrue);
842 }
843 /*
844 Scale pixels to desired depth.
845 */
846 status=MagickTrue;
cristyb6d6f7c2010-06-09 13:17:57 +0000847 range=GetQuantumRange(depth);
cristyda06ed12009-10-14 18:36:54 +0000848 exception=(&image->exception);
849 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +0000850#if defined(MAGICKCORE_OPENMP_SUPPORT)
851 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristyda06ed12009-10-14 18:36:54 +0000852#endif
cristybb503372010-05-27 20:51:26 +0000853 for (y=0; y < (ssize_t) image->rows; y++)
cristyda06ed12009-10-14 18:36:54 +0000854 {
cristybb503372010-05-27 20:51:26 +0000855 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000856 x;
857
cristy4c08aed2011-07-01 19:47:50 +0000858 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000859 *restrict q;
cristyda06ed12009-10-14 18:36:54 +0000860
861 if (status == MagickFalse)
862 continue;
863 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
864 exception);
cristy4c08aed2011-07-01 19:47:50 +0000865 if (q == (const Quantum *) NULL)
cristyda06ed12009-10-14 18:36:54 +0000866 {
867 status=MagickFalse;
868 continue;
869 }
cristybb503372010-05-27 20:51:26 +0000870 for (x=0; x < (ssize_t) image->columns; x++)
cristyda06ed12009-10-14 18:36:54 +0000871 {
872 if ((channel & RedChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000873 SetPixelRed(image,ScaleAnyToQuantum(ScaleQuantumToAny(
874 GetPixelRed(image,q),range),range),q);
cristyda06ed12009-10-14 18:36:54 +0000875 if ((channel & GreenChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000876 SetPixelGreen(image,ScaleAnyToQuantum(ScaleQuantumToAny(
877 GetPixelGreen(image,q),range),range),q);
cristyda06ed12009-10-14 18:36:54 +0000878 if ((channel & BlueChannel) != 0)
cristy4c08aed2011-07-01 19:47:50 +0000879 SetPixelBlue(image,ScaleAnyToQuantum(ScaleQuantumToAny(
880 GetPixelBlue(image,q),range),range),q);
881 if (((channel & BlackChannel) != 0) &&
cristyda06ed12009-10-14 18:36:54 +0000882 (image->colorspace == CMYKColorspace))
cristy4c08aed2011-07-01 19:47:50 +0000883 SetPixelBlack(image,ScaleAnyToQuantum(ScaleQuantumToAny(
884 GetPixelBlack(image,q),range),range),q);
885 if (((channel & AlphaChannel) != 0) && (image->matte != MagickFalse))
886 SetPixelAlpha(image,ScaleAnyToQuantum(ScaleQuantumToAny(
887 GetPixelAlpha(image,q),range),range),q);
888 q+=GetPixelChannels(image);
cristyda06ed12009-10-14 18:36:54 +0000889 }
890 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
891 {
892 status=MagickFalse;
893 continue;
894 }
895 }
896 image_view=DestroyCacheView(image_view);
897 if (image->storage_class == PseudoClass)
898 {
cristybb503372010-05-27 20:51:26 +0000899 register ssize_t
cristyda06ed12009-10-14 18:36:54 +0000900 i;
901
902 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000903 *restrict p;
cristyda06ed12009-10-14 18:36:54 +0000904
905 p=image->colormap;
cristyb5d5f722009-11-04 03:03:49 +0000906#if defined(MAGICKCORE_OPENMP_SUPPORT)
907 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristyda06ed12009-10-14 18:36:54 +0000908#endif
cristybb503372010-05-27 20:51:26 +0000909 for (i=0; i < (ssize_t) image->colors; i++)
cristyda06ed12009-10-14 18:36:54 +0000910 {
911 if ((channel & RedChannel) != 0)
cristy9384eed2011-06-13 14:16:32 +0000912 p->red=ScaleAnyToQuantum(ScaleQuantumToAny(p->red,range),range);
cristyda06ed12009-10-14 18:36:54 +0000913 if ((channel & GreenChannel) != 0)
cristy9384eed2011-06-13 14:16:32 +0000914 p->green=ScaleAnyToQuantum(ScaleQuantumToAny(p->green,range),range);
cristyda06ed12009-10-14 18:36:54 +0000915 if ((channel & BlueChannel) != 0)
cristy9384eed2011-06-13 14:16:32 +0000916 p->blue=ScaleAnyToQuantum(ScaleQuantumToAny(p->blue,range),range);
cristy4c08aed2011-07-01 19:47:50 +0000917 if ((channel & AlphaChannel) != 0)
918 p->alpha=ScaleAnyToQuantum(ScaleQuantumToAny(p->alpha,range),range);
cristyda06ed12009-10-14 18:36:54 +0000919 p++;
920 }
921 }
922 image->depth=depth;
923 return(status);
924}