]> granicus.if.org Git - imagemagick/blob - MagickCore/attribute.c
Fixed comment and return value.
[imagemagick] / MagickCore / attribute.c
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-2015 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 \f
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 \f
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 */
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     *p;
143
144   ssize_t
145     y;
146
147   assert(image != (Image *) NULL);
148   assert(image->signature == MagickSignature);
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   p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception);
158   if (p == (const Quantum *) NULL)
159     {
160       image_view=DestroyCacheView(image_view);
161       return(bounds);
162     }
163   GetPixelInfoPixel(image,p,&target[0]);
164   GetPixelInfo(image,&target[1]);
165   p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1,
166     exception);
167   if (p != (const Quantum *) NULL)
168     GetPixelInfoPixel(image,p,&target[1]);
169   GetPixelInfo(image,&target[2]);
170   p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1,
171     exception);
172   if (p != (const Quantum *) NULL)
173     GetPixelInfoPixel(image,p,&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       *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 \f
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 */
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 == MagickSignature);
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           *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       *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 \f
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 */
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 \f
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 potential type of image:
572 %
573 %        Bilevel         Grayscale        GrayscaleMatte
574 %        Palette         PaletteMatte     TrueColor
575 %        TrueColorMatte  ColorSeparation  ColorSeparationMatte
576 %
577 %  To ensure the image type matches its potential, use SetImageType():
578 %
579 %    (void) SetImageType(image,GetImageType(image));
580 %
581 %  The format of the GetImageType method is:
582 %
583 %      ImageType GetImageType(const Image *image,ExceptionInfo *exception)
584 %
585 %  A description of each parameter follows:
586 %
587 %    o image: the image.
588 %
589 %    o exception: return any errors or warnings in this structure.
590 %
591 */
592 MagickExport ImageType GetImageType(const Image *image,ExceptionInfo *exception)
593 {
594   assert(image != (Image *) NULL);
595   assert(image->signature == MagickSignature);
596   if (image->debug != MagickFalse)
597     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
598   if (image->colorspace == CMYKColorspace)
599     {
600       if (image->alpha_trait == UndefinedPixelTrait)
601         return(ColorSeparationType);
602       return(ColorSeparationAlphaType);
603     }
604   if (SetImageMonochrome((Image *) image,exception) != MagickFalse)
605     return(BilevelType);
606   if (SetImageGray((Image *) image,exception) != MagickFalse)
607     {
608       if (image->alpha_trait != UndefinedPixelTrait)
609         return(GrayscaleAlphaType);
610       return(GrayscaleType);
611     }
612   if (IsPaletteImage(image,exception) != MagickFalse)
613     {
614       if (image->alpha_trait != UndefinedPixelTrait)
615         return(PaletteAlphaType);
616       return(PaletteType);
617     }
618   if (image->alpha_trait != UndefinedPixelTrait)
619     return(TrueColorAlphaType);
620   return(TrueColorType);
621 }
622 \f
623 /*
624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625 %                                                                             %
626 %                                                                             %
627 %                                                                             %
628 %     I s I m a g e G r a y                                                   %
629 %                                                                             %
630 %                                                                             %
631 %                                                                             %
632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633 %
634 %  IsImageGray() returns MagickTrue if the type of the image is grayscale or
635 %  bi-level.
636 %
637 %  The format of the IsImageGray method is:
638 %
639 %      MagickBooleanType IsImageGray(const Image *image)
640 %
641 %  A description of each parameter follows:
642 %
643 %    o image: the image.
644 %
645 */
646 MagickExport MagickBooleanType IsImageGray(const Image *image)
647 {
648   assert(image != (Image *) NULL);
649   assert(image->signature == MagickSignature);
650   if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
651       (image->type == GrayscaleAlphaType))
652     return(MagickTrue);
653   return(MagickFalse);
654 }
655 \f
656 /*
657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 %                                                                             %
659 %                                                                             %
660 %                                                                             %
661 %   I s I m a g e M o n o c h r o m e                                         %
662 %                                                                             %
663 %                                                                             %
664 %                                                                             %
665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
666 %
667 %  IsImageMonochrome() returns MagickTrue if type of the image is bi-level.
668 %
669 %  The format of the IsImageMonochrome method is:
670 %
671 %      MagickBooleanType IsImageMonochrome(const Image *image)
672 %
673 %  A description of each parameter follows:
674 %
675 %    o image: the image.
676 %
677 */
678 MagickExport MagickBooleanType IsImageMonochrome(const Image *image)
679 {
680   assert(image != (Image *) NULL);
681   assert(image->signature == MagickSignature);
682   if (image->type == BilevelType)
683     return(MagickTrue);
684   return(MagickFalse);
685 }
686 \f
687 /*
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %                                                                             %
690 %                                                                             %
691 %                                                                             %
692 %     I s I m a g e O p a q u e                                               %
693 %                                                                             %
694 %                                                                             %
695 %                                                                             %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 %
698 %  IsImageOpaque() returns MagickTrue if none of the pixels in the image have
699 %  an alpha value other than OpaqueAlpha (QuantumRange).
700 %
701 %  Will return true immediatally is alpha channel is not available.
702 %
703 %  The format of the IsImageOpaque method is:
704 %
705 %      MagickBooleanType IsImageOpaque(const Image *image,
706 %        ExceptionInfo *exception)
707 %
708 %  A description of each parameter follows:
709 %
710 %    o image: the image.
711 %
712 %    o exception: return any errors or warnings in this structure.
713 %
714 */
715 MagickExport MagickBooleanType IsImageOpaque(const Image *image,
716   ExceptionInfo *exception)
717 {
718   CacheView
719     *image_view;
720
721   register const Quantum
722     *p;
723
724   register ssize_t
725     x;
726
727   ssize_t
728     y;
729
730   /*
731     Determine if image is opaque.
732   */
733   assert(image != (Image *) NULL);
734   assert(image->signature == MagickSignature);
735   if (image->debug != MagickFalse)
736     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
737   if (image->alpha_trait == UndefinedPixelTrait)
738     return(MagickTrue);
739   image_view=AcquireVirtualCacheView(image,exception);
740   for (y=0; y < (ssize_t) image->rows; y++)
741   {
742     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
743     if (p == (const Quantum *) NULL)
744       break;
745     for (x=0; x < (ssize_t) image->columns; x++)
746     {
747       if (GetPixelAlpha(image,p) != OpaqueAlpha)
748         break;
749       p+=GetPixelChannels(image);
750     }
751     if (x < (ssize_t) image->columns)
752       break;
753   }
754   image_view=DestroyCacheView(image_view);
755   return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
756 }
757 \f
758 /*
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 %                                                                             %
761 %                                                                             %
762 %                                                                             %
763 %   S e t I m a g e D e p t h                                                 %
764 %                                                                             %
765 %                                                                             %
766 %                                                                             %
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 %
769 %  SetImageDepth() sets the depth of the image.
770 %
771 %  The format of the SetImageDepth method is:
772 %
773 %      MagickBooleanType SetImageDepth(Image *image,const size_t depth,
774 %        ExceptionInfo *exception)
775 %
776 %  A description of each parameter follows:
777 %
778 %    o image: the image.
779 %
780 %    o channel: the channel.
781 %
782 %    o depth: the image depth.
783 %
784 %    o exception: return any errors or warnings in this structure.
785 %
786 */
787 MagickExport MagickBooleanType SetImageDepth(Image *image,
788   const size_t depth,ExceptionInfo *exception)
789 {
790   CacheView
791     *image_view;
792
793   MagickBooleanType
794     status;
795
796   QuantumAny
797     range;
798
799   ssize_t
800     y;
801
802   assert(image != (Image *) NULL);
803   if (image->debug != MagickFalse)
804     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
805   assert(image->signature == MagickSignature);
806   if (depth >= MAGICKCORE_QUANTUM_DEPTH)
807     {
808       image->depth=depth;
809       return(MagickTrue);
810     }
811   range=GetQuantumRange(depth);
812   if (image->storage_class == PseudoClass)
813     {
814       register ssize_t
815         i;
816
817 #if defined(MAGICKCORE_OPENMP_SUPPORT)
818       #pragma omp parallel for schedule(static,4) shared(status) \
819         magick_threads(image,image,1,1)
820 #endif
821       for (i=0; i < (ssize_t) image->colors; i++)
822       {
823         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
824           image->colormap[i].red=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
825             ClampPixel(image->colormap[i].red),range),range);
826         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
827           image->colormap[i].green=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
828             ClampPixel(image->colormap[i].green),range),range);
829         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
830           image->colormap[i].blue=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
831             ClampPixel(image->colormap[i].blue),range),range);
832         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
833           image->colormap[i].alpha=(double) ScaleAnyToQuantum(ScaleQuantumToAny(
834             ClampPixel(image->colormap[i].alpha),range),range);
835       }
836     }
837   status=MagickTrue;
838   image_view=AcquireAuthenticCacheView(image,exception);
839 #if !defined(MAGICKCORE_HDRI_SUPPORT)
840   if (QuantumRange <= MaxMap)
841     {
842       Quantum
843         *depth_map;
844
845       register ssize_t
846         i;
847
848       /*
849         Scale pixels to desired (optimized with depth map).
850       */
851       depth_map=(Quantum *) AcquireQuantumMemory(MaxMap+1,sizeof(*depth_map));
852       if (depth_map == (Quantum *) NULL)
853         ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
854       for (i=0; i <= (ssize_t) MaxMap; i++)
855         depth_map[i]=ScaleAnyToQuantum(ScaleQuantumToAny((Quantum) i,range),
856           range);
857 #if defined(MAGICKCORE_OPENMP_SUPPORT)
858       #pragma omp parallel for schedule(static,4) shared(status) \
859         magick_threads(image,image,image->rows,1)
860 #endif
861       for (y=0; y < (ssize_t) image->rows; y++)
862       {
863         register ssize_t
864           x;
865
866         register Quantum
867           *restrict q;
868
869         if (status == MagickFalse)
870           continue;
871         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
872           exception);
873         if (q == (Quantum *) NULL)
874           {
875             status=MagickFalse;
876             continue;
877           }
878         for (x=0; x < (ssize_t) image->columns; x++)
879         {
880           register ssize_t
881             i;
882
883           if (GetPixelReadMask(image,q) == 0)
884             {
885               q+=GetPixelChannels(image);
886               continue;
887             }
888           for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
889           {
890             PixelChannel
891               channel;
892
893             PixelTrait
894               traits;
895
896             channel=GetPixelChannelChannel(image,i);
897             traits=GetPixelChannelTraits(image,channel);
898             if ((traits == UndefinedPixelTrait) ||
899                 (channel == IndexPixelChannel) ||
900                 (channel == ReadMaskPixelChannel))
901               continue;
902             q[i]=depth_map[ScaleQuantumToMap(q[i])];
903           }
904           q+=GetPixelChannels(image);
905         }
906         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
907           {
908             status=MagickFalse;
909             continue;
910           }
911       }
912       image_view=DestroyCacheView(image_view);
913       depth_map=(Quantum *) RelinquishMagickMemory(depth_map);
914       if (status != MagickFalse)
915         image->depth=depth;
916       return(status);
917     }
918 #endif
919   /*
920     Scale pixels to desired depth.
921   */
922 #if defined(MAGICKCORE_OPENMP_SUPPORT)
923   #pragma omp parallel for schedule(static,4) shared(status) \
924     magick_threads(image,image,image->rows,1)
925 #endif
926   for (y=0; y < (ssize_t) image->rows; y++)
927   {
928     register ssize_t
929       x;
930
931     register Quantum
932       *restrict q;
933
934     if (status == MagickFalse)
935       continue;
936     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
937     if (q == (Quantum *) NULL)
938       {
939         status=MagickFalse;
940         continue;
941       }
942     for (x=0; x < (ssize_t) image->columns; x++)
943     {
944       register ssize_t
945         i;
946
947       if (GetPixelReadMask(image,q) == 0)
948         {
949           q+=GetPixelChannels(image);
950           continue;
951         }
952       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
953       {
954         PixelChannel
955           channel;
956
957         PixelTrait
958           traits;
959
960         channel=GetPixelChannelChannel(image,i);
961         traits=GetPixelChannelTraits(image,channel);
962         if ((traits == UndefinedPixelTrait) || (channel == IndexPixelChannel) ||
963             (channel == ReadMaskPixelChannel))
964           continue;
965         q[i]=ScaleAnyToQuantum(ScaleQuantumToAny(ClampPixel(q[i]),range),range);
966       }
967       q+=GetPixelChannels(image);
968     }
969     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
970       {
971         status=MagickFalse;
972         continue;
973       }
974   }
975   image_view=DestroyCacheView(image_view);
976   if (status != MagickFalse)
977     image->depth=depth;
978   return(status);
979 }
980 \f
981 /*
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983 %                                                                             %
984 %                                                                             %
985 %                                                                             %
986 %     S e t I m a g e G r a y                                                 %
987 %                                                                             %
988 %                                                                             %
989 %                                                                             %
990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 %
992 %  SetImageGray() returns MagickTrue if all the pixels in the image have the
993 %  same red, green, and blue intensities and changes the type of the image to
994 %  bi-level or grayscale.
995 %
996 %  The format of the SetImageGray method is:
997 %
998 %      MagickBooleanType SetImageGray(const Image *image,
999 %        ExceptionInfo *exception)
1000 %
1001 %  A description of each parameter follows:
1002 %
1003 %    o image: the image.
1004 %
1005 %    o exception: return any errors or warnings in this structure.
1006 %
1007 */
1008 MagickExport MagickBooleanType SetImageGray(Image *image,
1009   ExceptionInfo *exception)
1010 {
1011   CacheView
1012     *image_view;
1013
1014   ImageType
1015     type;
1016
1017   register const Quantum
1018     *p;
1019
1020   register ssize_t
1021     x;
1022
1023   ssize_t
1024     y;
1025
1026   assert(image != (Image *) NULL);
1027   assert(image->signature == MagickSignature);
1028   if (image->debug != MagickFalse)
1029     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1030   if (IsImageGray(image))
1031     return(MagickTrue);
1032   if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
1033       (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1034     return(MagickFalse);
1035   type=BilevelType;
1036   image_view=AcquireVirtualCacheView(image,exception);
1037   for (y=0; y < (ssize_t) image->rows; y++)
1038   {
1039     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1040     if (p == (const Quantum *) NULL)
1041       break;
1042     for (x=0; x < (ssize_t) image->columns; x++)
1043     {
1044       if (IsPixelGray(image,p) == MagickFalse)
1045         {
1046           type=UndefinedType;
1047           break;
1048         }
1049       if ((type == BilevelType) &&
1050           (IsPixelMonochrome(image,p) == MagickFalse))
1051         type=GrayscaleType;
1052       p+=GetPixelChannels(image);
1053     }
1054     if (type == UndefinedType)
1055       break;
1056   }
1057   image_view=DestroyCacheView(image_view);
1058   if (type == UndefinedType)
1059     return(MagickFalse);
1060   image->colorspace=GRAYColorspace;
1061   if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
1062     return(MagickFalse);
1063   image->type=type;
1064   if ((type == GrayscaleType) && (image->alpha_trait != UndefinedPixelTrait))
1065     image->type=GrayscaleAlphaType;
1066   return(MagickTrue);
1067 }
1068 \f
1069 /*
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071 %                                                                             %
1072 %                                                                             %
1073 %                                                                             %
1074 %   S e t I m a g e M o n o c h r o m e                                       %
1075 %                                                                             %
1076 %                                                                             %
1077 %                                                                             %
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 %
1080 %  SetImageMonochrome() returns MagickTrue if all the pixels in the image have
1081 %  the same red, green, and blue intensities and the intensity is either
1082 %  0 or QuantumRange and changes the type of the image to bi-level.
1083 %
1084 %  The format of the SetImageMonochrome method is:
1085 %
1086 %      MagickBooleanType SetImageMonochrome(const Image *image,
1087 %        ExceptionInfo *exception)
1088 %
1089 %  A description of each parameter follows:
1090 %
1091 %    o image: the image.
1092 %
1093 %    o exception: return any errors or warnings in this structure.
1094 %
1095 */
1096 MagickExport MagickBooleanType SetImageMonochrome(Image *image,
1097   ExceptionInfo *exception)
1098 {
1099   CacheView
1100     *image_view;
1101
1102   ImageType
1103     type;
1104
1105   register ssize_t
1106     x;
1107
1108   register const Quantum
1109     *p;
1110
1111   ssize_t
1112     y;
1113
1114   assert(image != (Image *) NULL);
1115   assert(image->signature == MagickSignature);
1116   if (image->debug != MagickFalse)
1117     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1118   if (image->type == BilevelType)
1119     return(MagickTrue);
1120   if ((IsGrayColorspace(image->colorspace) == MagickFalse) &&
1121       (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse))
1122     return(MagickFalse);
1123   type=BilevelType;
1124   image_view=AcquireVirtualCacheView(image,exception);
1125   for (y=0; y < (ssize_t) image->rows; y++)
1126   {
1127     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1128     if (p == (const Quantum *) NULL)
1129       break;
1130     for (x=0; x < (ssize_t) image->columns; x++)
1131     {
1132       if (IsPixelMonochrome(image,p) == MagickFalse)
1133         {
1134           type=UndefinedType;
1135           break;
1136         }
1137       p+=GetPixelChannels(image);
1138     }
1139     if (type == UndefinedType)
1140       break;
1141   }
1142   image_view=DestroyCacheView(image_view);
1143   if (type == UndefinedType)
1144     return(MagickFalse);
1145   image->colorspace=GRAYColorspace;
1146   if (SyncImagePixelCache((Image *) image,exception) == MagickFalse)
1147     return(MagickFalse);
1148   image->type=type;
1149   return(MagickTrue);
1150 }
1151 \f
1152 /*
1153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154 %                                                                             %
1155 %                                                                             %
1156 %                                                                             %
1157 %   S e t I m a g e T y p e                                                   %
1158 %                                                                             %
1159 %                                                                             %
1160 %                                                                             %
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1162 %
1163 %  SetImageType() sets the type of image.  Choose from these types:
1164 %
1165 %        Bilevel        Grayscale       GrayscaleMatte
1166 %        Palette        PaletteMatte    TrueColor
1167 %        TrueColorMatte ColorSeparation ColorSeparationMatte
1168 %        OptimizeType
1169 %
1170 %  The format of the SetImageType method is:
1171 %
1172 %      MagickBooleanType SetImageType(Image *image,const ImageType type,
1173 %        ExceptionInfo *exception)
1174 %
1175 %  A description of each parameter follows:
1176 %
1177 %    o image: the image.
1178 %
1179 %    o type: Image type.
1180 %
1181 %    o exception: return any errors or warnings in this structure.
1182 %
1183 */
1184 MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type,
1185   ExceptionInfo *exception)
1186 {
1187   const char
1188     *artifact;
1189
1190   ImageInfo
1191     *image_info;
1192
1193   MagickBooleanType
1194     status;
1195
1196   QuantizeInfo
1197     *quantize_info;
1198
1199   assert(image != (Image *) NULL);
1200   if (image->debug != MagickFalse)
1201     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1202   assert(image->signature == MagickSignature);
1203   status=MagickTrue;
1204   image_info=AcquireImageInfo();
1205   image_info->dither=image->dither;
1206   artifact=GetImageArtifact(image,"dither");
1207   if (artifact != (const char *) NULL)
1208     (void) SetImageOption(image_info,"dither",artifact);
1209   switch (type)
1210   {
1211     case BilevelType:
1212     {
1213       if (SetImageGray(image,exception) == MagickFalse)
1214         status=TransformImageColorspace(image,GRAYColorspace,exception);
1215       (void) NormalizeImage(image,exception);
1216       if (SetImageMonochrome(image,exception) == MagickFalse)
1217         {
1218           quantize_info=AcquireQuantizeInfo(image_info);
1219           quantize_info->number_colors=2;
1220           quantize_info->colorspace=GRAYColorspace;
1221           status=QuantizeImage(quantize_info,image,exception);
1222           quantize_info=DestroyQuantizeInfo(quantize_info);
1223         }
1224       image->colors=2;
1225       image->alpha_trait=UndefinedPixelTrait;
1226       break;
1227     }
1228     case GrayscaleType:
1229     {
1230       if (SetImageGray(image,exception) == MagickFalse)
1231         status=TransformImageColorspace(image,GRAYColorspace,exception);
1232       image->alpha_trait=UndefinedPixelTrait;
1233       break;
1234     }
1235     case GrayscaleAlphaType:
1236     {
1237       if (SetImageGray(image,exception) == MagickFalse)
1238         status=TransformImageColorspace(image,GRAYColorspace,exception);
1239       if (image->alpha_trait == UndefinedPixelTrait)
1240         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1241       break;
1242     }
1243     case PaletteType:
1244     {
1245       if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1246         status=TransformImageColorspace(image,sRGBColorspace,exception);
1247       if ((image->storage_class == DirectClass) || (image->colors > 256))
1248         {
1249           quantize_info=AcquireQuantizeInfo(image_info);
1250           quantize_info->number_colors=256;
1251           status=QuantizeImage(quantize_info,image,exception);
1252           quantize_info=DestroyQuantizeInfo(quantize_info);
1253         }
1254       image->alpha_trait=UndefinedPixelTrait;
1255       break;
1256     }
1257     case PaletteBilevelAlphaType:
1258     {
1259       ChannelType
1260         channel_mask;
1261
1262       if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1263         status=TransformImageColorspace(image,sRGBColorspace,exception);
1264       if (image->alpha_trait == UndefinedPixelTrait)
1265         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1266       channel_mask=SetImageChannelMask(image,AlphaChannel);
1267       (void) BilevelImage(image,(double) QuantumRange/2.0,exception);
1268       (void) SetImageChannelMask(image,channel_mask);
1269       quantize_info=AcquireQuantizeInfo(image_info);
1270       status=QuantizeImage(quantize_info,image,exception);
1271       quantize_info=DestroyQuantizeInfo(quantize_info);
1272       break;
1273     }
1274     case PaletteAlphaType:
1275     {
1276       if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1277         status=TransformImageColorspace(image,sRGBColorspace,exception);
1278       if (image->alpha_trait == UndefinedPixelTrait)
1279         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1280       quantize_info=AcquireQuantizeInfo(image_info);
1281       quantize_info->colorspace=TransparentColorspace;
1282       status=QuantizeImage(quantize_info,image,exception);
1283       quantize_info=DestroyQuantizeInfo(quantize_info);
1284       break;
1285     }
1286     case TrueColorType:
1287     {
1288       if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1289         status=TransformImageColorspace(image,sRGBColorspace,exception);
1290       if (image->storage_class != DirectClass)
1291         status=SetImageStorageClass(image,DirectClass,exception);
1292       image->alpha_trait=UndefinedPixelTrait;
1293       break;
1294     }
1295     case TrueColorAlphaType:
1296     {
1297       if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1298         status=TransformImageColorspace(image,sRGBColorspace,exception);
1299       if (image->storage_class != DirectClass)
1300         status=SetImageStorageClass(image,DirectClass,exception);
1301       if (image->alpha_trait == UndefinedPixelTrait)
1302         (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1303       break;
1304     }
1305     case ColorSeparationType:
1306     {
1307       if (image->colorspace != CMYKColorspace)
1308         {
1309           if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1310             status=TransformImageColorspace(image,sRGBColorspace,exception);
1311           status=TransformImageColorspace(image,CMYKColorspace,exception);
1312         }
1313       if (image->storage_class != DirectClass)
1314         status=SetImageStorageClass(image,DirectClass,exception);
1315       image->alpha_trait=UndefinedPixelTrait;
1316       break;
1317     }
1318     case ColorSeparationAlphaType:
1319     {
1320       if (image->colorspace != CMYKColorspace)
1321         {
1322           if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1323             status=TransformImageColorspace(image,sRGBColorspace,exception);
1324           status=TransformImageColorspace(image,CMYKColorspace,exception);
1325         }
1326       if (image->storage_class != DirectClass)
1327         status=SetImageStorageClass(image,DirectClass,exception);
1328       if (image->alpha_trait == UndefinedPixelTrait)
1329         status=SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1330       break;
1331     }
1332     case OptimizeType:
1333     case UndefinedType:
1334       break;
1335   }
1336   image_info=DestroyImageInfo(image_info);
1337   if (status == MagickFalse)
1338     return(status);
1339   image->type=type;
1340   return(MagickTrue);
1341 }