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