1 /*
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 % Cristy %
17 % October 2002 %
18 % %
19 % %
20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
21 % 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 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/artifact.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/blob.h"
47 #include "MagickCore/blob-private.h"
48 #include "MagickCore/cache.h"
49 #include "MagickCore/cache-private.h"
50 #include "MagickCore/cache-view.h"
51 #include "MagickCore/channel.h"
52 #include "MagickCore/client.h"
53 #include "MagickCore/color.h"
54 #include "MagickCore/color-private.h"
55 #include "MagickCore/colormap.h"
56 #include "MagickCore/colormap-private.h"
57 #include "MagickCore/colorspace.h"
58 #include "MagickCore/colorspace-private.h"
59 #include "MagickCore/composite.h"
60 #include "MagickCore/composite-private.h"
61 #include "MagickCore/constitute.h"
62 #include "MagickCore/draw.h"
63 #include "MagickCore/draw-private.h"
64 #include "MagickCore/effect.h"
65 #include "MagickCore/enhance.h"
66 #include "MagickCore/exception.h"
67 #include "MagickCore/exception-private.h"
68 #include "MagickCore/geometry.h"
69 #include "MagickCore/histogram.h"
70 #include "MagickCore/identify.h"
71 #include "MagickCore/image.h"
72 #include "MagickCore/image-private.h"
73 #include "MagickCore/list.h"
74 #include "MagickCore/log.h"
75 #include "MagickCore/memory_.h"
76 #include "MagickCore/magick.h"
77 #include "MagickCore/monitor.h"
78 #include "MagickCore/monitor-private.h"
79 #include "MagickCore/option.h"
80 #include "MagickCore/paint.h"
81 #include "MagickCore/pixel.h"
82 #include "MagickCore/pixel-accessor.h"
83 #include "MagickCore/property.h"
84 #include "MagickCore/quantize.h"
85 #include "MagickCore/quantum-private.h"
86 #include "MagickCore/random_.h"
87 #include "MagickCore/resource_.h"
88 #include "MagickCore/semaphore.h"
89 #include "MagickCore/segment.h"
90 #include "MagickCore/splay-tree.h"
91 #include "MagickCore/string_.h"
92 #include "MagickCore/thread-private.h"
93 #include "MagickCore/threshold.h"
94 #include "MagickCore/transform.h"
95 #include "MagickCore/utility.h"
96
97 /*
98 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99 % %
100 % %
101 % %
102 + G e t I m a g e B o u n d i n g B o x %
103 % %
104 % %
105 % %
106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107 %
108 % GetImageBoundingBox() returns the bounding box of an image canvas.
109 %
110 % The format of the GetImageBoundingBox method is:
111 %
112 % RectangleInfo GetImageBoundingBox(const Image *image,
113 % ExceptionInfo *exception)
114 %
115 % A description of each parameter follows:
116 %
117 % o bounds: Method GetImageBoundingBox returns the bounding box of an
118 % image canvas.
119 %
120 % o image: the image.
121 %
122 % o exception: return any errors or warnings in this structure.
123 %
124 */
GetImageBoundingBox(const Image * image,ExceptionInfo * exception)125 MagickExport RectangleInfo GetImageBoundingBox(const Image *image,
126 ExceptionInfo *exception)
127 {
128 CacheView
129 *image_view;
130
131 MagickBooleanType
132 status;
133
134 PixelInfo
135 target[3],
136 zero;
137
138 RectangleInfo
139 bounds;
140
141 register const Quantum
142 *r;
143
144 ssize_t
145 y;
146
147 assert(image != (Image *) NULL);
148 assert(image->signature == MagickCoreSignature);
149 if (image->debug != MagickFalse)
150 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
151 bounds.width=0;
152 bounds.height=0;
153 bounds.x=(ssize_t) image->columns;
154 bounds.y=(ssize_t) image->rows;
155 GetPixelInfo(image,&target[0]);
156 image_view=AcquireVirtualCacheView(image,exception);
157 r=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
158 if (r == (const Quantum *) NULL)
159 {
160 image_view=DestroyCacheView(image_view);
161 return(bounds);
162 }
163 GetPixelInfoPixel(image,r,&target[0]);
164 GetPixelInfo(image,&target[1]);
165 r=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
166 exception);
167 if (r != (const Quantum *) NULL)
168 GetPixelInfoPixel(image,r,&target[1]);
169 GetPixelInfo(image,&target[2]);
170 r=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
171 exception);
172 if (r != (const Quantum *) NULL)
173 GetPixelInfoPixel(image,r,&target[2]);
174 status=MagickTrue;
175 GetPixelInfo(image,&zero);
176 #if defined(MAGICKCORE_OPENMP_SUPPORT)
177 #pragma omp parallel for schedule(static,4) shared(status) \
178 magick_threads(image,image,image->rows,1)
179 #endif
180 for (y=0; y < (ssize_t) image->rows; y++)
181 {
182 PixelInfo
183 pixel;
184
185 RectangleInfo
186 bounding_box;
187
188 register const Quantum
189 *magick_restrict p;
190
191 register ssize_t
192 x;
193
194 if (status == MagickFalse)
195 continue;
196 #if defined(MAGICKCORE_OPENMP_SUPPORT)
197 # pragma omp critical (MagickCore_GetImageBoundingBox)
198 #endif
199 bounding_box=bounds;
200 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
201 if (p == (const Quantum *) NULL)
202 {
203 status=MagickFalse;
204 continue;
205 }
206 pixel=zero;
207 for (x=0; x < (ssize_t) image->columns; x++)
208 {
209 GetPixelInfoPixel(image,p,&pixel);
210 if ((x < bounding_box.x) &&
211 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
212 bounding_box.x=x;
213 if ((x > (ssize_t) bounding_box.width) &&
214 (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse))
215 bounding_box.width=(size_t) x;
216 if ((y < bounding_box.y) &&
217 (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse))
218 bounding_box.y=y;
219 if ((y > (ssize_t) bounding_box.height) &&
220 (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse))
221 bounding_box.height=(size_t) y;
222 p+=GetPixelChannels(image);
223 }
224 #if defined(MAGICKCORE_OPENMP_SUPPORT)
225 # pragma omp critical (MagickCore_GetImageBoundingBox)
226 #endif
227 {
228 if (bounding_box.x < bounds.x)
229 bounds.x=bounding_box.x;
230 if (bounding_box.y < bounds.y)
231 bounds.y=bounding_box.y;
232 if (bounding_box.width > bounds.width)
233 bounds.width=bounding_box.width;
234 if (bounding_box.height > bounds.height)
235 bounds.height=bounding_box.height;
236 }
237 }
238 image_view=DestroyCacheView(image_view);
239 if ((bounds.width == 0) && (bounds.height == 0))
240 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
241 "GeometryDoesNotContainImage","`%s'",image->filename);
242 else
243 {
244 bounds.width-=(bounds.x-1);
245 bounds.height-=(bounds.y-1);
246 }
247 return(bounds);
248 }
249
250 /*
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % %
253 % %
254 % %
255 % G e t I m a g e D e p t h %
256 % %
257 % %
258 % %
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 %
261 % GetImageDepth() returns the depth of a particular image channel.
262 %
263 % The format of the GetImageDepth method is:
264 %
265 % size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
266 %
267 % A description of each parameter follows:
268 %
269 % o image: the image.
270 %
271 % o exception: return any errors or warnings in this structure.
272 %
273 */
GetImageDepth(const Image * image,ExceptionInfo * exception)274 MagickExport size_t GetImageDepth(const Image *image,ExceptionInfo *exception)
275 {
276 CacheView
277 *image_view;
278
279 MagickBooleanType
280 status;
281
282 register ssize_t
283 i;
284
285 size_t
286 *current_depth,
287 depth,
288 number_threads;
289
290 ssize_t
291 y;
292
293 /*
294 Compute image depth.
295 */
296 assert(image != (Image *) NULL);
297 assert(image->signature == MagickCoreSignature);
298 if (image->debug != MagickFalse)
299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
300 number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
301 current_depth=(size_t *) AcquireQuantumMemory(number_threads,
302 sizeof(*current_depth));
303 if (current_depth == (size_t *) NULL)
304 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
305 status=MagickTrue;
306 for (i=0; i < (ssize_t) number_threads; i++)
307 current_depth[i]=1;
308 if ((image->storage_class == PseudoClass) &&
309 (image->alpha_trait == UndefinedPixelTrait))
310 {
311 #if defined(MAGICKCORE_OPENMP_SUPPORT)
312 #pragma omp parallel for schedule(static,4) shared(status) \
313 if ((image->colors) > 256) \
314 num_threads(GetMagickResourceLimit(ThreadResource))
315 #endif
316 for (i=0; i < (ssize_t) image->colors; i++)
317 {
318 const int
319 id = GetOpenMPThreadId();
320
321 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
322 {
323 MagickBooleanType
324 atDepth;
325
326 QuantumAny
327 range;
328
329 atDepth=MagickTrue;
330 range=GetQuantumRange(current_depth[id]);
331 if ((atDepth != MagickFalse) &&
332 (GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
333 if (IsPixelAtDepth(image->colormap[i].red,range) == MagickFalse)
334 atDepth=MagickFalse;
335 if ((atDepth != MagickFalse) &&
336 (GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
337 if (IsPixelAtDepth(image->colormap[i].green,range) == MagickFalse)
338 atDepth=MagickFalse;
339 if ((atDepth != MagickFalse) &&
340 (GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
341 if (IsPixelAtDepth(image->colormap[i].blue,range) == MagickFalse)
342 atDepth=MagickFalse;
343 if ((atDepth != MagickFalse))
344 break;
345 current_depth[id]++;
346 }
347 }
348 depth=current_depth[0];
349 for (i=1; i < (ssize_t) number_threads; i++)
350 if (depth < current_depth[i])
351 depth=current_depth[i];
352 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
353 return(depth);
354 }
355 image_view=AcquireVirtualCacheView(image,exception);
356 #if !defined(MAGICKCORE_HDRI_SUPPORT)
357 if (QuantumRange <= MaxMap)
358 {
359 size_t
360 *depth_map;
361
362 /*
363 Scale pixels to desired (optimized with depth map).
364 */
365 depth_map=(size_t *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
366 if (depth_map == (size_t *) NULL)
367 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
368 for (i=0; i <= (ssize_t) MaxMap; i++)
369 {
370 unsigned int
371 depth;
372
373 for (depth=1; depth < MAGICKCORE_QUANTUM_DEPTH; depth++)
374 {
375 Quantum
376 pixel;
377
378 QuantumAny
379 range;
380
381 range=GetQuantumRange(depth);
382 pixel=(Quantum) i;
383 if (pixel == ScaleAnyToQuantum(ScaleQuantumToAny(pixel,range),range))
384 break;
385 }
386 depth_map[i]=depth;
387 }
388 #if defined(MAGICKCORE_OPENMP_SUPPORT)
389 #pragma omp parallel for schedule(static,4) shared(status) \
390 magick_threads(image,image,image->rows,1)
391 #endif
392 for (y=0; y < (ssize_t) image->rows; y++)
393 {
394 const int
395 id = GetOpenMPThreadId();
396
397 register const Quantum
398 *magick_restrict p;
399
400 register ssize_t
401 x;
402
403 if (status == MagickFalse)
404 continue;
405 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
406 if (p == (const Quantum *) NULL)
407 continue;
408 for (x=0; x < (ssize_t) image->columns; x++)
409 {
410 if (GetPixelReadMask(image,p) == 0)
411 {
412 p+=GetPixelChannels(image);
413 continue;
414 }
415 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
416 {
417 PixelChannel channel=GetPixelChannelChannel(image,i);
418 PixelTrait traits=GetPixelChannelTraits(image,channel);
419 if ((traits == UndefinedPixelTrait) ||
420 (channel == IndexPixelChannel) ||
421 (channel == ReadMaskPixelChannel) ||
422 (channel == MetaPixelChannel))
423 continue;
424 if (depth_map[ScaleQuantumToMap(p[i])] > current_depth[id])
425 current_depth[id]=depth_map[ScaleQuantumToMap(p[i])];
426 }
427 p+=GetPixelChannels(image);
428 }
429 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
430 status=MagickFalse;
431 }
432 image_view=DestroyCacheView(image_view);
433 depth=current_depth[0];
434 for (i=1; i < (ssize_t) number_threads; i++)
435 if (depth < current_depth[i])
436 depth=current_depth[i];
437 depth_map=(size_t *) RelinquishMagickMemory(depth_map);
438 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
439 return(depth);
440 }
441 #endif
442 /*
443 Compute pixel depth.
444 */
445 #if defined(MAGICKCORE_OPENMP_SUPPORT)
446 #pragma omp parallel for schedule(static,4) shared(status) \
447 magick_threads(image,image,image->rows,1)
448 #endif
449 for (y=0; y < (ssize_t) image->rows; y++)
450 {
451 const int
452 id = GetOpenMPThreadId();
453
454 register const Quantum
455 *magick_restrict p;
456
457 register ssize_t
458 x;
459
460 if (status == MagickFalse)
461 continue;
462 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
463 if (p == (const Quantum *) NULL)
464 continue;
465 for (x=0; x < (ssize_t) image->columns; x++)
466 {
467 if (GetPixelReadMask(image,p) == 0)
468 {
469 p+=GetPixelChannels(image);
470 continue;
471 }
472 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
473 {
474 PixelChannel
475 channel;
476
477 PixelTrait
478 traits;
479
480 channel=GetPixelChannelChannel(image,i);
481 traits=GetPixelChannelTraits(image,channel);
482 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
483 (channel == ReadMaskPixelChannel))
484 continue;
485 while (current_depth[id] < MAGICKCORE_QUANTUM_DEPTH)
486 {
487 QuantumAny
488 range;
489
490 range=GetQuantumRange(current_depth[id]);
491 if (p[i] == ScaleAnyToQuantum(ScaleQuantumToAny(p[i],range),range))
492 break;
493 current_depth[id]++;
494 }
495 }
496 p+=GetPixelChannels(image);
497 }
498 if (current_depth[id] == MAGICKCORE_QUANTUM_DEPTH)
499 status=MagickFalse;
500 }
501 image_view=DestroyCacheView(image_view);
502 depth=current_depth[0];
503 for (i=1; i < (ssize_t) number_threads; i++)
504 if (depth < current_depth[i])
505 depth=current_depth[i];
506 current_depth=(size_t *) RelinquishMagickMemory(current_depth);
507 return(depth);
508 }
509
510 /*
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 % %
513 % %
514 % %
515 % G e t I m a g e Q u a n t u m D e p t h %
516 % %
517 % %
518 % %
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 %
521 % GetImageQuantumDepth() returns the depth of the image rounded to a legal
522 % quantum depth: 8, 16, or 32.
523 %
524 % The format of the GetImageQuantumDepth method is:
525 %
526 % size_t GetImageQuantumDepth(const Image *image,
527 % const MagickBooleanType constrain)
528 %
529 % A description of each parameter follows:
530 %
531 % o image: the image.
532 %
533 % o constrain: A value other than MagickFalse, constrains the depth to
534 % a maximum of MAGICKCORE_QUANTUM_DEPTH.
535 %
536 */
GetImageQuantumDepth(const Image * image,const MagickBooleanType constrain)537 MagickExport size_t GetImageQuantumDepth(const Image *image,
538 const MagickBooleanType constrain)
539 {
540 size_t
541 depth;
542
543 depth=image->depth;
544 if (depth <= 8)
545 depth=8;
546 else
547 if (depth <= 16)
548 depth=16;
549 else
550 if (depth <= 32)
551 depth=32;
552 else
553 if (depth <= 64)
554 depth=64;
555 if (constrain != MagickFalse)
556 depth=(size_t) MagickMin((double) depth,(double) MAGICKCORE_QUANTUM_DEPTH);
557 return(depth);
558 }
559
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 % %
563 % %
564 % %
565 % G e t I m a g e T y p e %
566 % %
567 % %
568 % %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 % GetImageType() returns the type of image:
572 %
573 % Bilevel Grayscale GrayscaleMatte
574 % Palette PaletteMatte TrueColor
575 % TrueColorMatte ColorSeparation ColorSeparationMatte
576 %
577 % The format of the GetImageType method is:
578 %
579 % ImageType GetImageType(const Image *image)
580 %
581 % A description of each parameter follows:
582 %
583 % o image: the image.
584 %
585 */
GetImageType(const Image * image)586 MagickExport ImageType GetImageType(const Image *image)
587 {
588 assert(image != (Image *) NULL);
589 assert(image->signature == MagickCoreSignature);
590 if (image->colorspace == CMYKColorspace)
591 {
592 if (image->alpha_trait == UndefinedPixelTrait)
593 return(ColorSeparationType);
594 return(ColorSeparationAlphaType);
595 }
596 if (IsImageMonochrome(image) != MagickFalse)
597 return(BilevelType);
598 if (IsImageGray(image) != MagickFalse)
599 {
600 if (image->alpha_trait != UndefinedPixelTrait)
601 return(GrayscaleAlphaType);
602 return(GrayscaleType);
603 }
604 if (IsPaletteImage(image) != MagickFalse)
605 {
606 if (image->alpha_trait != UndefinedPixelTrait)
607 return(PaletteAlphaType);
608 return(PaletteType);
609 }
610 if (image->alpha_trait != UndefinedPixelTrait)
611 return(TrueColorAlphaType);
612 return(TrueColorType);
613 }
614
615 /*
616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617 % %
618 % %
619 % %
620 % I d e n t i f y I m a g e G r a y %
621 % %
622 % %
623 % %
624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625 %
626 % IdentifyImageGray() returns grayscale if all the pixels in the image have
627 % the same red, green, and blue intensities, and bi-level is the intensity is
628 % either 0 or QuantumRange. Otherwise undefined is returned.
629 %
630 % The format of the IdentifyImageGray method is:
631 %
632 % ImageType IdentifyImageGray(const Image *image,ExceptionInfo *exception)
633 %
634 % A description of each parameter follows:
635 %
636 % o image: the image.
637 %
638 % o exception: return any errors or warnings in this structure.
639 %
640 */
IdentifyImageGray(const Image * image,ExceptionInfo * exception)641 MagickExport ImageType IdentifyImageGray(const Image *image,
642 ExceptionInfo *exception)
643 {
644 CacheView
645 *image_view;
646
647 ImageType
648 type;
649
650 register const Quantum
651 *p;
652
653 register ssize_t
654 x;
655
656 ssize_t
657 y;
658
659 assert(image != (Image *) NULL);
660 assert(image->signature == MagickCoreSignature);
661 if (image->debug != MagickFalse)
662 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
663 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
664 (image->type == GrayscaleAlphaType))
665 return(image->type);
666 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
667 return(UndefinedType);
668 type=BilevelType;
669 image_view=AcquireVirtualCacheView(image,exception);
670 for (y=0; y < (ssize_t) image->rows; y++)
671 {
672 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
673 if (p == (const Quantum *) NULL)
674 break;
675 for (x=0; x < (ssize_t) image->columns; x++)
676 {
677 if (IsPixelGray(image,p) == MagickFalse)
678 {
679 type=UndefinedType;
680 break;
681 }
682 if ((type == BilevelType) &&
683 (IsPixelMonochrome(image,p) == MagickFalse))
684 type=GrayscaleType;
685 p+=GetPixelChannels(image);
686 }
687 if (type == UndefinedType)
688 break;
689 }
690 image_view=DestroyCacheView(image_view);
691 if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
692 type=GrayscaleAlphaType;
693 return(type);
694 }
695
696 /*
697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698 % %
699 % %
700 % %
701 % I d e n t i f y I m a g e M o n o c h r o m e %
702 % %
703 % %
704 % %
705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706 %
707 % IdentifyImageMonochrome() returns MagickTrue if all the pixels in the image
708 % have the same red, green, and blue intensities and the intensity is either
709 % 0 or QuantumRange.
710 %
711 % The format of the IdentifyImageMonochrome method is:
712 %
713 % MagickBooleanType IdentifyImageMonochrome(const Image *image,
714 % ExceptionInfo *exception)
715 %
716 % A description of each parameter follows:
717 %
718 % o image: the image.
719 %
720 % o exception: return any errors or warnings in this structure.
721 %
722 */
IdentifyImageMonochrome(const Image * image,ExceptionInfo * exception)723 MagickExport MagickBooleanType IdentifyImageMonochrome(const Image *image,
724 ExceptionInfo *exception)
725 {
726 CacheView
727 *image_view;
728
729 ImageType
730 type;
731
732 register ssize_t
733 x;
734
735 register const Quantum
736 *p;
737
738 ssize_t
739 y;
740
741 assert(image != (Image *) NULL);
742 assert(image->signature == MagickCoreSignature);
743 if (image->debug != MagickFalse)
744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
745 if (image->type == BilevelType)
746 return(MagickTrue);
747 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
748 return(MagickFalse);
749 type=BilevelType;
750 image_view=AcquireVirtualCacheView(image,exception);
751 for (y=0; y < (ssize_t) image->rows; y++)
752 {
753 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
754 if (p == (const Quantum *) NULL)
755 break;
756 for (x=0; x < (ssize_t) image->columns; x++)
757 {
758 if (IsPixelMonochrome(image,p) == MagickFalse)
759 {
760 type=UndefinedType;
761 break;
762 }
763 p+=GetPixelChannels(image);
764 }
765 if (type == UndefinedType)
766 break;
767 }
768 image_view=DestroyCacheView(image_view);
769 if (type == BilevelType)
770 return(MagickTrue);
771 return(MagickFalse);
772 }
773
774 /*
775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776 % %
777 % %
778 % %
779 % I d e n t i f y I m a g e T y p e %
780 % %
781 % %
782 % %
783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784 %
785 % IdentifyImageType() returns the potential type of image:
786 %
787 % Bilevel Grayscale GrayscaleMatte
788 % Palette PaletteMatte TrueColor
789 % TrueColorMatte ColorSeparation ColorSeparationMatte
790 %
791 % To ensure the image type matches its potential, use SetImageType():
792 %
793 % (void) SetImageType(image,IdentifyImageType(image,exception),exception);
794 %
795 % The format of the IdentifyImageType method is:
796 %
797 % ImageType IdentifyImageType(const Image *image,ExceptionInfo *exception)
798 %
799 % A description of each parameter follows:
800 %
801 % o image: the image.
802 %
803 % o exception: return any errors or warnings in this structure.
804 %
805 */
IdentifyImageType(const Image * image,ExceptionInfo * exception)806 MagickExport ImageType IdentifyImageType(const Image *image,
807 ExceptionInfo *exception)
808 {
809 assert(image != (Image *) NULL);
810 assert(image->signature == MagickCoreSignature);
811 if (image->debug != MagickFalse)
812 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
813 if (image->colorspace == CMYKColorspace)
814 {
815 if (image->alpha_trait == UndefinedPixelTrait)
816 return(ColorSeparationType);
817 return(ColorSeparationAlphaType);
818 }
819 if (IdentifyImageMonochrome(image,exception) != MagickFalse)
820 return(BilevelType);
821 if (IdentifyImageGray(image,exception) != UndefinedType)
822 {
823 if (image->alpha_trait != UndefinedPixelTrait)
824 return(GrayscaleAlphaType);
825 return(GrayscaleType);
826 }
827 if (IdentifyPaletteImage(image,exception) != MagickFalse)
828 {
829 if (image->alpha_trait != UndefinedPixelTrait)
830 return(PaletteAlphaType);
831 return(PaletteType);
832 }
833 if (image->alpha_trait != UndefinedPixelTrait)
834 return(TrueColorAlphaType);
835 return(TrueColorType);
836 }
837
838 /*
839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
840 % %
841 % %
842 % %
843 % I s I m a g e G r a y %
844 % %
845 % %
846 % %
847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848 %
849 % IsImageGray() returns MagickTrue if the type of the image is grayscale or
850 % bi-level.
851 %
852 % The format of the IsImageGray method is:
853 %
854 % MagickBooleanType IsImageGray(const Image *image)
855 %
856 % A description of each parameter follows:
857 %
858 % o image: the image.
859 %
860 */
IsImageGray(const Image * image)861 MagickExport MagickBooleanType IsImageGray(const Image *image)
862 {
863 assert(image != (Image *) NULL);
864 assert(image->signature == MagickCoreSignature);
865 if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
866 (image->type == GrayscaleAlphaType))
867 return(MagickTrue);
868 return(MagickFalse);
869 }
870
871 /*
872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873 % %
874 % %
875 % %
876 % I s I m a g e M o n o c h r o m e %
877 % %
878 % %
879 % %
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 %
882 % IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
883 %
884 % The format of the IsImageMonochrome method is:
885 %
886 % MagickBooleanType IsImageMonochrome(const Image *image)
887 %
888 % A description of each parameter follows:
889 %
890 % o image: the image.
891 %
892 */
IsImageMonochrome(const Image * image)893 MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
894 {
895 assert(image != (Image *) NULL);
896 assert(image->signature == MagickCoreSignature);
897 if (image->type == BilevelType)
898 return(MagickTrue);
899 return(MagickFalse);
900 }
901
902 /*
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904 % %
905 % %
906 % %
907 % I s I m a g e O p a q u e %
908 % %
909 % %
910 % %
911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912 %
913 % IsImageOpaque() returns MagickTrue if none of the pixels in the image have
914 % an alpha value other than OpaqueAlpha (QuantumRange).
915 %
916 % Will return true immediatally is alpha channel is not available.
917 %
918 % The format of the IsImageOpaque method is:
919 %
920 % MagickBooleanType IsImageOpaque(const Image *image,
921 % ExceptionInfo *exception)
922 %
923 % A description of each parameter follows:
924 %
925 % o image: the image.
926 %
927 % o exception: return any errors or warnings in this structure.
928 %
929 */
IsImageOpaque(const Image * image,ExceptionInfo * exception)930 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
931 ExceptionInfo *exception)
932 {
933 CacheView
934 *image_view;
935
936 register const Quantum
937 *p;
938
939 register ssize_t
940 x;
941
942 ssize_t
943 y;
944
945 /*
946 Determine if image is opaque.
947 */
948 assert(image != (Image *) NULL);
949 assert(image->signature == MagickCoreSignature);
950 if (image->debug != MagickFalse)
951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
952 if (image->alpha_trait == UndefinedPixelTrait)
953 return(MagickTrue);
954 image_view=AcquireVirtualCacheView(image,exception);
955 for (y=0; y < (ssize_t) image->rows; y++)
956 {
957 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
958 if (p == (const Quantum *) NULL)
959 break;
960 for (x=0; x < (ssize_t) image->columns; x++)
961 {
962 if (GetPixelAlpha(image,p) != OpaqueAlpha)
963 break;
964 p+=GetPixelChannels(image);
965 }
966 if (x < (ssize_t) image->columns)
967 break;
968 }
969 image_view=DestroyCacheView(image_view);
970 return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
971 }
972
973 /*
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 % %
976 % %
977 % %
978 % S e t I m a g e D e p t h %
979 % %
980 % %
981 % %
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983 %
984 % SetImageDepth() sets the depth of the image.
985 %
986 % The format of the SetImageDepth method is:
987 %
988 % MagickBooleanType SetImageDepth(Image *image,const size_t depth,
989 % ExceptionInfo *exception)
990 %
991 % A description of each parameter follows:
992 %
993 % o image: the image.
994 %
995 % o channel: the channel.
996 %
997 % o depth: the image depth.
998 %
999 % o exception: return any errors or warnings in this structure.
1000 %
1001 */
SetImageDepth(Image * image,const size_t depth,ExceptionInfo * exception)1002 MagickExport MagickBooleanType SetImageDepth(Image *image,
1003 const size_t depth,ExceptionInfo *exception)
1004 {
1005 CacheView
1006 *image_view;
1007
1008 MagickBooleanType
1009 status;
1010
1011 QuantumAny
1012 range;
1013
1014 ssize_t
1015 y;
1016
1017 assert(image != (Image *) NULL);
1018 if (image->debug != MagickFalse)
1019 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1020 assert(image->signature == MagickCoreSignature);
1021 if (depth >= MAGICKCORE_QUANTUM_DEPTH)
1022 {
1023 image->depth=depth;
1024 return(MagickTrue);
1025 }
1026 range=GetQuantumRange(depth);
1027 if (image->storage_class == PseudoClass)
1028 {
1029 register ssize_t
1030 i;
1031
1032 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1033 #pragma omp parallel for schedule(static,4) shared(status) \
1034 magick_threads(image,image,1,1)
1035 #endif
1036 for (i=0; i < (ssize_t) image->colors; i++)
1037 {
1038 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
1039 image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1040 ClampPixel(image->colormap[i].red),range),range);
1041 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
1042 image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1043 ClampPixel(image->colormap[i].green),range),range);
1044 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
1045 image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1046 ClampPixel(image->colormap[i].blue),range),range);
1047 if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
1048 image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
1049 ClampPixel(image->colormap[i].alpha),range),range);
1050 }
1051 }
1052 status=MagickTrue;
1053 image_view=AcquireAuthenticCacheView(image,exception);
1054 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1055 if (QuantumRange <= MaxMap)
1056 {
1057 Quantum
1058 *depth_map;
1059
1060 register ssize_t
1061 i;
1062
1063 /*
1064 Scale pixels to desired (optimized with depth map).
1065 */
1066 depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
1067 if (depth_map == (Quantum *) NULL)
1068 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1069 for (i=0; i <= (ssize_t) MaxMap; i++)
1070 depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
1071 range);
1072 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1073 #pragma omp parallel for schedule(static,4) shared(status) \
1074 magick_threads(image,image,image->rows,1)
1075 #endif
1076 for (y=0; y < (ssize_t) image->rows; y++)
1077 {
1078 register ssize_t
1079 x;
1080
1081 register Quantum
1082 *magick_restrict q;
1083
1084 if (status == MagickFalse)
1085 continue;
1086 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1087 exception);
1088 if (q == (Quantum *) NULL)
1089 {
1090 status=MagickFalse;
1091 continue;
1092 }
1093 for (x=0; x < (ssize_t) image->columns; x++)
1094 {
1095 register ssize_t
1096 i;
1097
1098 if (GetPixelReadMask(image,q) == 0)
1099 {
1100 q+=GetPixelChannels(image);
1101 continue;
1102 }
1103 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1104 {
1105 PixelChannel
1106 channel;
1107
1108 PixelTrait
1109 traits;
1110
1111 channel=GetPixelChannelChannel(image,i);
1112 traits=GetPixelChannelTraits(image,channel);
1113 if ((traits == UndefinedPixelTrait) ||
1114 (channel == IndexPixelChannel) ||
1115 (channel == ReadMaskPixelChannel))
1116 continue;
1117 q[i]=depth_map[ScaleQuantumToMap(q[i])];
1118 }
1119 q+=GetPixelChannels(image);
1120 }
1121 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1122 {
1123 status=MagickFalse;
1124 continue;
1125 }
1126 }
1127 image_view=DestroyCacheView(image_view);
1128 depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
1129 if (status != MagickFalse)
1130 image->depth=depth;
1131 return(status);
1132 }
1133 #endif
1134 /*
1135 Scale pixels to desired depth.
1136 */
1137 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1138 #pragma omp parallel for schedule(static,4) shared(status) \
1139 magick_threads(image,image,image->rows,1)
1140 #endif
1141 for (y=0; y < (ssize_t) image->rows; y++)
1142 {
1143 register ssize_t
1144 x;
1145
1146 register Quantum
1147 *magick_restrict q;
1148
1149 if (status == MagickFalse)
1150 continue;
1151 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
1152 if (q == (Quantum *) NULL)
1153 {
1154 status=MagickFalse;
1155 continue;
1156 }
1157 for (x=0; x < (ssize_t) image->columns; x++)
1158 {
1159 register ssize_t
1160 i;
1161
1162 if (GetPixelReadMask(image,q) == 0)
1163 {
1164 q+=GetPixelChannels(image);
1165 continue;
1166 }
1167 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1168 {
1169 PixelChannel
1170 channel;
1171
1172 PixelTrait
1173 traits;
1174
1175 channel=GetPixelChannelChannel(image,i);
1176 traits=GetPixelChannelTraits(image,channel);
1177 if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
1178 (channel == ReadMaskPixelChannel))
1179 continue;
1180 q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(q[i]),range),range);
1181 }
1182 q+=GetPixelChannels(image);
1183 }
1184 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
1185 {
1186 status=MagickFalse;
1187 continue;
1188 }
1189 }
1190 image_view=DestroyCacheView(image_view);
1191 if (status != MagickFalse)
1192 image->depth=depth;
1193 return(status);
1194 }
1195
1196 /*
1197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1198 % %
1199 % %
1200 % %
1201 % S e t I m a g e T y p e %
1202 % %
1203 % %
1204 % %
1205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1206 %
1207 % SetImageType() sets the type of image. Choose from these types:
1208 %
1209 % Bilevel Grayscale GrayscaleMatte
1210 % Palette PaletteMatte TrueColor
1211 % TrueColorMatte ColorSeparation ColorSeparationMatte
1212 % OptimizeType
1213 %
1214 % The format of the SetImageType method is:
1215 %
1216 % MagickBooleanType SetImageType(Image *image,const ImageType type,
1217 % ExceptionInfo *exception)
1218 %
1219 % A description of each parameter follows:
1220 %
1221 % o image: the image.
1222 %
1223 % o type: Image type.
1224 %
1225 % o exception: return any errors or warnings in this structure.
1226 %
1227 */
SetImageType(Image * image,const ImageType type,ExceptionInfo * exception)1228 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1229 ExceptionInfo *exception)
1230 {
1231 const char
1232 *artifact;
1233
1234 ImageInfo
1235 *image_info;
1236
1237 MagickBooleanType
1238 status;
1239
1240 QuantizeInfo
1241 *quantize_info;
1242
1243 assert(image != (Image *) NULL);
1244 if (image->debug != MagickFalse)
1245 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1246 assert(image->signature == MagickCoreSignature);
1247 status=MagickTrue;
1248 image_info=AcquireImageInfo();
1249 image_info->dither=image->dither;
1250 artifact=GetImageArtifact(image,"dither");
1251 if (artifact != (const char *) NULL)
1252 (void) SetImageOption(image_info,"dither",artifact);
1253 switch (type)
1254 {
1255 case BilevelType:
1256 {
1257 if (SetImageMonochrome(image,exception) == MagickFalse)
1258 {
1259 status=TransformImageColorspace(image,GRAYColorspace,exception);
1260 (void) NormalizeImage(image,exception);
1261 quantize_info=AcquireQuantizeInfo(image_info);
1262 quantize_info->number_colors=2;
1263 quantize_info->colorspace=GRAYColorspace;
1264 status=QuantizeImage(quantize_info,image,exception);
1265 quantize_info=DestroyQuantizeInfo(quantize_info);
1266 }
1267 image->colors=2;
1268 image->alpha_trait=UndefinedPixelTrait;
1269 break;
1270 }
1271 case GrayscaleType:
1272 {
1273 if (SetImageGray(image,exception) == MagickFalse)
1274 status=TransformImageColorspace(image,GRAYColorspace,exception);
1275 image->alpha_trait=UndefinedPixelTrait;
1276 break;
1277 }
1278 case GrayscaleAlphaType:
1279 {
1280 if (SetImageGray(image,exception) == MagickFalse)
1281 status=TransformImageColorspace(image,GRAYColorspace,exception);
1282 if (image->alpha_trait == UndefinedPixelTrait)
1283 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1284 break;
1285 }
1286 case PaletteType:
1287 {
1288 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1289 status=TransformImageColorspace(image,sRGBColorspace,exception);
1290 if ((image->storage_class == DirectClass) || (image->colors > 256))
1291 {
1292 quantize_info=AcquireQuantizeInfo(image_info);
1293 quantize_info->number_colors=256;
1294 status=QuantizeImage(quantize_info,image,exception);
1295 quantize_info=DestroyQuantizeInfo(quantize_info);
1296 }
1297 image->alpha_trait=UndefinedPixelTrait;
1298 break;
1299 }
1300 case PaletteBilevelAlphaType:
1301 {
1302 ChannelType
1303 channel_mask;
1304
1305 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1306 status=TransformImageColorspace(image,sRGBColorspace,exception);
1307 if (image->alpha_trait == UndefinedPixelTrait)
1308 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1309 channel_mask=SetImageChannelMask(image,AlphaChannel);
1310 (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1311 (void) SetImageChannelMask(image,channel_mask);
1312 quantize_info=AcquireQuantizeInfo(image_info);
1313 status=QuantizeImage(quantize_info,image,exception);
1314 quantize_info=DestroyQuantizeInfo(quantize_info);
1315 break;
1316 }
1317 case PaletteAlphaType:
1318 {
1319 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1320 status=TransformImageColorspace(image,sRGBColorspace,exception);
1321 if (image->alpha_trait == UndefinedPixelTrait)
1322 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1323 quantize_info=AcquireQuantizeInfo(image_info);
1324 quantize_info->colorspace=TransparentColorspace;
1325 status=QuantizeImage(quantize_info,image,exception);
1326 quantize_info=DestroyQuantizeInfo(quantize_info);
1327 break;
1328 }
1329 case TrueColorType:
1330 {
1331 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1332 status=TransformImageColorspace(image,sRGBColorspace,exception);
1333 if (image->storage_class != DirectClass)
1334 status=SetImageStorageClass(image,DirectClass,exception);
1335 image->alpha_trait=UndefinedPixelTrait;
1336 break;
1337 }
1338 case TrueColorAlphaType:
1339 {
1340 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1341 status=TransformImageColorspace(image,sRGBColorspace,exception);
1342 if (image->storage_class != DirectClass)
1343 status=SetImageStorageClass(image,DirectClass,exception);
1344 if (image->alpha_trait == UndefinedPixelTrait)
1345 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1346 break;
1347 }
1348 case ColorSeparationType:
1349 {
1350 if (image->colorspace != CMYKColorspace)
1351 {
1352 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1353 status=TransformImageColorspace(image,sRGBColorspace,exception);
1354 status=TransformImageColorspace(image,CMYKColorspace,exception);
1355 }
1356 if (image->storage_class != DirectClass)
1357 status=SetImageStorageClass(image,DirectClass,exception);
1358 image->alpha_trait=UndefinedPixelTrait;
1359 break;
1360 }
1361 case ColorSeparationAlphaType:
1362 {
1363 if (image->colorspace != CMYKColorspace)
1364 {
1365 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1366 status=TransformImageColorspace(image,sRGBColorspace,exception);
1367 status=TransformImageColorspace(image,CMYKColorspace,exception);
1368 }
1369 if (image->storage_class != DirectClass)
1370 status=SetImageStorageClass(image,DirectClass,exception);
1371 if (image->alpha_trait == UndefinedPixelTrait)
1372 status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1373 break;
1374 }
1375 case OptimizeType:
1376 case UndefinedType:
1377 break;
1378 }
1379 image_info=DestroyImageInfo(image_info);
1380 if (status == MagickFalse)
1381 return(status);
1382 image->type=type;
1383 return(MagickTrue);
1384 }
1385