1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % IIIII M M AAA GGGG EEEEE % 7 % I MM MM A A G E % 8 % I M M M AAAAA G GG EEE % 9 % I M M A A G G E % 10 % IIIII M M A A GGGG EEEEE % 11 % % 12 % % 13 % MagickCore Image Methods % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 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/animate.h" 46 #include "MagickCore/artifact.h" 47 #include "MagickCore/attribute.h" 48 #include "MagickCore/blob.h" 49 #include "MagickCore/blob-private.h" 50 #include "MagickCore/cache.h" 51 #include "MagickCore/cache-private.h" 52 #include "MagickCore/cache-view.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/colorspace.h" 58 #include "MagickCore/colorspace-private.h" 59 #include "MagickCore/composite.h" 60 #include "MagickCore/composite-private.h" 61 #include "MagickCore/compress.h" 62 #include "MagickCore/constitute.h" 63 #include "MagickCore/delegate.h" 64 #include "MagickCore/display.h" 65 #include "MagickCore/draw.h" 66 #include "MagickCore/enhance.h" 67 #include "MagickCore/exception.h" 68 #include "MagickCore/exception-private.h" 69 #include "MagickCore/gem.h" 70 #include "MagickCore/geometry.h" 71 #include "MagickCore/histogram.h" 72 #include "MagickCore/image-private.h" 73 #include "MagickCore/list.h" 74 #include "MagickCore/magic.h" 75 #include "MagickCore/magick.h" 76 #include "MagickCore/magick-private.h" 77 #include "MagickCore/memory_.h" 78 #include "MagickCore/module.h" 79 #include "MagickCore/monitor.h" 80 #include "MagickCore/monitor-private.h" 81 #include "MagickCore/option.h" 82 #include "MagickCore/paint.h" 83 #include "MagickCore/pixel-accessor.h" 84 #include "MagickCore/profile.h" 85 #include "MagickCore/property.h" 86 #include "MagickCore/quantize.h" 87 #include "MagickCore/random_.h" 88 #include "MagickCore/resource_.h" 89 #include "MagickCore/segment.h" 90 #include "MagickCore/semaphore.h" 91 #include "MagickCore/signature-private.h" 92 #include "MagickCore/statistic.h" 93 #include "MagickCore/string_.h" 94 #include "MagickCore/string-private.h" 95 #include "MagickCore/thread-private.h" 96 #include "MagickCore/threshold.h" 97 #include "MagickCore/timer.h" 98 #include "MagickCore/token.h" 99 #include "MagickCore/utility.h" 100 #include "MagickCore/utility-private.h" 101 #include "MagickCore/version.h" 102 #include "MagickCore/xwindow-private.h" 103 104 /* 106 Constant declaration. 107 */ 108 const char 109 AlphaColor[] = "#bdbdbd", /* gray */ 110 BackgroundColor[] = "#ffffff", /* white */ 111 BorderColor[] = "#dfdfdf", /* gray */ 112 DefaultTileFrame[] = "15x15+3+3", 113 DefaultTileGeometry[] = "120x120+4+3>", 114 DefaultTileLabel[] = "%f\n%G\n%b", 115 ForegroundColor[] = "#000", /* black */ 116 LoadImageTag[] = "Load/Image", 117 LoadImagesTag[] = "Load/Images", 118 PSDensityGeometry[] = "72.0x72.0", 119 PSPageGeometry[] = "612x792", 120 SaveImageTag[] = "Save/Image", 121 SaveImagesTag[] = "Save/Images", 122 TransparentColor[] = "#00000000"; /* transparent black */ 123 124 const double 125 DefaultResolution = 72.0; 126 127 /* 129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 130 % % 131 % % 132 % % 133 % A c q u i r e I m a g e % 134 % % 135 % % 136 % % 137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 138 % 139 % AcquireImage() returns a pointer to an image structure initialized to 140 % default values. 141 % 142 % The format of the AcquireImage method is: 143 % 144 % Image *AcquireImage(const ImageInfo *image_info,ExceptionInfo *exception) 145 % 146 % A description of each parameter follows: 147 % 148 % o image_info: Many of the image default values are set from this 149 % structure. For example, filename, compression, depth, background color, 150 % and others. 151 % 152 % o exception: return any errors or warnings in this structure. 153 % 154 */ 155 MagickExport Image *AcquireImage(const ImageInfo *image_info, 156 ExceptionInfo *exception) 157 { 158 const char 159 *option; 160 161 Image 162 *image; 163 164 MagickStatusType 165 flags; 166 167 /* 168 Allocate image structure. 169 */ 170 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 171 image=(Image *) AcquireMagickMemory(sizeof(*image)); 172 if (image == (Image *) NULL) 173 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 174 (void) ResetMagickMemory(image,0,sizeof(*image)); 175 /* 176 Initialize Image structure. 177 */ 178 (void) CopyMagickString(image->magick,"MIFF",MagickPathExtent); 179 image->storage_class=DirectClass; 180 image->depth=MAGICKCORE_QUANTUM_DEPTH; 181 image->colorspace=sRGBColorspace; 182 image->rendering_intent=PerceptualIntent; 183 image->gamma=1.000f/2.200f; 184 image->chromaticity.red_primary.x=0.6400f; 185 image->chromaticity.red_primary.y=0.3300f; 186 image->chromaticity.red_primary.z=0.0300f; 187 image->chromaticity.green_primary.x=0.3000f; 188 image->chromaticity.green_primary.y=0.6000f; 189 image->chromaticity.green_primary.z=0.1000f; 190 image->chromaticity.blue_primary.x=0.1500f; 191 image->chromaticity.blue_primary.y=0.0600f; 192 image->chromaticity.blue_primary.z=0.7900f; 193 image->chromaticity.white_point.x=0.3127f; 194 image->chromaticity.white_point.y=0.3290f; 195 image->chromaticity.white_point.z=0.3583f; 196 image->interlace=NoInterlace; 197 image->ticks_per_second=UndefinedTicksPerSecond; 198 image->compose=OverCompositeOp; 199 (void) QueryColorCompliance(AlphaColor,AllCompliance,&image->alpha_color, 200 exception); 201 (void) QueryColorCompliance(BackgroundColor,AllCompliance, 202 &image->background_color,exception); 203 (void) QueryColorCompliance(BorderColor,AllCompliance,&image->border_color, 204 exception); 205 (void) QueryColorCompliance(TransparentColor,AllCompliance, 206 &image->transparent_color,exception); 207 GetTimerInfo(&image->timer); 208 image->cache=AcquirePixelCache(0); 209 image->channel_mask=DefaultChannels; 210 image->channel_map=AcquirePixelChannelMap(); 211 image->blob=CloneBlobInfo((BlobInfo *) NULL); 212 image->timestamp=time((time_t *) NULL); 213 image->debug=IsEventLogging(); 214 image->reference_count=1; 215 image->semaphore=AcquireSemaphoreInfo(); 216 image->signature=MagickCoreSignature; 217 if (image_info == (ImageInfo *) NULL) 218 return(image); 219 /* 220 Transfer image info. 221 */ 222 SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue : 223 MagickFalse); 224 (void) CopyMagickString(image->filename,image_info->filename, 225 MagickPathExtent); 226 (void) CopyMagickString(image->magick_filename,image_info->filename, 227 MagickPathExtent); 228 (void) CopyMagickString(image->magick,image_info->magick,MagickPathExtent); 229 if (image_info->size != (char *) NULL) 230 { 231 (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info); 232 image->columns=image->extract_info.width; 233 image->rows=image->extract_info.height; 234 image->offset=image->extract_info.x; 235 image->extract_info.x=0; 236 image->extract_info.y=0; 237 } 238 if (image_info->extract != (char *) NULL) 239 { 240 RectangleInfo 241 geometry; 242 243 flags=ParseAbsoluteGeometry(image_info->extract,&geometry); 244 if (((flags & XValue) != 0) || ((flags & YValue) != 0)) 245 { 246 image->extract_info=geometry; 247 Swap(image->columns,image->extract_info.width); 248 Swap(image->rows,image->extract_info.height); 249 } 250 } 251 image->compression=image_info->compression; 252 image->quality=image_info->quality; 253 image->endian=image_info->endian; 254 image->interlace=image_info->interlace; 255 image->units=image_info->units; 256 if (image_info->density != (char *) NULL) 257 { 258 GeometryInfo 259 geometry_info; 260 261 flags=ParseGeometry(image_info->density,&geometry_info); 262 image->resolution.x=geometry_info.rho; 263 image->resolution.y=geometry_info.sigma; 264 if ((flags & SigmaValue) == 0) 265 image->resolution.y=image->resolution.x; 266 } 267 if (image_info->page != (char *) NULL) 268 { 269 char 270 *geometry; 271 272 image->page=image->extract_info; 273 geometry=GetPageGeometry(image_info->page); 274 (void) ParseAbsoluteGeometry(geometry,&image->page); 275 geometry=DestroyString(geometry); 276 } 277 if (image_info->depth != 0) 278 image->depth=image_info->depth; 279 image->dither=image_info->dither; 280 image->alpha_color=image_info->alpha_color; 281 image->background_color=image_info->background_color; 282 image->border_color=image_info->border_color; 283 image->transparent_color=image_info->transparent_color; 284 image->ping=image_info->ping; 285 image->progress_monitor=image_info->progress_monitor; 286 image->client_data=image_info->client_data; 287 if (image_info->cache != (void *) NULL) 288 ClonePixelCacheMethods(image->cache,image_info->cache); 289 /* 290 Set all global options that map to per-image settings. 291 */ 292 (void) SyncImageSettings(image_info,image,exception); 293 /* 294 Global options that are only set for new images. 295 */ 296 option=GetImageOption(image_info,"delay"); 297 if (option != (const char *) NULL) 298 { 299 GeometryInfo 300 geometry_info; 301 302 flags=ParseGeometry(option,&geometry_info); 303 if ((flags & GreaterValue) != 0) 304 { 305 if (image->delay > (size_t) floor(geometry_info.rho+0.5)) 306 image->delay=(size_t) floor(geometry_info.rho+0.5); 307 } 308 else 309 if ((flags & LessValue) != 0) 310 { 311 if (image->delay < (size_t) floor(geometry_info.rho+0.5)) 312 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5); 313 } 314 else 315 image->delay=(size_t) floor(geometry_info.rho+0.5); 316 if ((flags & SigmaValue) != 0) 317 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5); 318 } 319 option=GetImageOption(image_info,"dispose"); 320 if (option != (const char *) NULL) 321 image->dispose=(DisposeType) ParseCommandOption(MagickDisposeOptions, 322 MagickFalse,option); 323 return(image); 324 } 325 326 /* 328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 329 % % 330 % % 331 % % 332 % A c q u i r e I m a g e I n f o % 333 % % 334 % % 335 % % 336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 337 % 338 % AcquireImageInfo() allocates the ImageInfo structure. 339 % 340 % The format of the AcquireImageInfo method is: 341 % 342 % ImageInfo *AcquireImageInfo(void) 343 % 344 */ 345 MagickExport ImageInfo *AcquireImageInfo(void) 346 { 347 ImageInfo 348 *image_info; 349 350 image_info=(ImageInfo *) AcquireMagickMemory(sizeof(*image_info)); 351 if (image_info == (ImageInfo *) NULL) 352 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 353 GetImageInfo(image_info); 354 return(image_info); 355 } 356 357 /* 359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 360 % % 361 % % 362 % % 363 % A c q u i r e N e x t I m a g e % 364 % % 365 % % 366 % % 367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 368 % 369 % AcquireNextImage() initializes the next image in a sequence to 370 % default values. The next member of image points to the newly allocated 371 % image. If there is a memory shortage, next is assigned NULL. 372 % 373 % The format of the AcquireNextImage method is: 374 % 375 % void AcquireNextImage(const ImageInfo *image_info,Image *image, 376 % ExceptionInfo *exception) 377 % 378 % A description of each parameter follows: 379 % 380 % o image_info: Many of the image default values are set from this 381 % structure. For example, filename, compression, depth, background color, 382 % and others. 383 % 384 % o image: the image. 385 % 386 % o exception: return any errors or warnings in this structure. 387 % 388 */ 389 MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image, 390 ExceptionInfo *exception) 391 { 392 /* 393 Allocate image structure. 394 */ 395 assert(image != (Image *) NULL); 396 assert(image->signature == MagickCoreSignature); 397 if (image->debug != MagickFalse) 398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 399 image->next=AcquireImage(image_info,exception); 400 if (GetNextImageInList(image) == (Image *) NULL) 401 return; 402 (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename, 403 MagickPathExtent); 404 if (image_info != (ImageInfo *) NULL) 405 (void) CopyMagickString(GetNextImageInList(image)->filename, 406 image_info->filename,MagickPathExtent); 407 DestroyBlob(GetNextImageInList(image)); 408 image->next->blob=ReferenceBlob(image->blob); 409 image->next->endian=image->endian; 410 image->next->scene=image->scene+1; 411 image->next->previous=image; 412 } 413 414 /* 416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 417 % % 418 % % 419 % % 420 % A p p e n d I m a g e s % 421 % % 422 % % 423 % % 424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 425 % 426 % AppendImages() takes all images from the current image pointer to the end 427 % of the image list and appends them to each other top-to-bottom if the 428 % stack parameter is true, otherwise left-to-right. 429 % 430 % The current gravity setting effects how the image is justified in the 431 % final image. 432 % 433 % The format of the AppendImages method is: 434 % 435 % Image *AppendImages(const Image *images,const MagickBooleanType stack, 436 % ExceptionInfo *exception) 437 % 438 % A description of each parameter follows: 439 % 440 % o images: the image sequence. 441 % 442 % o stack: A value other than 0 stacks the images top-to-bottom. 443 % 444 % o exception: return any errors or warnings in this structure. 445 % 446 */ 447 MagickExport Image *AppendImages(const Image *images, 448 const MagickBooleanType stack,ExceptionInfo *exception) 449 { 450 #define AppendImageTag "Append/Image" 451 452 CacheView 453 *append_view; 454 455 Image 456 *append_image; 457 458 MagickBooleanType 459 status; 460 461 MagickOffsetType 462 n; 463 464 PixelTrait 465 alpha_trait; 466 467 RectangleInfo 468 geometry; 469 470 register const Image 471 *next; 472 473 size_t 474 depth, 475 height, 476 number_images, 477 width; 478 479 ssize_t 480 x_offset, 481 y, 482 y_offset; 483 484 /* 485 Compute maximum area of appended area. 486 */ 487 assert(images != (Image *) NULL); 488 assert(images->signature == MagickCoreSignature); 489 if (images->debug != MagickFalse) 490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 491 assert(exception != (ExceptionInfo *) NULL); 492 assert(exception->signature == MagickCoreSignature); 493 alpha_trait=images->alpha_trait; 494 number_images=1; 495 width=images->columns; 496 height=images->rows; 497 depth=images->depth; 498 next=GetNextImageInList(images); 499 for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) 500 { 501 if (next->depth > depth) 502 depth=next->depth; 503 if (next->alpha_trait != UndefinedPixelTrait) 504 alpha_trait=BlendPixelTrait; 505 number_images++; 506 if (stack != MagickFalse) 507 { 508 if (next->columns > width) 509 width=next->columns; 510 height+=next->rows; 511 continue; 512 } 513 width+=next->columns; 514 if (next->rows > height) 515 height=next->rows; 516 } 517 /* 518 Append images. 519 */ 520 append_image=CloneImage(images,width,height,MagickTrue,exception); 521 if (append_image == (Image *) NULL) 522 return((Image *) NULL); 523 if (SetImageStorageClass(append_image,DirectClass,exception) == MagickFalse) 524 { 525 append_image=DestroyImage(append_image); 526 return((Image *) NULL); 527 } 528 append_image->depth=depth; 529 append_image->alpha_trait=alpha_trait; 530 (void) SetImageBackgroundColor(append_image,exception); 531 status=MagickTrue; 532 x_offset=0; 533 y_offset=0; 534 next=images; 535 append_view=AcquireAuthenticCacheView(append_image,exception); 536 for (n=0; n < (MagickOffsetType) number_images; n++) 537 { 538 CacheView 539 *image_view; 540 541 MagickBooleanType 542 proceed; 543 544 SetGeometry(append_image,&geometry); 545 GravityAdjustGeometry(next->columns,next->rows,next->gravity,&geometry); 546 if (stack != MagickFalse) 547 x_offset-=geometry.x; 548 else 549 y_offset-=geometry.y; 550 image_view=AcquireVirtualCacheView(next,exception); 551 #if defined(MAGICKCORE_OPENMP_SUPPORT) 552 #pragma omp parallel for schedule(static,4) shared(status) \ 553 magick_threads(next,next,next->rows,1) 554 #endif 555 for (y=0; y < (ssize_t) next->rows; y++) 556 { 557 MagickBooleanType 558 sync; 559 560 PixelInfo 561 pixel; 562 563 register const Quantum 564 *magick_restrict p; 565 566 register Quantum 567 *magick_restrict q; 568 569 register ssize_t 570 x; 571 572 if (status == MagickFalse) 573 continue; 574 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); 575 q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset, 576 next->columns,1,exception); 577 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 578 { 579 status=MagickFalse; 580 continue; 581 } 582 GetPixelInfo(next,&pixel); 583 for (x=0; x < (ssize_t) next->columns; x++) 584 { 585 if (GetPixelReadMask(next,p) == 0) 586 { 587 SetPixelBackgoundColor(append_image,q); 588 p+=GetPixelChannels(next); 589 q+=GetPixelChannels(append_image); 590 continue; 591 } 592 GetPixelInfoPixel(next,p,&pixel); 593 SetPixelViaPixelInfo(append_image,&pixel,q); 594 p+=GetPixelChannels(next); 595 q+=GetPixelChannels(append_image); 596 } 597 sync=SyncCacheViewAuthenticPixels(append_view,exception); 598 if (sync == MagickFalse) 599 status=MagickFalse; 600 } 601 image_view=DestroyCacheView(image_view); 602 if (stack == MagickFalse) 603 { 604 x_offset+=(ssize_t) next->columns; 605 y_offset=0; 606 } 607 else 608 { 609 x_offset=0; 610 y_offset+=(ssize_t) next->rows; 611 } 612 proceed=SetImageProgress(append_image,AppendImageTag,n,number_images); 613 if (proceed == MagickFalse) 614 break; 615 next=GetNextImageInList(next); 616 } 617 append_view=DestroyCacheView(append_view); 618 if (status == MagickFalse) 619 append_image=DestroyImage(append_image); 620 return(append_image); 621 } 622 623 /* 625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 626 % % 627 % % 628 % % 629 % C a t c h I m a g e E x c e p t i o n % 630 % % 631 % % 632 % % 633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 634 % 635 % CatchImageException() returns if no exceptions are found in the image 636 % sequence, otherwise it determines the most severe exception and reports 637 % it as a warning or error depending on the severity. 638 % 639 % The format of the CatchImageException method is: 640 % 641 % ExceptionType CatchImageException(Image *image) 642 % 643 % A description of each parameter follows: 644 % 645 % o image: An image sequence. 646 % 647 */ 648 MagickExport ExceptionType CatchImageException(Image *image) 649 { 650 ExceptionInfo 651 *exception; 652 653 ExceptionType 654 severity; 655 656 assert(image != (const Image *) NULL); 657 assert(image->signature == MagickCoreSignature); 658 if (image->debug != MagickFalse) 659 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 660 exception=AcquireExceptionInfo(); 661 CatchException(exception); 662 severity=exception->severity; 663 exception=DestroyExceptionInfo(exception); 664 return(severity); 665 } 666 667 /* 669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 670 % % 671 % % 672 % % 673 % C l i p I m a g e P a t h % 674 % % 675 % % 676 % % 677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 678 % 679 % ClipImagePath() sets the image clip mask based any clipping path information 680 % if it exists. 681 % 682 % The format of the ClipImagePath method is: 683 % 684 % MagickBooleanType ClipImagePath(Image *image,const char *pathname, 685 % const MagickBooleanType inside,ExceptionInfo *exception) 686 % 687 % A description of each parameter follows: 688 % 689 % o image: the image. 690 % 691 % o pathname: name of clipping path resource. If name is preceded by #, use 692 % clipping path numbered by name. 693 % 694 % o inside: if non-zero, later operations take effect inside clipping path. 695 % Otherwise later operations take effect outside clipping path. 696 % 697 % o exception: return any errors or warnings in this structure. 698 % 699 */ 700 701 MagickExport MagickBooleanType ClipImage(Image *image,ExceptionInfo *exception) 702 { 703 return(ClipImagePath(image,"#1",MagickTrue,exception)); 704 } 705 706 MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname, 707 const MagickBooleanType inside,ExceptionInfo *exception) 708 { 709 #define ClipImagePathTag "ClipPath/Image" 710 711 char 712 *property; 713 714 const char 715 *value; 716 717 Image 718 *clip_mask; 719 720 ImageInfo 721 *image_info; 722 723 assert(image != (const Image *) NULL); 724 assert(image->signature == MagickCoreSignature); 725 if (image->debug != MagickFalse) 726 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 727 assert(pathname != NULL); 728 property=AcquireString(pathname); 729 (void) FormatLocaleString(property,MagickPathExtent,"8BIM:1999,2998:%s", 730 pathname); 731 value=GetImageProperty(image,property,exception); 732 property=DestroyString(property); 733 if (value == (const char *) NULL) 734 { 735 ThrowFileException(exception,OptionError,"NoClipPathDefined", 736 image->filename); 737 return(MagickFalse); 738 } 739 image_info=AcquireImageInfo(); 740 (void) CopyMagickString(image_info->filename,image->filename, 741 MagickPathExtent); 742 (void) ConcatenateMagickString(image_info->filename,pathname, 743 MagickPathExtent); 744 clip_mask=BlobToImage(image_info,value,strlen(value),exception); 745 image_info=DestroyImageInfo(image_info); 746 if (clip_mask == (Image *) NULL) 747 return(MagickFalse); 748 if (clip_mask->storage_class == PseudoClass) 749 { 750 (void) SyncImage(clip_mask,exception); 751 if (SetImageStorageClass(clip_mask,DirectClass,exception) == MagickFalse) 752 return(MagickFalse); 753 } 754 if (inside == MagickFalse) 755 (void) NegateImage(clip_mask,MagickFalse,exception); 756 (void) FormatLocaleString(clip_mask->magick_filename,MagickPathExtent, 757 "8BIM:1999,2998:%s\nPS",pathname); 758 (void) SetImageMask(image,ReadPixelMask,clip_mask,exception); 759 clip_mask=DestroyImage(clip_mask); 760 return(MagickTrue); 761 } 762 763 /* 765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 766 % % 767 % % 768 % % 769 % C l o n e I m a g e % 770 % % 771 % % 772 % % 773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 774 % 775 % CloneImage() copies an image and returns the copy as a new image object. 776 % 777 % If the specified columns and rows is 0, an exact copy of the image is 778 % returned, otherwise the pixel data is undefined and must be initialized 779 % with the QueueAuthenticPixels() and SyncAuthenticPixels() methods. On 780 % failure, a NULL image is returned and exception describes the reason for the 781 % failure. 782 % 783 % The format of the CloneImage method is: 784 % 785 % Image *CloneImage(const Image *image,const size_t columns, 786 % const size_t rows,const MagickBooleanType orphan, 787 % ExceptionInfo *exception) 788 % 789 % A description of each parameter follows: 790 % 791 % o image: the image. 792 % 793 % o columns: the number of columns in the cloned image. 794 % 795 % o rows: the number of rows in the cloned image. 796 % 797 % o detach: With a value other than 0, the cloned image is detached from 798 % its parent I/O stream. 799 % 800 % o exception: return any errors or warnings in this structure. 801 % 802 */ 803 MagickExport Image *CloneImage(const Image *image,const size_t columns, 804 const size_t rows,const MagickBooleanType detach,ExceptionInfo *exception) 805 { 806 Image 807 *clone_image; 808 809 double 810 scale; 811 812 size_t 813 length; 814 815 /* 816 Clone the image. 817 */ 818 assert(image != (const Image *) NULL); 819 assert(image->signature == MagickCoreSignature); 820 if (image->debug != MagickFalse) 821 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 822 assert(exception != (ExceptionInfo *) NULL); 823 assert(exception->signature == MagickCoreSignature); 824 if ((image->columns == 0) || (image->rows == 0)) 825 { 826 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, 827 "NegativeOrZeroImageSize","`%s'",image->filename); 828 return((Image *) NULL); 829 } 830 clone_image=(Image *) AcquireMagickMemory(sizeof(*clone_image)); 831 if (clone_image == (Image *) NULL) 832 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 833 (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image)); 834 clone_image->signature=MagickCoreSignature; 835 clone_image->storage_class=image->storage_class; 836 clone_image->number_channels=image->number_channels; 837 clone_image->number_meta_channels=image->number_meta_channels; 838 clone_image->metacontent_extent=image->metacontent_extent; 839 clone_image->colorspace=image->colorspace; 840 clone_image->read_mask=image->read_mask; 841 clone_image->write_mask=image->write_mask; 842 clone_image->alpha_trait=image->alpha_trait; 843 clone_image->columns=image->columns; 844 clone_image->rows=image->rows; 845 clone_image->dither=image->dither; 846 if (image->colormap != (PixelInfo *) NULL) 847 { 848 /* 849 Allocate and copy the image colormap. 850 */ 851 clone_image->colors=image->colors; 852 length=(size_t) image->colors; 853 clone_image->colormap=(PixelInfo *) AcquireQuantumMemory(length, 854 sizeof(*clone_image->colormap)); 855 if (clone_image->colormap == (PixelInfo *) NULL) 856 { 857 clone_image=DestroyImage(clone_image); 858 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 859 } 860 (void) CopyMagickMemory(clone_image->colormap,image->colormap,length* 861 sizeof(*clone_image->colormap)); 862 } 863 clone_image->image_info=CloneImageInfo(image->image_info); 864 (void) CloneImageProfiles(clone_image,image); 865 (void) CloneImageProperties(clone_image,image); 866 (void) CloneImageArtifacts(clone_image,image); 867 GetTimerInfo(&clone_image->timer); 868 if (image->ascii85 != (void *) NULL) 869 Ascii85Initialize(clone_image); 870 clone_image->magick_columns=image->magick_columns; 871 clone_image->magick_rows=image->magick_rows; 872 clone_image->type=image->type; 873 clone_image->channel_mask=image->channel_mask; 874 clone_image->channel_map=ClonePixelChannelMap(image->channel_map); 875 (void) CopyMagickString(clone_image->magick_filename,image->magick_filename, 876 MagickPathExtent); 877 (void) CopyMagickString(clone_image->magick,image->magick,MagickPathExtent); 878 (void) CopyMagickString(clone_image->filename,image->filename, 879 MagickPathExtent); 880 clone_image->progress_monitor=image->progress_monitor; 881 clone_image->client_data=image->client_data; 882 clone_image->reference_count=1; 883 clone_image->next=image->next; 884 clone_image->previous=image->previous; 885 clone_image->list=NewImageList(); 886 if (detach == MagickFalse) 887 clone_image->blob=ReferenceBlob(image->blob); 888 else 889 { 890 clone_image->next=NewImageList(); 891 clone_image->previous=NewImageList(); 892 clone_image->blob=CloneBlobInfo((BlobInfo *) NULL); 893 } 894 clone_image->ping=image->ping; 895 clone_image->debug=IsEventLogging(); 896 clone_image->semaphore=AcquireSemaphoreInfo(); 897 if ((columns == 0) || (rows == 0)) 898 { 899 if (image->montage != (char *) NULL) 900 (void) CloneString(&clone_image->montage,image->montage); 901 if (image->directory != (char *) NULL) 902 (void) CloneString(&clone_image->directory,image->directory); 903 clone_image->cache=ReferencePixelCache(image->cache); 904 return(clone_image); 905 } 906 scale=1.0; 907 if (image->columns != 0) 908 scale=(double) columns/(double) image->columns; 909 clone_image->page.width=(size_t) floor(scale*image->page.width+0.5); 910 clone_image->page.x=(ssize_t) ceil(scale*image->page.x-0.5); 911 clone_image->tile_offset.x=(ssize_t) ceil(scale*image->tile_offset.x-0.5); 912 scale=1.0; 913 if (image->rows != 0) 914 scale=(double) rows/(double) image->rows; 915 clone_image->page.height=(size_t) floor(scale*image->page.height+0.5); 916 clone_image->page.y=(ssize_t) ceil(scale*image->page.y-0.5); 917 clone_image->tile_offset.y=(ssize_t) ceil(scale*image->tile_offset.y-0.5); 918 clone_image->cache=ClonePixelCache(image->cache); 919 if (SetImageExtent(clone_image,columns,rows,exception) == MagickFalse) 920 clone_image=DestroyImage(clone_image); 921 return(clone_image); 922 } 923 924 /* 926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 927 % % 928 % % 929 % % 930 % C l o n e I m a g e I n f o % 931 % % 932 % % 933 % % 934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 935 % 936 % CloneImageInfo() makes a copy of the given image info structure. If 937 % NULL is specified, a new image info structure is created initialized to 938 % default values. 939 % 940 % The format of the CloneImageInfo method is: 941 % 942 % ImageInfo *CloneImageInfo(const ImageInfo *image_info) 943 % 944 % A description of each parameter follows: 945 % 946 % o image_info: the image info. 947 % 948 */ 949 MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info) 950 { 951 ImageInfo 952 *clone_info; 953 954 clone_info=AcquireImageInfo(); 955 if (image_info == (ImageInfo *) NULL) 956 return(clone_info); 957 clone_info->compression=image_info->compression; 958 clone_info->temporary=image_info->temporary; 959 clone_info->adjoin=image_info->adjoin; 960 clone_info->antialias=image_info->antialias; 961 clone_info->scene=image_info->scene; 962 clone_info->number_scenes=image_info->number_scenes; 963 clone_info->depth=image_info->depth; 964 (void) CloneString(&clone_info->size,image_info->size); 965 (void) CloneString(&clone_info->extract,image_info->extract); 966 (void) CloneString(&clone_info->scenes,image_info->scenes); 967 (void) CloneString(&clone_info->page,image_info->page); 968 clone_info->interlace=image_info->interlace; 969 clone_info->endian=image_info->endian; 970 clone_info->units=image_info->units; 971 clone_info->quality=image_info->quality; 972 (void) CloneString(&clone_info->sampling_factor,image_info->sampling_factor); 973 (void) CloneString(&clone_info->server_name,image_info->server_name); 974 (void) CloneString(&clone_info->font,image_info->font); 975 (void) CloneString(&clone_info->texture,image_info->texture); 976 (void) CloneString(&clone_info->density,image_info->density); 977 clone_info->pointsize=image_info->pointsize; 978 clone_info->fuzz=image_info->fuzz; 979 clone_info->alpha_color=image_info->alpha_color; 980 clone_info->background_color=image_info->background_color; 981 clone_info->border_color=image_info->border_color; 982 clone_info->transparent_color=image_info->transparent_color; 983 clone_info->dither=image_info->dither; 984 clone_info->monochrome=image_info->monochrome; 985 clone_info->colorspace=image_info->colorspace; 986 clone_info->type=image_info->type; 987 clone_info->orientation=image_info->orientation; 988 clone_info->ping=image_info->ping; 989 clone_info->verbose=image_info->verbose; 990 clone_info->progress_monitor=image_info->progress_monitor; 991 clone_info->client_data=image_info->client_data; 992 clone_info->cache=image_info->cache; 993 if (image_info->cache != (void *) NULL) 994 clone_info->cache=ReferencePixelCache(image_info->cache); 995 if (image_info->profile != (void *) NULL) 996 clone_info->profile=(void *) CloneStringInfo((StringInfo *) 997 image_info->profile); 998 SetImageInfoFile(clone_info,image_info->file); 999 SetImageInfoBlob(clone_info,image_info->blob,image_info->length); 1000 clone_info->stream=image_info->stream; 1001 (void) CopyMagickString(clone_info->magick,image_info->magick, 1002 MagickPathExtent); 1003 (void) CopyMagickString(clone_info->unique,image_info->unique, 1004 MagickPathExtent); 1005 (void) CopyMagickString(clone_info->filename,image_info->filename, 1006 MagickPathExtent); 1007 clone_info->channel=image_info->channel; 1008 (void) CloneImageOptions(clone_info,image_info); 1009 clone_info->debug=IsEventLogging(); 1010 clone_info->signature=image_info->signature; 1011 return(clone_info); 1012 } 1013 1014 /* 1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1017 % % 1018 % % 1019 % % 1020 % C o p y I m a g e P i x e l s % 1021 % % 1022 % % 1023 % % 1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1025 % 1026 % CopyImagePixels() copies pixels from the source image as defined by the 1027 % geometry the destination image at the specified offset. 1028 % 1029 % The format of the CopyImagePixels method is: 1030 % 1031 % MagickBooleanType CopyImagePixels(Image *image,const Image *source_image, 1032 % const RectangleInfo *geometry,const OffsetInfo *offset, 1033 % ExceptionInfo *exception); 1034 % 1035 % A description of each parameter follows: 1036 % 1037 % o image: the destination image. 1038 % 1039 % o source_image: the source image. 1040 % 1041 % o geometry: define the dimensions of the source pixel rectangle. 1042 % 1043 % o offset: define the offset in the destination image. 1044 % 1045 % o exception: return any errors or warnings in this structure. 1046 % 1047 */ 1048 MagickExport MagickBooleanType CopyImagePixels(Image *image, 1049 const Image *source_image,const RectangleInfo *geometry, 1050 const OffsetInfo *offset,ExceptionInfo *exception) 1051 { 1052 #define CopyImageTag "Copy/Image" 1053 1054 CacheView 1055 *image_view, 1056 *source_view; 1057 1058 MagickBooleanType 1059 status; 1060 1061 MagickOffsetType 1062 progress; 1063 1064 ssize_t 1065 y; 1066 1067 assert(image != (Image *) NULL); 1068 if (image->debug != MagickFalse) 1069 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1070 assert(source_image != (Image *) NULL); 1071 assert(geometry != (RectangleInfo *) NULL); 1072 assert(offset != (OffsetInfo *) NULL); 1073 if ((offset->x < 0) || (offset->y < 0) || 1074 ((ssize_t) (offset->x+geometry->width) > (ssize_t) image->columns) || 1075 ((ssize_t) (offset->y+geometry->height) > (ssize_t) image->rows)) 1076 ThrowBinaryException(OptionError,"GeometryDoesNotContainImage", 1077 image->filename); 1078 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 1079 return(MagickFalse); 1080 /* 1081 Copy image pixels. 1082 */ 1083 status=MagickTrue; 1084 progress=0; 1085 source_view=AcquireVirtualCacheView(source_image,exception); 1086 image_view=AcquireAuthenticCacheView(image,exception); 1087 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1088 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 1089 magick_threads(image,source_image,geometry->height,1) 1090 #endif 1091 for (y=0; y < (ssize_t) geometry->height; y++) 1092 { 1093 MagickBooleanType 1094 sync; 1095 1096 register const Quantum 1097 *magick_restrict p; 1098 1099 register ssize_t 1100 x; 1101 1102 register Quantum 1103 *magick_restrict q; 1104 1105 if (status == MagickFalse) 1106 continue; 1107 p=GetCacheViewVirtualPixels(source_view,geometry->x,y+geometry->y, 1108 geometry->width,1,exception); 1109 q=QueueCacheViewAuthenticPixels(image_view,offset->x,y+offset->y, 1110 geometry->width,1,exception); 1111 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 1112 { 1113 status=MagickFalse; 1114 continue; 1115 } 1116 for (x=0; x < (ssize_t) geometry->width; x++) 1117 { 1118 register ssize_t 1119 i; 1120 1121 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 1122 { 1123 PixelChannel channel=GetPixelChannelChannel(image,i); 1124 PixelTrait traits=GetPixelChannelTraits(image,channel); 1125 PixelTrait source_traits=GetPixelChannelTraits(source_image,channel); 1126 if ((traits == UndefinedPixelTrait) || 1127 (source_traits == UndefinedPixelTrait)) 1128 continue; 1129 SetPixelChannel(image,channel,p[i],q); 1130 } 1131 p+=GetPixelChannels(source_image); 1132 q+=GetPixelChannels(image); 1133 } 1134 sync=SyncCacheViewAuthenticPixels(image_view,exception); 1135 if (sync == MagickFalse) 1136 status=MagickFalse; 1137 if (image->progress_monitor != (MagickProgressMonitor) NULL) 1138 { 1139 MagickBooleanType 1140 proceed; 1141 1142 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1143 #pragma omp critical (MagickCore_CopyImage) 1144 #endif 1145 proceed=SetImageProgress(image,CopyImageTag,progress++,image->rows); 1146 if (proceed == MagickFalse) 1147 status=MagickFalse; 1148 } 1149 } 1150 source_view=DestroyCacheView(source_view); 1151 image_view=DestroyCacheView(image_view); 1152 return(status); 1153 } 1154 1155 /* 1157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1158 % % 1159 % % 1160 % % 1161 % D e s t r o y I m a g e % 1162 % % 1163 % % 1164 % % 1165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1166 % 1167 % DestroyImage() dereferences an image, deallocating memory associated with 1168 % the image if the reference count becomes zero. 1169 % 1170 % The format of the DestroyImage method is: 1171 % 1172 % Image *DestroyImage(Image *image) 1173 % 1174 % A description of each parameter follows: 1175 % 1176 % o image: the image. 1177 % 1178 */ 1179 MagickExport Image *DestroyImage(Image *image) 1180 { 1181 MagickBooleanType 1182 destroy; 1183 1184 /* 1185 Dereference image. 1186 */ 1187 assert(image != (Image *) NULL); 1188 assert(image->signature == MagickCoreSignature); 1189 if (image->debug != MagickFalse) 1190 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1191 destroy=MagickFalse; 1192 LockSemaphoreInfo(image->semaphore); 1193 image->reference_count--; 1194 if (image->reference_count == 0) 1195 destroy=MagickTrue; 1196 UnlockSemaphoreInfo(image->semaphore); 1197 if (destroy == MagickFalse) 1198 return((Image *) NULL); 1199 /* 1200 Destroy image. 1201 */ 1202 DestroyImagePixels(image); 1203 image->channel_map=DestroyPixelChannelMap(image->channel_map); 1204 if (image->montage != (char *) NULL) 1205 image->montage=DestroyString(image->montage); 1206 if (image->directory != (char *) NULL) 1207 image->directory=DestroyString(image->directory); 1208 if (image->colormap != (PixelInfo *) NULL) 1209 image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap); 1210 if (image->geometry != (char *) NULL) 1211 image->geometry=DestroyString(image->geometry); 1212 DestroyImageProfiles(image); 1213 DestroyImageProperties(image); 1214 DestroyImageArtifacts(image); 1215 if (image->ascii85 != (Ascii85Info *) NULL) 1216 image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85); 1217 if (image->image_info != (ImageInfo *) NULL) 1218 image->image_info=DestroyImageInfo(image->image_info); 1219 DestroyBlob(image); 1220 if (image->semaphore != (SemaphoreInfo *) NULL) 1221 RelinquishSemaphoreInfo(&image->semaphore); 1222 image->signature=(~MagickCoreSignature); 1223 image=(Image *) RelinquishMagickMemory(image); 1224 return(image); 1225 } 1226 1227 /* 1229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1230 % % 1231 % % 1232 % % 1233 % D e s t r o y I m a g e I n f o % 1234 % % 1235 % % 1236 % % 1237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1238 % 1239 % DestroyImageInfo() deallocates memory associated with an ImageInfo 1240 % structure. 1241 % 1242 % The format of the DestroyImageInfo method is: 1243 % 1244 % ImageInfo *DestroyImageInfo(ImageInfo *image_info) 1245 % 1246 % A description of each parameter follows: 1247 % 1248 % o image_info: the image info. 1249 % 1250 */ 1251 MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info) 1252 { 1253 assert(image_info != (ImageInfo *) NULL); 1254 assert(image_info->signature == MagickCoreSignature); 1255 if (image_info->debug != MagickFalse) 1256 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 1257 image_info->filename); 1258 if (image_info->size != (char *) NULL) 1259 image_info->size=DestroyString(image_info->size); 1260 if (image_info->extract != (char *) NULL) 1261 image_info->extract=DestroyString(image_info->extract); 1262 if (image_info->scenes != (char *) NULL) 1263 image_info->scenes=DestroyString(image_info->scenes); 1264 if (image_info->page != (char *) NULL) 1265 image_info->page=DestroyString(image_info->page); 1266 if (image_info->sampling_factor != (char *) NULL) 1267 image_info->sampling_factor=DestroyString( 1268 image_info->sampling_factor); 1269 if (image_info->server_name != (char *) NULL) 1270 image_info->server_name=DestroyString( 1271 image_info->server_name); 1272 if (image_info->font != (char *) NULL) 1273 image_info->font=DestroyString(image_info->font); 1274 if (image_info->texture != (char *) NULL) 1275 image_info->texture=DestroyString(image_info->texture); 1276 if (image_info->density != (char *) NULL) 1277 image_info->density=DestroyString(image_info->density); 1278 if (image_info->cache != (void *) NULL) 1279 image_info->cache=DestroyPixelCache(image_info->cache); 1280 if (image_info->profile != (StringInfo *) NULL) 1281 image_info->profile=(void *) DestroyStringInfo((StringInfo *) 1282 image_info->profile); 1283 DestroyImageOptions(image_info); 1284 image_info->signature=(~MagickCoreSignature); 1285 image_info=(ImageInfo *) RelinquishMagickMemory(image_info); 1286 return(image_info); 1287 } 1288 1289 /* 1291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1292 % % 1293 % % 1294 % % 1295 + D i s a s s o c i a t e I m a g e S t r e a m % 1296 % % 1297 % % 1298 % % 1299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1300 % 1301 % DisassociateImageStream() disassociates the image stream. It checks if the 1302 % blob of the specified image is referenced by other images. If the reference 1303 % count is higher then 1 a new blob is assigned to the specified image. 1304 % 1305 % The format of the DisassociateImageStream method is: 1306 % 1307 % void DisassociateImageStream(const Image *image) 1308 % 1309 % A description of each parameter follows: 1310 % 1311 % o image: the image. 1312 % 1313 */ 1314 MagickExport void DisassociateImageStream(Image *image) 1315 { 1316 assert(image != (Image *) NULL); 1317 assert(image->signature == MagickCoreSignature); 1318 if (image->debug != MagickFalse) 1319 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1320 DisassociateBlob(image); 1321 } 1322 1323 /* 1325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1326 % % 1327 % % 1328 % % 1329 % G e t I m a g e I n f o % 1330 % % 1331 % % 1332 % % 1333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1334 % 1335 % GetImageInfo() initializes image_info to default values. 1336 % 1337 % The format of the GetImageInfo method is: 1338 % 1339 % void GetImageInfo(ImageInfo *image_info) 1340 % 1341 % A description of each parameter follows: 1342 % 1343 % o image_info: the image info. 1344 % 1345 */ 1346 MagickExport void GetImageInfo(ImageInfo *image_info) 1347 { 1348 char 1349 *synchronize; 1350 1351 ExceptionInfo 1352 *exception; 1353 1354 /* 1355 File and image dimension members. 1356 */ 1357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1358 assert(image_info != (ImageInfo *) NULL); 1359 (void) ResetMagickMemory(image_info,0,sizeof(*image_info)); 1360 image_info->adjoin=MagickTrue; 1361 image_info->interlace=NoInterlace; 1362 image_info->channel=DefaultChannels; 1363 image_info->quality=UndefinedCompressionQuality; 1364 image_info->antialias=MagickTrue; 1365 image_info->dither=MagickTrue; 1366 synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE"); 1367 if (synchronize != (const char *) NULL) 1368 { 1369 image_info->synchronize=IsStringTrue(synchronize); 1370 synchronize=DestroyString(synchronize); 1371 } 1372 exception=AcquireExceptionInfo(); 1373 (void) QueryColorCompliance(AlphaColor,AllCompliance,&image_info->alpha_color, 1374 exception); 1375 (void) QueryColorCompliance(BackgroundColor,AllCompliance, 1376 &image_info->background_color,exception); 1377 (void) QueryColorCompliance(BorderColor,AllCompliance, 1378 &image_info->border_color,exception); 1379 (void) QueryColorCompliance(TransparentColor,AllCompliance, 1380 &image_info->transparent_color,exception); 1381 exception=DestroyExceptionInfo(exception); 1382 image_info->debug=IsEventLogging(); 1383 image_info->signature=MagickCoreSignature; 1384 } 1385 1386 /* 1388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1389 % % 1390 % % 1391 % % 1392 % G e t I m a g e I n f o F i l e % 1393 % % 1394 % % 1395 % % 1396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1397 % 1398 % GetImageInfoFile() returns the image info file member. 1399 % 1400 % The format of the GetImageInfoFile method is: 1401 % 1402 % FILE *GetImageInfoFile(const ImageInfo *image_info) 1403 % 1404 % A description of each parameter follows: 1405 % 1406 % o image_info: the image info. 1407 % 1408 */ 1409 MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info) 1410 { 1411 return(image_info->file); 1412 } 1413 1414 /* 1416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1417 % % 1418 % % 1419 % % 1420 % G e t I m a g e M a s k % 1421 % % 1422 % % 1423 % % 1424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1425 % 1426 % GetImageMask() returns the mask associated with the image. 1427 % 1428 % The format of the GetImageMask method is: 1429 % 1430 % Image *GetImageMask(const Image *image,const PixelMask type, 1431 % ExceptionInfo *exception) 1432 % 1433 % A description of each parameter follows: 1434 % 1435 % o image: the image. 1436 % 1437 % o type: the mask type, ReadPixelMask or WritePixelMask. 1438 % 1439 */ 1440 MagickExport Image *GetImageMask(const Image *image,const PixelMask type, 1441 ExceptionInfo *exception) 1442 { 1443 CacheView 1444 *mask_view, 1445 *image_view; 1446 1447 Image 1448 *mask_image; 1449 1450 MagickBooleanType 1451 status; 1452 1453 ssize_t 1454 y; 1455 1456 /* 1457 Get image mask. 1458 */ 1459 assert(image != (Image *) NULL); 1460 if (image->debug != MagickFalse) 1461 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1462 assert(image->signature == MagickCoreSignature); 1463 mask_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); 1464 if (mask_image == (Image *) NULL) 1465 return((Image *) NULL); 1466 status=MagickTrue; 1467 mask_image->alpha_trait=UndefinedPixelTrait; 1468 (void) SetImageColorspace(mask_image,GRAYColorspace,exception); 1469 mask_image->read_mask=MagickFalse; 1470 image_view=AcquireVirtualCacheView(image,exception); 1471 mask_view=AcquireAuthenticCacheView(mask_image,exception); 1472 for (y=0; y < (ssize_t) image->rows; y++) 1473 { 1474 register const Quantum 1475 *magick_restrict p; 1476 1477 register Quantum 1478 *magick_restrict q; 1479 1480 register ssize_t 1481 x; 1482 1483 if (status == MagickFalse) 1484 continue; 1485 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 1486 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1, 1487 exception); 1488 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 1489 { 1490 status=MagickFalse; 1491 continue; 1492 } 1493 for (x=0; x < (ssize_t) image->columns; x++) 1494 { 1495 switch (type) 1496 { 1497 case WritePixelMask: 1498 { 1499 SetPixelGray(mask_image,GetPixelWriteMask(image,p),q); 1500 break; 1501 } 1502 default: 1503 { 1504 SetPixelGray(mask_image,GetPixelReadMask(image,p),q); 1505 break; 1506 } 1507 } 1508 p+=GetPixelChannels(image); 1509 q+=GetPixelChannels(mask_image); 1510 } 1511 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse) 1512 status=MagickFalse; 1513 } 1514 mask_view=DestroyCacheView(mask_view); 1515 image_view=DestroyCacheView(image_view); 1516 if (status == MagickFalse) 1517 mask_image=DestroyImage(mask_image); 1518 return(mask_image); 1519 } 1520 1521 /* 1523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1524 % % 1525 % % 1526 % % 1527 + G e t I m a g e R e f e r e n c e C o u n t % 1528 % % 1529 % % 1530 % % 1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1532 % 1533 % GetImageReferenceCount() returns the image reference count. 1534 % 1535 % The format of the GetReferenceCount method is: 1536 % 1537 % ssize_t GetImageReferenceCount(Image *image) 1538 % 1539 % A description of each parameter follows: 1540 % 1541 % o image: the image. 1542 % 1543 */ 1544 MagickExport ssize_t GetImageReferenceCount(Image *image) 1545 { 1546 ssize_t 1547 reference_count; 1548 1549 assert(image != (Image *) NULL); 1550 assert(image->signature == MagickCoreSignature); 1551 if (image->debug != MagickFalse) 1552 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1553 LockSemaphoreInfo(image->semaphore); 1554 reference_count=image->reference_count; 1555 UnlockSemaphoreInfo(image->semaphore); 1556 return(reference_count); 1557 } 1558 1559 /* 1561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1562 % % 1563 % % 1564 % % 1565 % G e t I m a g e V i r t u a l P i x e l M e t h o d % 1566 % % 1567 % % 1568 % % 1569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1570 % 1571 % GetImageVirtualPixelMethod() gets the "virtual pixels" method for the 1572 % image. A virtual pixel is any pixel access that is outside the boundaries 1573 % of the image cache. 1574 % 1575 % The format of the GetImageVirtualPixelMethod() method is: 1576 % 1577 % VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image) 1578 % 1579 % A description of each parameter follows: 1580 % 1581 % o image: the image. 1582 % 1583 */ 1584 MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image) 1585 { 1586 assert(image != (Image *) NULL); 1587 assert(image->signature == MagickCoreSignature); 1588 if (image->debug != MagickFalse) 1589 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1590 return(GetPixelCacheVirtualMethod(image)); 1591 } 1592 1593 /* 1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1596 % % 1597 % % 1598 % % 1599 % I n t e r p r e t I m a g e F i l e n a m e % 1600 % % 1601 % % 1602 % % 1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1604 % 1605 % InterpretImageFilename() interprets embedded characters in an image filename. 1606 % The filename length is returned. 1607 % 1608 % The format of the InterpretImageFilename method is: 1609 % 1610 % size_t InterpretImageFilename(const ImageInfo *image_info,Image *image, 1611 % const char *format,int value,char *filename,ExceptionInfo *exception) 1612 % 1613 % A description of each parameter follows. 1614 % 1615 % o image_info: the image info.. 1616 % 1617 % o image: the image. 1618 % 1619 % o format: A filename describing the format to use to write the numeric 1620 % argument. Only the first numeric format identifier is replaced. 1621 % 1622 % o value: Numeric value to substitute into format filename. 1623 % 1624 % o filename: return the formatted filename in this character buffer. 1625 % 1626 % o exception: return any errors or warnings in this structure. 1627 % 1628 */ 1629 MagickExport size_t InterpretImageFilename(const ImageInfo *image_info, 1630 Image *image,const char *format,int value,char *filename, 1631 ExceptionInfo *exception) 1632 { 1633 char 1634 *q; 1635 1636 int 1637 c; 1638 1639 MagickBooleanType 1640 canonical; 1641 1642 register const char 1643 *p; 1644 1645 size_t 1646 length; 1647 1648 canonical=MagickFalse; 1649 length=0; 1650 (void) CopyMagickString(filename,format,MagickPathExtent); 1651 for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%')) 1652 { 1653 q=(char *) p+1; 1654 if (*q == '%') 1655 { 1656 p=q+1; 1657 continue; 1658 } 1659 if (*q == '0') 1660 { 1661 ssize_t 1662 foo; 1663 1664 foo=(ssize_t) strtol(q,&q,10); 1665 (void) foo; 1666 } 1667 switch (*q) 1668 { 1669 case 'd': 1670 case 'o': 1671 case 'x': 1672 { 1673 q++; 1674 c=(*q); 1675 *q='\0'; 1676 (void) FormatLocaleString(filename+(p-format),(size_t) 1677 (MagickPathExtent-(p-format)),p,value); 1678 *q=c; 1679 (void) ConcatenateMagickString(filename,q,MagickPathExtent); 1680 canonical=MagickTrue; 1681 if (*(q-1) != '%') 1682 break; 1683 p++; 1684 break; 1685 } 1686 case '[': 1687 { 1688 char 1689 pattern[MagickPathExtent]; 1690 1691 const char 1692 *option; 1693 1694 register char 1695 *r; 1696 1697 register ssize_t 1698 i; 1699 1700 ssize_t 1701 depth; 1702 1703 /* 1704 Image option. 1705 */ 1706 /* FUTURE: Compare update with code from InterpretImageProperties() 1707 Note that a 'filename:' property should not need depth recursion. 1708 */ 1709 if (strchr(p,']') == (char *) NULL) 1710 break; 1711 depth=1; 1712 r=q+1; 1713 for (i=0; (i < (MagickPathExtent-1L)) && (*r != '\0'); i++) 1714 { 1715 if (*r == '[') 1716 depth++; 1717 if (*r == ']') 1718 depth--; 1719 if (depth <= 0) 1720 break; 1721 pattern[i]=(*r++); 1722 } 1723 pattern[i]='\0'; 1724 if (LocaleNCompare(pattern,"filename:",9) != 0) 1725 break; 1726 option=(const char *) NULL; 1727 if (image != (Image *) NULL) 1728 option=GetImageProperty(image,pattern,exception); 1729 if ((option == (const char *) NULL) && (image != (Image *) NULL)) 1730 option=GetImageArtifact(image,pattern); 1731 if ((option == (const char *) NULL) && 1732 (image_info != (ImageInfo *) NULL)) 1733 option=GetImageOption(image_info,pattern); 1734 if (option == (const char *) NULL) 1735 break; 1736 q--; 1737 c=(*q); 1738 *q='\0'; 1739 (void) CopyMagickString(filename+(p-format-length),option,(size_t) 1740 (MagickPathExtent-(p-format-length))); 1741 length+=strlen(pattern)-1; 1742 *q=c; 1743 (void) ConcatenateMagickString(filename,r+1,MagickPathExtent); 1744 canonical=MagickTrue; 1745 if (*(q-1) != '%') 1746 break; 1747 p++; 1748 break; 1749 } 1750 default: 1751 break; 1752 } 1753 } 1754 for (q=filename; *q != '\0'; q++) 1755 if ((*q == '%') && (*(q+1) == '%')) 1756 { 1757 (void) CopyMagickString(q,q+1,(size_t) (MagickPathExtent-(q-filename))); 1758 canonical=MagickTrue; 1759 } 1760 if (canonical == MagickFalse) 1761 (void) CopyMagickString(filename,format,MagickPathExtent); 1762 return(strlen(filename)); 1763 } 1764 1765 /* 1767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1768 % % 1769 % % 1770 % % 1771 % I s H i g h D y n a m i c R a n g e I m a g e % 1772 % % 1773 % % 1774 % % 1775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1776 % 1777 % IsHighDynamicRangeImage() returns MagickTrue if any pixel component is 1778 % non-integer or exceeds the bounds of the quantum depth (e.g. for Q16 1779 % 0..65535. 1780 % 1781 % The format of the IsHighDynamicRangeImage method is: 1782 % 1783 % MagickBooleanType IsHighDynamicRangeImage(const Image *image, 1784 % ExceptionInfo *exception) 1785 % 1786 % A description of each parameter follows: 1787 % 1788 % o image: the image. 1789 % 1790 % o exception: return any errors or warnings in this structure. 1791 % 1792 */ 1793 MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image, 1794 ExceptionInfo *exception) 1795 { 1796 #if !defined(MAGICKCORE_HDRI_SUPPORT) 1797 (void) image; 1798 (void) exception; 1799 return(MagickFalse); 1800 #else 1801 CacheView 1802 *image_view; 1803 1804 MagickBooleanType 1805 status; 1806 1807 ssize_t 1808 y; 1809 1810 assert(image != (Image *) NULL); 1811 assert(image->signature == MagickCoreSignature); 1812 if (image->debug != MagickFalse) 1813 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1814 status=MagickTrue; 1815 image_view=AcquireVirtualCacheView(image,exception); 1816 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1817 #pragma omp parallel for schedule(static,4) shared(status) \ 1818 magick_threads(image,image,image->rows,1) 1819 #endif 1820 for (y=0; y < (ssize_t) image->rows; y++) 1821 { 1822 register const Quantum 1823 *p; 1824 1825 register ssize_t 1826 x; 1827 1828 if (status == MagickFalse) 1829 continue; 1830 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); 1831 if (p == (const Quantum *) NULL) 1832 { 1833 status=MagickFalse; 1834 continue; 1835 } 1836 for (x=0; x < (ssize_t) image->columns; x++) 1837 { 1838 register ssize_t 1839 i; 1840 1841 if (GetPixelReadMask(image,p) == 0) 1842 { 1843 p+=GetPixelChannels(image); 1844 continue; 1845 } 1846 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 1847 { 1848 double 1849 pixel; 1850 1851 PixelTrait 1852 traits; 1853 1854 traits=GetPixelChannelTraits(image,(PixelChannel) i); 1855 if (traits == UndefinedPixelTrait) 1856 continue; 1857 pixel=(double) p[i]; 1858 if ((pixel < 0.0) || (pixel > QuantumRange) || 1859 (pixel != (double) ((QuantumAny) pixel))) 1860 break; 1861 } 1862 p+=GetPixelChannels(image); 1863 if (i < (ssize_t) GetPixelChannels(image)) 1864 status=MagickFalse; 1865 } 1866 if (x < (ssize_t) image->columns) 1867 status=MagickFalse; 1868 } 1869 image_view=DestroyCacheView(image_view); 1870 return(status != MagickFalse ? MagickFalse : MagickTrue); 1871 #endif 1872 } 1873 1874 /* 1876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1877 % % 1878 % % 1879 % % 1880 % I s I m a g e O b j e c t % 1881 % % 1882 % % 1883 % % 1884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1885 % 1886 % IsImageObject() returns MagickTrue if the image sequence contains a valid 1887 % set of image objects. 1888 % 1889 % The format of the IsImageObject method is: 1890 % 1891 % MagickBooleanType IsImageObject(const Image *image) 1892 % 1893 % A description of each parameter follows: 1894 % 1895 % o image: the image. 1896 % 1897 */ 1898 MagickExport MagickBooleanType IsImageObject(const Image *image) 1899 { 1900 register const Image 1901 *p; 1902 1903 assert(image != (Image *) NULL); 1904 if (image->debug != MagickFalse) 1905 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1906 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 1907 if (p->signature != MagickCoreSignature) 1908 return(MagickFalse); 1909 return(MagickTrue); 1910 } 1911 1912 /* 1914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1915 % % 1916 % % 1917 % % 1918 % I s T a i n t I m a g e % 1919 % % 1920 % % 1921 % % 1922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1923 % 1924 % IsTaintImage() returns MagickTrue any pixel in the image has been altered 1925 % since it was first constituted. 1926 % 1927 % The format of the IsTaintImage method is: 1928 % 1929 % MagickBooleanType IsTaintImage(const Image *image) 1930 % 1931 % A description of each parameter follows: 1932 % 1933 % o image: the image. 1934 % 1935 */ 1936 MagickExport MagickBooleanType IsTaintImage(const Image *image) 1937 { 1938 char 1939 magick[MagickPathExtent], 1940 filename[MagickPathExtent]; 1941 1942 register const Image 1943 *p; 1944 1945 assert(image != (Image *) NULL); 1946 if (image->debug != MagickFalse) 1947 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 1948 assert(image->signature == MagickCoreSignature); 1949 (void) CopyMagickString(magick,image->magick,MagickPathExtent); 1950 (void) CopyMagickString(filename,image->filename,MagickPathExtent); 1951 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p)) 1952 { 1953 if (p->taint != MagickFalse) 1954 return(MagickTrue); 1955 if (LocaleCompare(p->magick,magick) != 0) 1956 return(MagickTrue); 1957 if (LocaleCompare(p->filename,filename) != 0) 1958 return(MagickTrue); 1959 } 1960 return(MagickFalse); 1961 } 1962 1963 /* 1965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1966 % % 1967 % % 1968 % % 1969 % M o d i f y I m a g e % 1970 % % 1971 % % 1972 % % 1973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1974 % 1975 % ModifyImage() ensures that there is only a single reference to the image 1976 % to be modified, updating the provided image pointer to point to a clone of 1977 % the original image if necessary. 1978 % 1979 % The format of the ModifyImage method is: 1980 % 1981 % MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception) 1982 % 1983 % A description of each parameter follows: 1984 % 1985 % o image: the image. 1986 % 1987 % o exception: return any errors or warnings in this structure. 1988 % 1989 */ 1990 MagickExport MagickBooleanType ModifyImage(Image **image, 1991 ExceptionInfo *exception) 1992 { 1993 Image 1994 *clone_image; 1995 1996 assert(image != (Image **) NULL); 1997 assert(*image != (Image *) NULL); 1998 assert((*image)->signature == MagickCoreSignature); 1999 if ((*image)->debug != MagickFalse) 2000 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename); 2001 if (GetImageReferenceCount(*image) <= 1) 2002 return(MagickTrue); 2003 clone_image=CloneImage(*image,0,0,MagickTrue,exception); 2004 LockSemaphoreInfo((*image)->semaphore); 2005 (*image)->reference_count--; 2006 UnlockSemaphoreInfo((*image)->semaphore); 2007 *image=clone_image; 2008 return(MagickTrue); 2009 } 2010 2011 /* 2013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2014 % % 2015 % % 2016 % % 2017 % N e w M a g i c k I m a g e % 2018 % % 2019 % % 2020 % % 2021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2022 % 2023 % NewMagickImage() creates a blank image canvas of the specified size and 2024 % background color. 2025 % 2026 % The format of the NewMagickImage method is: 2027 % 2028 % Image *NewMagickImage(const ImageInfo *image_info,const size_t width, 2029 % const size_t height,const PixelInfo *background, 2030 % ExceptionInfo *exception) 2031 % 2032 % A description of each parameter follows: 2033 % 2034 % o image: the image. 2035 % 2036 % o width: the image width. 2037 % 2038 % o height: the image height. 2039 % 2040 % o background: the image color. 2041 % 2042 % o exception: return any errors or warnings in this structure. 2043 % 2044 */ 2045 MagickExport Image *NewMagickImage(const ImageInfo *image_info, 2046 const size_t width,const size_t height,const PixelInfo *background, 2047 ExceptionInfo *exception) 2048 { 2049 CacheView 2050 *image_view; 2051 2052 Image 2053 *image; 2054 2055 MagickBooleanType 2056 status; 2057 2058 ssize_t 2059 y; 2060 2061 assert(image_info != (const ImageInfo *) NULL); 2062 if (image_info->debug != MagickFalse) 2063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 2064 assert(image_info->signature == MagickCoreSignature); 2065 assert(background != (const PixelInfo *) NULL); 2066 image=AcquireImage(image_info,exception); 2067 image->columns=width; 2068 image->rows=height; 2069 image->colorspace=background->colorspace; 2070 image->alpha_trait=background->alpha_trait; 2071 image->fuzz=background->fuzz; 2072 image->depth=background->depth; 2073 status=MagickTrue; 2074 image_view=AcquireAuthenticCacheView(image,exception); 2075 #if defined(MAGICKCORE_OPENMP_SUPPORT) 2076 #pragma omp parallel for schedule(static,4) shared(status) \ 2077 magick_threads(image,image,image->rows,1) 2078 #endif 2079 for (y=0; y < (ssize_t) image->rows; y++) 2080 { 2081 register Quantum 2082 *magick_restrict q; 2083 2084 register ssize_t 2085 x; 2086 2087 if (status == MagickFalse) 2088 continue; 2089 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 2090 if (q == (Quantum *) NULL) 2091 { 2092 status=MagickFalse; 2093 continue; 2094 } 2095 for (x=0; x < (ssize_t) image->columns; x++) 2096 { 2097 SetPixelViaPixelInfo(image,background,q); 2098 q+=GetPixelChannels(image); 2099 } 2100 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 2101 status=MagickFalse; 2102 } 2103 image_view=DestroyCacheView(image_view); 2104 if (status == MagickFalse) 2105 image=DestroyImage(image); 2106 return(image); 2107 } 2108 2109 /* 2111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2112 % % 2113 % % 2114 % % 2115 % R e f e r e n c e I m a g e % 2116 % % 2117 % % 2118 % % 2119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2120 % 2121 % ReferenceImage() increments the reference count associated with an image 2122 % returning a pointer to the image. 2123 % 2124 % The format of the ReferenceImage method is: 2125 % 2126 % Image *ReferenceImage(Image *image) 2127 % 2128 % A description of each parameter follows: 2129 % 2130 % o image: the image. 2131 % 2132 */ 2133 MagickExport Image *ReferenceImage(Image *image) 2134 { 2135 assert(image != (Image *) NULL); 2136 if (image->debug != MagickFalse) 2137 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 2138 assert(image->signature == MagickCoreSignature); 2139 LockSemaphoreInfo(image->semaphore); 2140 image->reference_count++; 2141 UnlockSemaphoreInfo(image->semaphore); 2142 return(image); 2143 } 2144 2145 /* 2147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2148 % % 2149 % % 2150 % % 2151 % R e s e t I m a g e P a g e % 2152 % % 2153 % % 2154 % % 2155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2156 % 2157 % ResetImagePage() resets the image page canvas and position. 2158 % 2159 % The format of the ResetImagePage method is: 2160 % 2161 % MagickBooleanType ResetImagePage(Image *image,const char *page) 2162 % 2163 % A description of each parameter follows: 2164 % 2165 % o image: the image. 2166 % 2167 % o page: the relative page specification. 2168 % 2169 */ 2170 MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page) 2171 { 2172 MagickStatusType 2173 flags; 2174 2175 RectangleInfo 2176 geometry; 2177 2178 assert(image != (Image *) NULL); 2179 assert(image->signature == MagickCoreSignature); 2180 if (image->debug != MagickFalse) 2181 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 2182 flags=ParseAbsoluteGeometry(page,&geometry); 2183 if ((flags & WidthValue) != 0) 2184 { 2185 if ((flags & HeightValue) == 0) 2186 geometry.height=geometry.width; 2187 image->page.width=geometry.width; 2188 image->page.height=geometry.height; 2189 } 2190 if ((flags & AspectValue) != 0) 2191 { 2192 if ((flags & XValue) != 0) 2193 image->page.x+=geometry.x; 2194 if ((flags & YValue) != 0) 2195 image->page.y+=geometry.y; 2196 } 2197 else 2198 { 2199 if ((flags & XValue) != 0) 2200 { 2201 image->page.x=geometry.x; 2202 if ((image->page.width == 0) && (geometry.x > 0)) 2203 image->page.width=image->columns+geometry.x; 2204 } 2205 if ((flags & YValue) != 0) 2206 { 2207 image->page.y=geometry.y; 2208 if ((image->page.height == 0) && (geometry.y > 0)) 2209 image->page.height=image->rows+geometry.y; 2210 } 2211 } 2212 return(MagickTrue); 2213 } 2214 2215 /* 2217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2218 % % 2219 % % 2220 % % 2221 % S e t I m a g e B a c k g r o u n d C o l o r % 2222 % % 2223 % % 2224 % % 2225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2226 % 2227 % SetImageBackgroundColor() initializes the image pixels to the image 2228 % background color. The background color is defined by the background_color 2229 % member of the image structure. 2230 % 2231 % The format of the SetImage method is: 2232 % 2233 % MagickBooleanType SetImageBackgroundColor(Image *image, 2234 % ExceptionInfo *exception) 2235 % 2236 % A description of each parameter follows: 2237 % 2238 % o image: the image. 2239 % 2240 % o exception: return any errors or warnings in this structure. 2241 % 2242 */ 2243 MagickExport MagickBooleanType SetImageBackgroundColor(Image *image, 2244 ExceptionInfo *exception) 2245 { 2246 CacheView 2247 *image_view; 2248 2249 MagickBooleanType 2250 status; 2251 2252 PixelInfo 2253 background; 2254 2255 ssize_t 2256 y; 2257 2258 assert(image != (Image *) NULL); 2259 if (image->debug != MagickFalse) 2260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 2261 assert(image->signature == MagickCoreSignature); 2262 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 2263 return(MagickFalse); 2264 ConformPixelInfo(image,&image->background_color,&background,exception); 2265 /* 2266 Set image background color. 2267 */ 2268 status=MagickTrue; 2269 image_view=AcquireAuthenticCacheView(image,exception); 2270 for (y=0; y < (ssize_t) image->rows; y++) 2271 { 2272 register Quantum 2273 *magick_restrict q; 2274 2275 register ssize_t 2276 x; 2277 2278 if (status == MagickFalse) 2279 continue; 2280 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 2281 if (q == (Quantum *) NULL) 2282 { 2283 status=MagickFalse; 2284 continue; 2285 } 2286 for (x=0; x < (ssize_t) image->columns; x++) 2287 { 2288 SetPixelViaPixelInfo(image,&background,q); 2289 q+=GetPixelChannels(image); 2290 } 2291 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 2292 status=MagickFalse; 2293 } 2294 image_view=DestroyCacheView(image_view); 2295 return(status); 2296 } 2297 2298 /* 2300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2301 % % 2302 % % 2303 % % 2304 % S e t I m a g e C h a n n e l M a s k % 2305 % % 2306 % % 2307 % % 2308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2309 % 2310 % SetImageChannelMask() sets the image channel mask from the specified channel 2311 % mask. 2312 % 2313 % The format of the SetImageChannelMask method is: 2314 % 2315 % ChannelType SetImageChannelMask(Image *image, 2316 % const ChannelType channel_mask) 2317 % 2318 % A description of each parameter follows: 2319 % 2320 % o image: the image. 2321 % 2322 % o channel_mask: the channel mask. 2323 % 2324 */ 2325 MagickExport ChannelType SetImageChannelMask(Image *image, 2326 const ChannelType channel_mask) 2327 { 2328 return(SetPixelChannelMask(image,channel_mask)); 2329 } 2330 2331 /* 2333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2334 % % 2335 % % 2336 % % 2337 % S e t I m a g e C o l o r % 2338 % % 2339 % % 2340 % % 2341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2342 % 2343 % SetImageColor() set the entire image canvas to the specified color. 2344 % 2345 % The format of the SetImageColor method is: 2346 % 2347 % MagickBooleanType SetImageColor(Image *image,const PixelInfo *color, 2348 % ExeptionInfo *exception) 2349 % 2350 % A description of each parameter follows: 2351 % 2352 % o image: the image. 2353 % 2354 % o background: the image color. 2355 % 2356 % o exception: return any errors or warnings in this structure. 2357 % 2358 */ 2359 MagickExport MagickBooleanType SetImageColor(Image *image, 2360 const PixelInfo *color,ExceptionInfo *exception) 2361 { 2362 CacheView 2363 *image_view; 2364 2365 MagickBooleanType 2366 status; 2367 2368 ssize_t 2369 y; 2370 2371 assert(image != (Image *) NULL); 2372 if (image->debug != MagickFalse) 2373 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 2374 assert(image->signature == MagickCoreSignature); 2375 assert(color != (const PixelInfo *) NULL); 2376 image->colorspace=color->colorspace; 2377 image->alpha_trait=color->alpha_trait; 2378 image->fuzz=color->fuzz; 2379 image->depth=color->depth; 2380 status=MagickTrue; 2381 image_view=AcquireAuthenticCacheView(image,exception); 2382 #if defined(MAGICKCORE_OPENMP_SUPPORT) 2383 #pragma omp parallel for schedule(static,4) shared(status) \ 2384 magick_threads(image,image,image->rows,1) 2385 #endif 2386 for (y=0; y < (ssize_t) image->rows; y++) 2387 { 2388 register Quantum 2389 *magick_restrict q; 2390 2391 register ssize_t 2392 x; 2393 2394 if (status == MagickFalse) 2395 continue; 2396 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 2397 if (q == (Quantum *) NULL) 2398 { 2399 status=MagickFalse; 2400 continue; 2401 } 2402 for (x=0; x < (ssize_t) image->columns; x++) 2403 { 2404 SetPixelViaPixelInfo(image,color,q); 2405 q+=GetPixelChannels(image); 2406 } 2407 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 2408 status=MagickFalse; 2409 } 2410 image_view=DestroyCacheView(image_view); 2411 return(status); 2412 } 2413 2414 /* 2416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2417 % % 2418 % % 2419 % % 2420 % S e t I m a g e S t o r a g e C l a s s % 2421 % % 2422 % % 2423 % % 2424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2425 % 2426 % SetImageStorageClass() sets the image class: DirectClass for true color 2427 % images or PseudoClass for colormapped images. 2428 % 2429 % The format of the SetImageStorageClass method is: 2430 % 2431 % MagickBooleanType SetImageStorageClass(Image *image, 2432 % const ClassType storage_class,ExceptionInfo *exception) 2433 % 2434 % A description of each parameter follows: 2435 % 2436 % o image: the image. 2437 % 2438 % o storage_class: The image class. 2439 % 2440 % o exception: return any errors or warnings in this structure. 2441 % 2442 */ 2443 MagickExport MagickBooleanType SetImageStorageClass(Image *image, 2444 const ClassType storage_class,ExceptionInfo *exception) 2445 { 2446 image->storage_class=storage_class; 2447 return(SyncImagePixelCache(image,exception)); 2448 } 2449 2450 /* 2452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2453 % % 2454 % % 2455 % % 2456 % S e t I m a g e E x t e n t % 2457 % % 2458 % % 2459 % % 2460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2461 % 2462 % SetImageExtent() sets the image size (i.e. columns & rows). 2463 % 2464 % The format of the SetImageExtent method is: 2465 % 2466 % MagickBooleanType SetImageExtent(Image *image,const size_t columns, 2467 % const size_t rows,ExceptionInfo *exception) 2468 % 2469 % A description of each parameter follows: 2470 % 2471 % o image: the image. 2472 % 2473 % o columns: The image width in pixels. 2474 % 2475 % o rows: The image height in pixels. 2476 % 2477 % o exception: return any errors or warnings in this structure. 2478 % 2479 */ 2480 MagickExport MagickBooleanType SetImageExtent(Image *image,const size_t columns, 2481 const size_t rows,ExceptionInfo *exception) 2482 { 2483 if ((columns == 0) || (rows == 0)) 2484 ThrowBinaryException(ImageError,"NegativeOrZeroImageSize",image->filename); 2485 image->columns=columns; 2486 image->rows=rows; 2487 if (image->depth > (8*sizeof(MagickSizeType))) 2488 ThrowBinaryException(ImageError,"ImageDepthNotSupported",image->filename); 2489 return(SyncImagePixelCache(image,exception)); 2490 } 2491 2492 /* 2494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2495 % % 2496 % % 2497 % % 2498 + S e t I m a g e I n f o % 2499 % % 2500 % % 2501 % % 2502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2503 % 2504 % SetImageInfo() initializes the 'magick' field of the ImageInfo structure. 2505 % It is set to a type of image format based on the prefix or suffix of the 2506 % filename. For example, 'ps:image' returns PS indicating a Postscript image. 2507 % JPEG is returned for this filename: 'image.jpg'. The filename prefix has 2508 % precendence over the suffix. Use an optional index enclosed in brackets 2509 % after a file name to specify a desired scene of a multi-resolution image 2510 % format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value 2511 % indicates success. 2512 % 2513 % The format of the SetImageInfo method is: 2514 % 2515 % MagickBooleanType SetImageInfo(ImageInfo *image_info, 2516 % const unsigned int frames,ExceptionInfo *exception) 2517 % 2518 % A description of each parameter follows: 2519 % 2520 % o image_info: the image info. 2521 % 2522 % o frames: the number of images you intend to write. 2523 % 2524 % o exception: return any errors or warnings in this structure. 2525 % 2526 */ 2527 MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info, 2528 const unsigned int frames,ExceptionInfo *exception) 2529 { 2530 char 2531 component[MagickPathExtent], 2532 magic[MagickPathExtent], 2533 *q; 2534 2535 const MagicInfo 2536 *magic_info; 2537 2538 const MagickInfo 2539 *magick_info; 2540 2541 ExceptionInfo 2542 *sans_exception; 2543 2544 Image 2545 *image; 2546 2547 MagickBooleanType 2548 status; 2549 2550 register const char 2551 *p; 2552 2553 ssize_t 2554 count; 2555 2556 /* 2557 Look for 'image.format' in filename. 2558 */ 2559 assert(image_info != (ImageInfo *) NULL); 2560 assert(image_info->signature == MagickCoreSignature); 2561 if (image_info->debug != MagickFalse) 2562 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 2563 image_info->filename); 2564 *component='\0'; 2565 GetPathComponent(image_info->filename,SubimagePath,component); 2566 if (*component != '\0') 2567 { 2568 /* 2569 Look for scene specification (e.g. img0001.pcd[4]). 2570 */ 2571 if (IsSceneGeometry(component,MagickFalse) == MagickFalse) 2572 { 2573 if (IsGeometry(component) != MagickFalse) 2574 (void) CloneString(&image_info->extract,component); 2575 } 2576 else 2577 { 2578 size_t 2579 first, 2580 last; 2581 2582 (void) CloneString(&image_info->scenes,component); 2583 image_info->scene=StringToUnsignedLong(image_info->scenes); 2584 image_info->number_scenes=image_info->scene; 2585 p=image_info->scenes; 2586 for (q=(char *) image_info->scenes; *q != '\0'; p++) 2587 { 2588 while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ',')) 2589 p++; 2590 first=(size_t) strtol(p,&q,10); 2591 last=first; 2592 while (isspace((int) ((unsigned char) *q)) != 0) 2593 q++; 2594 if (*q == '-') 2595 last=(size_t) strtol(q+1,&q,10); 2596 if (first > last) 2597 Swap(first,last); 2598 if (first < image_info->scene) 2599 image_info->scene=first; 2600 if (last > image_info->number_scenes) 2601 image_info->number_scenes=last; 2602 p=q; 2603 } 2604 image_info->number_scenes-=image_info->scene-1; 2605 } 2606 } 2607 *component='\0'; 2608 if (*image_info->magick == '\0') 2609 GetPathComponent(image_info->filename,ExtensionPath,component); 2610 #if defined(MAGICKCORE_ZLIB_DELEGATE) 2611 if (*component != '\0') 2612 if ((LocaleCompare(component,"gz") == 0) || 2613 (LocaleCompare(component,"Z") == 0) || 2614 (LocaleCompare(component,"svgz") == 0) || 2615 (LocaleCompare(component,"wmz") == 0)) 2616 { 2617 char 2618 path[MagickPathExtent]; 2619 2620 (void) CopyMagickString(path,image_info->filename,MagickPathExtent); 2621 path[strlen(path)-strlen(component)-1]='\0'; 2622 GetPathComponent(path,ExtensionPath,component); 2623 } 2624 #endif 2625 #if defined(MAGICKCORE_BZLIB_DELEGATE) 2626 if (*component != '\0') 2627 if (LocaleCompare(component,"bz2") == 0) 2628 { 2629 char 2630 path[MagickPathExtent]; 2631 2632 (void) CopyMagickString(path,image_info->filename,MagickPathExtent); 2633 path[strlen(path)-strlen(component)-1]='\0'; 2634 GetPathComponent(path,ExtensionPath,component); 2635 } 2636 #endif 2637 image_info->affirm=MagickFalse; 2638 sans_exception=AcquireExceptionInfo(); 2639 if (*component != '\0') 2640 { 2641 MagickFormatType 2642 format_type; 2643 2644 register ssize_t 2645 i; 2646 2647 static const char 2648 *format_type_formats[] = 2649 { 2650 "AUTOTRACE", 2651 "BROWSE", 2652 "DCRAW", 2653 "EDIT", 2654 "LAUNCH", 2655 "MPEG:DECODE", 2656 "MPEG:ENCODE", 2657 "PRINT", 2658 "PS:ALPHA", 2659 "PS:CMYK", 2660 "PS:COLOR", 2661 "PS:GRAY", 2662 "PS:MONO", 2663 "SCAN", 2664 "SHOW", 2665 "WIN", 2666 (char *) NULL 2667 }; 2668 2669 /* 2670 User specified image format. 2671 */ 2672 (void) CopyMagickString(magic,component,MagickPathExtent); 2673 LocaleUpper(magic); 2674 /* 2675 Look for explicit image formats. 2676 */ 2677 format_type=UndefinedFormatType; 2678 magick_info=GetMagickInfo(magic,sans_exception); 2679 if ((magick_info != (const MagickInfo *) NULL) && 2680 (magick_info->format_type != UndefinedFormatType)) 2681 format_type=magick_info->format_type; 2682 i=0; 2683 while ((format_type == UndefinedFormatType) && 2684 (format_type_formats[i] != (char *) NULL)) 2685 { 2686 if ((*magic == *format_type_formats[i]) && 2687 (LocaleCompare(magic,format_type_formats[i]) == 0)) 2688 format_type=ExplicitFormatType; 2689 i++; 2690 } 2691 if (format_type == UndefinedFormatType) 2692 (void) CopyMagickString(image_info->magick,magic,MagickPathExtent); 2693 else 2694 if (format_type == ExplicitFormatType) 2695 { 2696 image_info->affirm=MagickTrue; 2697 (void) CopyMagickString(image_info->magick,magic,MagickPathExtent); 2698 } 2699 if (LocaleCompare(magic,"RGB") == 0) 2700 image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */ 2701 } 2702 /* 2703 Look for explicit 'format:image' in filename. 2704 */ 2705 *magic='\0'; 2706 GetPathComponent(image_info->filename,MagickPath,magic); 2707 if (*magic == '\0') 2708 { 2709 (void) CopyMagickString(magic,image_info->magick,MagickPathExtent); 2710 magick_info=GetMagickInfo(magic,sans_exception); 2711 GetPathComponent(image_info->filename,CanonicalPath,component); 2712 (void) CopyMagickString(image_info->filename,component,MagickPathExtent); 2713 } 2714 else 2715 { 2716 const DelegateInfo 2717 *delegate_info; 2718 2719 /* 2720 User specified image format. 2721 */ 2722 LocaleUpper(magic); 2723 magick_info=GetMagickInfo(magic,sans_exception); 2724 delegate_info=GetDelegateInfo(magic,"*",sans_exception); 2725 if (delegate_info == (const DelegateInfo *) NULL) 2726 delegate_info=GetDelegateInfo("*",magic,sans_exception); 2727 if (((magick_info != (const MagickInfo *) NULL) || 2728 (delegate_info != (const DelegateInfo *) NULL)) && 2729 (IsMagickConflict(magic) == MagickFalse)) 2730 { 2731 image_info->affirm=MagickTrue; 2732 (void) CopyMagickString(image_info->magick,magic,MagickPathExtent); 2733 GetPathComponent(image_info->filename,CanonicalPath,component); 2734 (void) CopyMagickString(image_info->filename,component, 2735 MagickPathExtent); 2736 } 2737 } 2738 sans_exception=DestroyExceptionInfo(sans_exception); 2739 if ((magick_info == (const MagickInfo *) NULL) || 2740 (GetMagickEndianSupport(magick_info) == MagickFalse)) 2741 image_info->endian=UndefinedEndian; 2742 if ((image_info->adjoin != MagickFalse) && (frames > 1)) 2743 { 2744 /* 2745 Test for multiple image support (e.g. image%02d.png). 2746 */ 2747 (void) InterpretImageFilename(image_info,(Image *) NULL, 2748 image_info->filename,(int) image_info->scene,component,exception); 2749 if ((LocaleCompare(component,image_info->filename) != 0) && 2750 (strchr(component,'%') == (char *) NULL)) 2751 image_info->adjoin=MagickFalse; 2752 } 2753 if ((image_info->adjoin != MagickFalse) && (frames > 0)) 2754 { 2755 /* 2756 Some image formats do not support multiple frames per file. 2757 */ 2758 magick_info=GetMagickInfo(magic,exception); 2759 if (magick_info != (const MagickInfo *) NULL) 2760 if (GetMagickAdjoin(magick_info) == MagickFalse) 2761 image_info->adjoin=MagickFalse; 2762 } 2763 if (image_info->affirm != MagickFalse) 2764 return(MagickTrue); 2765 if (frames == 0) 2766 { 2767 unsigned char 2768 *magick; 2769 2770 size_t 2771 magick_size; 2772 2773 /* 2774 Determine the image format from the first few bytes of the file. 2775 */ 2776 magick_size=GetMagicPatternExtent(exception); 2777 if (magick_size == 0) 2778 return(MagickFalse); 2779 image=AcquireImage(image_info,exception); 2780 (void) CopyMagickString(image->filename,image_info->filename, 2781 MagickPathExtent); 2782 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 2783 if (status == MagickFalse) 2784 { 2785 image=DestroyImage(image); 2786 return(MagickFalse); 2787 } 2788 if ((IsBlobSeekable(image) == MagickFalse) || 2789 (IsBlobExempt(image) != MagickFalse)) 2790 { 2791 /* 2792 Copy standard input or pipe to temporary file. 2793 */ 2794 *component='\0'; 2795 status=ImageToFile(image,component,exception); 2796 (void) CloseBlob(image); 2797 if (status == MagickFalse) 2798 { 2799 image=DestroyImage(image); 2800 return(MagickFalse); 2801 } 2802 SetImageInfoFile(image_info,(FILE *) NULL); 2803 (void) CopyMagickString(image->filename,component,MagickPathExtent); 2804 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 2805 if (status == MagickFalse) 2806 { 2807 image=DestroyImage(image); 2808 return(MagickFalse); 2809 } 2810 (void) CopyMagickString(image_info->filename,component, 2811 MagickPathExtent); 2812 image_info->temporary=MagickTrue; 2813 } 2814 magick=(unsigned char *) AcquireMagickMemory(magick_size); 2815 if (magick == (unsigned char *) NULL) 2816 { 2817 (void) CloseBlob(image); 2818 image=DestroyImage(image); 2819 return(MagickFalse); 2820 } 2821 (void) ResetMagickMemory(magick,0,magick_size); 2822 count=ReadBlob(image,magick_size,magick); 2823 (void) SeekBlob(image,-((MagickOffsetType) count),SEEK_CUR); 2824 (void) CloseBlob(image); 2825 image=DestroyImage(image); 2826 /* 2827 Check magic.xml configuration file. 2828 */ 2829 sans_exception=AcquireExceptionInfo(); 2830 magic_info=GetMagicInfo(magick,(size_t) count,sans_exception); 2831 magick=(unsigned char *) RelinquishMagickMemory(magick); 2832 if ((magic_info != (const MagicInfo *) NULL) && 2833 (GetMagicName(magic_info) != (char *) NULL)) 2834 { 2835 /* 2836 Try to use magick_info that was determined earlier by the extension 2837 */ 2838 if ((magick_info != (const MagickInfo *) NULL) && 2839 (GetMagickUseExtension(magick_info) != MagickFalse) && 2840 (LocaleCompare(magick_info->module,GetMagicName( 2841 magic_info)) == 0)) 2842 (void) CopyMagickString(image_info->magick,magick_info->name, 2843 MagickPathExtent); 2844 else 2845 { 2846 (void) CopyMagickString(image_info->magick,GetMagicName( 2847 magic_info),MagickPathExtent); 2848 magick_info=GetMagickInfo(image_info->magick,sans_exception); 2849 } 2850 if ((magick_info == (const MagickInfo *) NULL) || 2851 (GetMagickEndianSupport(magick_info) == MagickFalse)) 2852 image_info->endian=UndefinedEndian; 2853 sans_exception=DestroyExceptionInfo(sans_exception); 2854 return(MagickTrue); 2855 } 2856 magick_info=GetMagickInfo(image_info->magick,sans_exception); 2857 if ((magick_info == (const MagickInfo *) NULL) || 2858 (GetMagickEndianSupport(magick_info) == MagickFalse)) 2859 image_info->endian=UndefinedEndian; 2860 sans_exception=DestroyExceptionInfo(sans_exception); 2861 } 2862 return(MagickTrue); 2863 } 2864 2865 /* 2867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2868 % % 2869 % % 2870 % % 2871 % S e t I m a g e I n f o B l o b % 2872 % % 2873 % % 2874 % % 2875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2876 % 2877 % SetImageInfoBlob() sets the image info blob member. 2878 % 2879 % The format of the SetImageInfoBlob method is: 2880 % 2881 % void SetImageInfoBlob(ImageInfo *image_info,const void *blob, 2882 % const size_t length) 2883 % 2884 % A description of each parameter follows: 2885 % 2886 % o image_info: the image info. 2887 % 2888 % o blob: the blob. 2889 % 2890 % o length: the blob length. 2891 % 2892 */ 2893 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob, 2894 const size_t length) 2895 { 2896 assert(image_info != (ImageInfo *) NULL); 2897 assert(image_info->signature == MagickCoreSignature); 2898 if (image_info->debug != MagickFalse) 2899 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 2900 image_info->filename); 2901 image_info->blob=(void *) blob; 2902 image_info->length=length; 2903 } 2904 2905 /* 2907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2908 % % 2909 % % 2910 % % 2911 % S e t I m a g e I n f o F i l e % 2912 % % 2913 % % 2914 % % 2915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2916 % 2917 % SetImageInfoFile() sets the image info file member. 2918 % 2919 % The format of the SetImageInfoFile method is: 2920 % 2921 % void SetImageInfoFile(ImageInfo *image_info,FILE *file) 2922 % 2923 % A description of each parameter follows: 2924 % 2925 % o image_info: the image info. 2926 % 2927 % o file: the file. 2928 % 2929 */ 2930 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file) 2931 { 2932 assert(image_info != (ImageInfo *) NULL); 2933 assert(image_info->signature == MagickCoreSignature); 2934 if (image_info->debug != MagickFalse) 2935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 2936 image_info->filename); 2937 image_info->file=file; 2938 } 2939 2940 /* 2942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2943 % % 2944 % % 2945 % % 2946 % S e t I m a g e M a s k % 2947 % % 2948 % % 2949 % % 2950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2951 % 2952 % SetImageMask() associates a mask with the image. The mask must be the same 2953 % dimensions as the image. 2954 % 2955 % The format of the SetImageMask method is: 2956 % 2957 % MagickBooleanType SetImageMask(Image *image,const PixelMask type, 2958 % const Image *mask,ExceptionInfo *exception) 2959 % 2960 % A description of each parameter follows: 2961 % 2962 % o image: the image. 2963 % 2964 % o type: the mask type, ReadPixelMask or WritePixelMask. 2965 % 2966 % o mask: the image mask. 2967 % 2968 % o exception: return any errors or warnings in this structure. 2969 % 2970 */ 2971 MagickExport MagickBooleanType SetImageMask(Image *image,const PixelMask type, 2972 const Image *mask,ExceptionInfo *exception) 2973 { 2974 CacheView 2975 *mask_view, 2976 *image_view; 2977 2978 MagickBooleanType 2979 status; 2980 2981 ssize_t 2982 y; 2983 2984 /* 2985 Set image mask. 2986 */ 2987 assert(image != (Image *) NULL); 2988 if (image->debug != MagickFalse) 2989 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 2990 assert(image->signature == MagickCoreSignature); 2991 if (mask == (const Image *) NULL) 2992 { 2993 switch (type) 2994 { 2995 case WritePixelMask: image->write_mask=MagickFalse; break; 2996 default: image->read_mask=MagickFalse; break; 2997 } 2998 return(SyncImagePixelCache(image,exception)); 2999 } 3000 switch (type) 3001 { 3002 case WritePixelMask: image->write_mask=MagickTrue; break; 3003 default: image->read_mask=MagickTrue; break; 3004 } 3005 if (SyncImagePixelCache(image,exception) == MagickFalse) 3006 return(MagickFalse); 3007 status=MagickTrue; 3008 mask_view=AcquireVirtualCacheView(mask,exception); 3009 image_view=AcquireAuthenticCacheView(image,exception); 3010 #if defined(MAGICKCORE_OPENMP_SUPPORT) 3011 #pragma omp parallel for schedule(static,4) shared(status) \ 3012 magick_threads(mask,image,1,1) 3013 #endif 3014 for (y=0; y < (ssize_t) image->rows; y++) 3015 { 3016 register const Quantum 3017 *magick_restrict p; 3018 3019 register Quantum 3020 *magick_restrict q; 3021 3022 register ssize_t 3023 x; 3024 3025 if (status == MagickFalse) 3026 continue; 3027 p=GetCacheViewVirtualPixels(mask_view,0,y,mask->columns,1,exception); 3028 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 3029 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 3030 { 3031 status=MagickFalse; 3032 continue; 3033 } 3034 for (x=0; x < (ssize_t) image->columns; x++) 3035 { 3036 MagickRealType 3037 intensity; 3038 3039 intensity=GetPixelIntensity(mask,p); 3040 switch (type) 3041 { 3042 case WritePixelMask: 3043 { 3044 SetPixelWriteMask(image,ClampToQuantum(QuantumRange-intensity),q); 3045 break; 3046 } 3047 default: 3048 { 3049 SetPixelReadMask(image,ClampToQuantum(QuantumRange-intensity),q); 3050 break; 3051 } 3052 } 3053 p+=GetPixelChannels(mask); 3054 q+=GetPixelChannels(image); 3055 } 3056 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 3057 status=MagickFalse; 3058 } 3059 mask_view=DestroyCacheView(mask_view); 3060 image_view=DestroyCacheView(image_view); 3061 return(status); 3062 } 3063 3064 /* 3066 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3067 % % 3068 % % 3069 % % 3070 % S e t I m a g e A l p h a % 3071 % % 3072 % % 3073 % % 3074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3075 % 3076 % SetImageAlpha() sets the alpha levels of the image. 3077 % 3078 % The format of the SetImageAlpha method is: 3079 % 3080 % MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha, 3081 % ExceptionInfo *exception) 3082 % 3083 % A description of each parameter follows: 3084 % 3085 % o image: the image. 3086 % 3087 % o Alpha: the level of transparency: 0 is fully opaque and QuantumRange is 3088 % fully transparent. 3089 % 3090 */ 3091 MagickExport MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha, 3092 ExceptionInfo *exception) 3093 { 3094 CacheView 3095 *image_view; 3096 3097 MagickBooleanType 3098 status; 3099 3100 ssize_t 3101 y; 3102 3103 assert(image != (Image *) NULL); 3104 if (image->debug != MagickFalse) 3105 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 3106 assert(image->signature == MagickCoreSignature); 3107 image->alpha_trait=BlendPixelTrait; 3108 status=MagickTrue; 3109 image_view=AcquireAuthenticCacheView(image,exception); 3110 #if defined(MAGICKCORE_OPENMP_SUPPORT) 3111 #pragma omp parallel for schedule(static,4) shared(status) \ 3112 magick_threads(image,image,image->rows,1) 3113 #endif 3114 for (y=0; y < (ssize_t) image->rows; y++) 3115 { 3116 register Quantum 3117 *magick_restrict q; 3118 3119 register ssize_t 3120 x; 3121 3122 if (status == MagickFalse) 3123 continue; 3124 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 3125 if (q == (Quantum *) NULL) 3126 { 3127 status=MagickFalse; 3128 continue; 3129 } 3130 for (x=0; x < (ssize_t) image->columns; x++) 3131 { 3132 if (GetPixelReadMask(image,q) != 0) 3133 SetPixelAlpha(image,alpha,q); 3134 q+=GetPixelChannels(image); 3135 } 3136 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 3137 status=MagickFalse; 3138 } 3139 image_view=DestroyCacheView(image_view); 3140 return(status); 3141 } 3142 3143 /* 3145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3146 % % 3147 % % 3148 % % 3149 % S e t I m a g e V i r t u a l P i x e l M e t h o d % 3150 % % 3151 % % 3152 % % 3153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3154 % 3155 % SetImageVirtualPixelMethod() sets the "virtual pixels" method for the 3156 % image and returns the previous setting. A virtual pixel is any pixel access 3157 % that is outside the boundaries of the image cache. 3158 % 3159 % The format of the SetImageVirtualPixelMethod() method is: 3160 % 3161 % VirtualPixelMethod SetImageVirtualPixelMethod(Image *image, 3162 % const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception) 3163 % 3164 % A description of each parameter follows: 3165 % 3166 % o image: the image. 3167 % 3168 % o virtual_pixel_method: choose the type of virtual pixel. 3169 % 3170 % o exception: return any errors or warnings in this structure. 3171 % 3172 */ 3173 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(Image *image, 3174 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception) 3175 { 3176 assert(image != (const Image *) NULL); 3177 assert(image->signature == MagickCoreSignature); 3178 if (image->debug != MagickFalse) 3179 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 3180 return(SetPixelCacheVirtualMethod(image,virtual_pixel_method,exception)); 3181 } 3182 3183 /* 3185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3186 % % 3187 % % 3188 % % 3189 % S m u s h I m a g e s % 3190 % % 3191 % % 3192 % % 3193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3194 % 3195 % SmushImages() takes all images from the current image pointer to the end 3196 % of the image list and smushes them to each other top-to-bottom if the 3197 % stack parameter is true, otherwise left-to-right. 3198 % 3199 % The current gravity setting now effects how the image is justified in the 3200 % final image. 3201 % 3202 % The format of the SmushImages method is: 3203 % 3204 % Image *SmushImages(const Image *images,const MagickBooleanType stack, 3205 % ExceptionInfo *exception) 3206 % 3207 % A description of each parameter follows: 3208 % 3209 % o images: the image sequence. 3210 % 3211 % o stack: A value other than 0 stacks the images top-to-bottom. 3212 % 3213 % o offset: minimum distance in pixels between images. 3214 % 3215 % o exception: return any errors or warnings in this structure. 3216 % 3217 */ 3218 3219 static ssize_t SmushXGap(const Image *smush_image,const Image *images, 3220 const ssize_t offset,ExceptionInfo *exception) 3221 { 3222 CacheView 3223 *left_view, 3224 *right_view; 3225 3226 const Image 3227 *left_image, 3228 *right_image; 3229 3230 RectangleInfo 3231 left_geometry, 3232 right_geometry; 3233 3234 register const Quantum 3235 *p; 3236 3237 register ssize_t 3238 i, 3239 y; 3240 3241 size_t 3242 gap; 3243 3244 ssize_t 3245 x; 3246 3247 if (images->previous == (Image *) NULL) 3248 return(0); 3249 right_image=images; 3250 SetGeometry(smush_image,&right_geometry); 3251 GravityAdjustGeometry(right_image->columns,right_image->rows, 3252 right_image->gravity,&right_geometry); 3253 left_image=images->previous; 3254 SetGeometry(smush_image,&left_geometry); 3255 GravityAdjustGeometry(left_image->columns,left_image->rows, 3256 left_image->gravity,&left_geometry); 3257 gap=right_image->columns; 3258 left_view=AcquireVirtualCacheView(left_image,exception); 3259 right_view=AcquireVirtualCacheView(right_image,exception); 3260 for (y=0; y < (ssize_t) smush_image->rows; y++) 3261 { 3262 for (x=(ssize_t) left_image->columns-1; x > 0; x--) 3263 { 3264 p=GetCacheViewVirtualPixels(left_view,x,left_geometry.y+y,1,1,exception); 3265 if ((p == (const Quantum *) NULL) || 3266 (GetPixelAlpha(left_image,p) != TransparentAlpha) || 3267 ((left_image->columns-x-1) >= gap)) 3268 break; 3269 } 3270 i=(ssize_t) left_image->columns-x-1; 3271 for (x=0; x < (ssize_t) right_image->columns; x++) 3272 { 3273 p=GetCacheViewVirtualPixels(right_view,x,right_geometry.y+y,1,1, 3274 exception); 3275 if ((p == (const Quantum *) NULL) || 3276 (GetPixelAlpha(right_image,p) != TransparentAlpha) || 3277 ((x+i) >= (ssize_t) gap)) 3278 break; 3279 } 3280 if ((x+i) < (ssize_t) gap) 3281 gap=(size_t) (x+i); 3282 } 3283 right_view=DestroyCacheView(right_view); 3284 left_view=DestroyCacheView(left_view); 3285 if (y < (ssize_t) smush_image->rows) 3286 return(offset); 3287 return((ssize_t) gap-offset); 3288 } 3289 3290 static ssize_t SmushYGap(const Image *smush_image,const Image *images, 3291 const ssize_t offset,ExceptionInfo *exception) 3292 { 3293 CacheView 3294 *bottom_view, 3295 *top_view; 3296 3297 const Image 3298 *bottom_image, 3299 *top_image; 3300 3301 RectangleInfo 3302 bottom_geometry, 3303 top_geometry; 3304 3305 register const Quantum 3306 *p; 3307 3308 register ssize_t 3309 i, 3310 x; 3311 3312 size_t 3313 gap; 3314 3315 ssize_t 3316 y; 3317 3318 if (images->previous == (Image *) NULL) 3319 return(0); 3320 bottom_image=images; 3321 SetGeometry(smush_image,&bottom_geometry); 3322 GravityAdjustGeometry(bottom_image->columns,bottom_image->rows, 3323 bottom_image->gravity,&bottom_geometry); 3324 top_image=images->previous; 3325 SetGeometry(smush_image,&top_geometry); 3326 GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity, 3327 &top_geometry); 3328 gap=bottom_image->rows; 3329 top_view=AcquireVirtualCacheView(top_image,exception); 3330 bottom_view=AcquireVirtualCacheView(bottom_image,exception); 3331 for (x=0; x < (ssize_t) smush_image->columns; x++) 3332 { 3333 for (y=(ssize_t) top_image->rows-1; y > 0; y--) 3334 { 3335 p=GetCacheViewVirtualPixels(top_view,top_geometry.x+x,y,1,1,exception); 3336 if ((p == (const Quantum *) NULL) || 3337 (GetPixelAlpha(top_image,p) != TransparentAlpha) || 3338 ((top_image->rows-y-1) >= gap)) 3339 break; 3340 } 3341 i=(ssize_t) top_image->rows-y-1; 3342 for (y=0; y < (ssize_t) bottom_image->rows; y++) 3343 { 3344 p=GetCacheViewVirtualPixels(bottom_view,bottom_geometry.x+x,y,1,1, 3345 exception); 3346 if ((p == (const Quantum *) NULL) || 3347 (GetPixelAlpha(bottom_image,p) != TransparentAlpha) || 3348 ((y+i) >= (ssize_t) gap)) 3349 break; 3350 } 3351 if ((y+i) < (ssize_t) gap) 3352 gap=(size_t) (y+i); 3353 } 3354 bottom_view=DestroyCacheView(bottom_view); 3355 top_view=DestroyCacheView(top_view); 3356 if (x < (ssize_t) smush_image->columns) 3357 return(offset); 3358 return((ssize_t) gap-offset); 3359 } 3360 3361 MagickExport Image *SmushImages(const Image *images, 3362 const MagickBooleanType stack,const ssize_t offset,ExceptionInfo *exception) 3363 { 3364 #define SmushImageTag "Smush/Image" 3365 3366 const Image 3367 *image; 3368 3369 Image 3370 *smush_image; 3371 3372 MagickBooleanType 3373 proceed, 3374 status; 3375 3376 MagickOffsetType 3377 n; 3378 3379 PixelTrait 3380 alpha_trait; 3381 3382 RectangleInfo 3383 geometry; 3384 3385 register const Image 3386 *next; 3387 3388 size_t 3389 height, 3390 number_images, 3391 width; 3392 3393 ssize_t 3394 x_offset, 3395 y_offset; 3396 3397 /* 3398 Compute maximum area of smushed area. 3399 */ 3400 assert(images != (Image *) NULL); 3401 assert(images->signature == MagickCoreSignature); 3402 if (images->debug != MagickFalse) 3403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 3404 assert(exception != (ExceptionInfo *) NULL); 3405 assert(exception->signature == MagickCoreSignature); 3406 image=images; 3407 alpha_trait=image->alpha_trait; 3408 number_images=1; 3409 width=image->columns; 3410 height=image->rows; 3411 next=GetNextImageInList(image); 3412 for ( ; next != (Image *) NULL; next=GetNextImageInList(next)) 3413 { 3414 if (next->alpha_trait != UndefinedPixelTrait) 3415 alpha_trait=BlendPixelTrait; 3416 number_images++; 3417 if (stack != MagickFalse) 3418 { 3419 if (next->columns > width) 3420 width=next->columns; 3421 height+=next->rows; 3422 if (next->previous != (Image *) NULL) 3423 height+=offset; 3424 continue; 3425 } 3426 width+=next->columns; 3427 if (next->previous != (Image *) NULL) 3428 width+=offset; 3429 if (next->rows > height) 3430 height=next->rows; 3431 } 3432 /* 3433 Smush images. 3434 */ 3435 smush_image=CloneImage(image,width,height,MagickTrue,exception); 3436 if (smush_image == (Image *) NULL) 3437 return((Image *) NULL); 3438 if (SetImageStorageClass(smush_image,DirectClass,exception) == MagickFalse) 3439 { 3440 smush_image=DestroyImage(smush_image); 3441 return((Image *) NULL); 3442 } 3443 smush_image->alpha_trait=alpha_trait; 3444 (void) SetImageBackgroundColor(smush_image,exception); 3445 status=MagickTrue; 3446 x_offset=0; 3447 y_offset=0; 3448 for (n=0; n < (MagickOffsetType) number_images; n++) 3449 { 3450 SetGeometry(smush_image,&geometry); 3451 GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry); 3452 if (stack != MagickFalse) 3453 { 3454 x_offset-=geometry.x; 3455 y_offset-=SmushYGap(smush_image,image,offset,exception); 3456 } 3457 else 3458 { 3459 x_offset-=SmushXGap(smush_image,image,offset,exception); 3460 y_offset-=geometry.y; 3461 } 3462 status=CompositeImage(smush_image,image,OverCompositeOp,MagickTrue,x_offset, 3463 y_offset,exception); 3464 proceed=SetImageProgress(image,SmushImageTag,n,number_images); 3465 if (proceed == MagickFalse) 3466 break; 3467 if (stack == MagickFalse) 3468 { 3469 x_offset+=(ssize_t) image->columns; 3470 y_offset=0; 3471 } 3472 else 3473 { 3474 x_offset=0; 3475 y_offset+=(ssize_t) image->rows; 3476 } 3477 image=GetNextImageInList(image); 3478 } 3479 if (stack == MagickFalse) 3480 smush_image->columns=(size_t) x_offset; 3481 else 3482 smush_image->rows=(size_t) y_offset; 3483 if (status == MagickFalse) 3484 smush_image=DestroyImage(smush_image); 3485 return(smush_image); 3486 } 3487 3488 /* 3490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3491 % % 3492 % % 3493 % % 3494 % S t r i p I m a g e % 3495 % % 3496 % % 3497 % % 3498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3499 % 3500 % StripImage() strips an image of all profiles and comments. 3501 % 3502 % The format of the StripImage method is: 3503 % 3504 % MagickBooleanType StripImage(Image *image,ExceptionInfo *exception) 3505 % 3506 % A description of each parameter follows: 3507 % 3508 % o image: the image. 3509 % 3510 % o exception: return any errors or warnings in this structure. 3511 % 3512 */ 3513 MagickExport MagickBooleanType StripImage(Image *image,ExceptionInfo *exception) 3514 { 3515 MagickBooleanType 3516 status; 3517 3518 assert(image != (Image *) NULL); 3519 if (image->debug != MagickFalse) 3520 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 3521 (void) exception; 3522 DestroyImageProfiles(image); 3523 (void) DeleteImageProperty(image,"comment"); 3524 (void) DeleteImageProperty(image,"date:create"); 3525 (void) DeleteImageProperty(image,"date:modify"); 3526 status=SetImageArtifact(image,"png:exclude-chunk", 3527 "bKGD,cHRM,EXIF,gAMA,iCCP,iTXt,sRGB,tEXt,zCCP,zTXt,date"); 3528 return(status); 3529 } 3530 3531 /* 3533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3534 % % 3535 % % 3536 % % 3537 + S y n c I m a g e % 3538 % % 3539 % % 3540 % % 3541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3542 % 3543 % SyncImage() initializes the red, green, and blue intensities of each pixel 3544 % as defined by the colormap index. 3545 % 3546 % The format of the SyncImage method is: 3547 % 3548 % MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception) 3549 % 3550 % A description of each parameter follows: 3551 % 3552 % o image: the image. 3553 % 3554 % o exception: return any errors or warnings in this structure. 3555 % 3556 */ 3557 3558 static inline Quantum PushColormapIndex(Image *image,const Quantum index, 3559 MagickBooleanType *range_exception) 3560 { 3561 if ((size_t) index < image->colors) 3562 return(index); 3563 *range_exception=MagickTrue; 3564 return((Quantum) 0); 3565 } 3566 3567 MagickExport MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception) 3568 { 3569 CacheView 3570 *image_view; 3571 3572 MagickBooleanType 3573 range_exception, 3574 status, 3575 taint; 3576 3577 ssize_t 3578 y; 3579 3580 assert(image != (Image *) NULL); 3581 if (image->debug != MagickFalse) 3582 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 3583 assert(image->signature == MagickCoreSignature); 3584 if (image->storage_class == DirectClass) 3585 return(MagickFalse); 3586 range_exception=MagickFalse; 3587 status=MagickTrue; 3588 taint=image->taint; 3589 image_view=AcquireAuthenticCacheView(image,exception); 3590 #if defined(MAGICKCORE_OPENMP_SUPPORT) 3591 #pragma omp parallel for schedule(static,4) shared(range_exception,status) \ 3592 magick_threads(image,image,image->rows,1) 3593 #endif 3594 for (y=0; y < (ssize_t) image->rows; y++) 3595 { 3596 Quantum 3597 index; 3598 3599 register Quantum 3600 *magick_restrict q; 3601 3602 register ssize_t 3603 x; 3604 3605 if (status == MagickFalse) 3606 continue; 3607 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 3608 if (q == (Quantum *) NULL) 3609 { 3610 status=MagickFalse; 3611 continue; 3612 } 3613 for (x=0; x < (ssize_t) image->columns; x++) 3614 { 3615 index=PushColormapIndex(image,GetPixelIndex(image,q),&range_exception); 3616 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q); 3617 q+=GetPixelChannels(image); 3618 } 3619 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 3620 status=MagickFalse; 3621 } 3622 image_view=DestroyCacheView(image_view); 3623 image->taint=taint; 3624 if ((image->ping == MagickFalse) && (range_exception != MagickFalse)) 3625 (void) ThrowMagickException(exception,GetMagickModule(), 3626 CorruptImageWarning,"InvalidColormapIndex","`%s'",image->filename); 3627 return(status); 3628 } 3629 3630 /* 3632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3633 % % 3634 % % 3635 % % 3636 % S y n c I m a g e S e t t i n g s % 3637 % % 3638 % % 3639 % % 3640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3641 % 3642 % SyncImageSettings() syncs any image_info global options into per-image 3643 % attributes. 3644 % 3645 % Note: in IMv6 free form 'options' were always mapped into 'artifacts', so 3646 % that operations and coders can find such settings. In IMv7 if a desired 3647 % per-image artifact is not set, then it will directly look for a global 3648 % option as a fallback, as such this copy is no longer needed, only the 3649 % link set up. 3650 % 3651 % The format of the SyncImageSettings method is: 3652 % 3653 % MagickBooleanType SyncImageSettings(const ImageInfo *image_info, 3654 % Image *image,ExceptionInfo *exception) 3655 % MagickBooleanType SyncImagesSettings(const ImageInfo *image_info, 3656 % Image *image,ExceptionInfo *exception) 3657 % 3658 % A description of each parameter follows: 3659 % 3660 % o image_info: the image info. 3661 % 3662 % o image: the image. 3663 % 3664 % o exception: return any errors or warnings in this structure. 3665 % 3666 */ 3667 3668 MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info, 3669 Image *images,ExceptionInfo *exception) 3670 { 3671 Image 3672 *image; 3673 3674 assert(image_info != (const ImageInfo *) NULL); 3675 assert(image_info->signature == MagickCoreSignature); 3676 assert(images != (Image *) NULL); 3677 assert(images->signature == MagickCoreSignature); 3678 if (images->debug != MagickFalse) 3679 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 3680 image=images; 3681 for ( ; image != (Image *) NULL; image=GetNextImageInList(image)) 3682 (void) SyncImageSettings(image_info,image,exception); 3683 (void) DeleteImageOption(image_info,"page"); 3684 return(MagickTrue); 3685 } 3686 3687 MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info, 3688 Image *image,ExceptionInfo *exception) 3689 { 3690 const char 3691 *option; 3692 3693 GeometryInfo 3694 geometry_info; 3695 3696 MagickStatusType 3697 flags; 3698 3699 ResolutionType 3700 units; 3701 3702 /* 3703 Sync image options. 3704 */ 3705 assert(image_info != (const ImageInfo *) NULL); 3706 assert(image_info->signature == MagickCoreSignature); 3707 assert(image != (Image *) NULL); 3708 assert(image->signature == MagickCoreSignature); 3709 if (image->debug != MagickFalse) 3710 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 3711 option=GetImageOption(image_info,"alpha-color"); 3712 if (option != (const char *) NULL) 3713 (void) QueryColorCompliance(option,AllCompliance,&image->alpha_color, 3714 exception); 3715 option=GetImageOption(image_info,"background"); 3716 if (option != (const char *) NULL) 3717 (void) QueryColorCompliance(option,AllCompliance,&image->background_color, 3718 exception); 3719 option=GetImageOption(image_info,"black-point-compensation"); 3720 if (option != (const char *) NULL) 3721 image->black_point_compensation=(MagickBooleanType) ParseCommandOption( 3722 MagickBooleanOptions,MagickFalse,option); 3723 option=GetImageOption(image_info,"blue-primary"); 3724 if (option != (const char *) NULL) 3725 { 3726 flags=ParseGeometry(option,&geometry_info); 3727 image->chromaticity.blue_primary.x=geometry_info.rho; 3728 image->chromaticity.blue_primary.y=geometry_info.sigma; 3729 if ((flags & SigmaValue) == 0) 3730 image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x; 3731 } 3732 option=GetImageOption(image_info,"bordercolor"); 3733 if (option != (const char *) NULL) 3734 (void) QueryColorCompliance(option,AllCompliance,&image->border_color, 3735 exception); 3736 /* FUTURE: do not sync compose to per-image compose setting here */ 3737 option=GetImageOption(image_info,"compose"); 3738 if (option != (const char *) NULL) 3739 image->compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions, 3740 MagickFalse,option); 3741 /* -- */ 3742 option=GetImageOption(image_info,"compress"); 3743 if (option != (const char *) NULL) 3744 image->compression=(CompressionType) ParseCommandOption( 3745 MagickCompressOptions,MagickFalse,option); 3746 option=GetImageOption(image_info,"debug"); 3747 if (option != (const char *) NULL) 3748 image->debug=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions, 3749 MagickFalse,option); 3750 option=GetImageOption(image_info,"density"); 3751 if (option != (const char *) NULL) 3752 { 3753 GeometryInfo 3754 geometry_info; 3755 3756 flags=ParseGeometry(option,&geometry_info); 3757 image->resolution.x=geometry_info.rho; 3758 image->resolution.y=geometry_info.sigma; 3759 if ((flags & SigmaValue) == 0) 3760 image->resolution.y=image->resolution.x; 3761 } 3762 option=GetImageOption(image_info,"depth"); 3763 if (option != (const char *) NULL) 3764 image->depth=StringToUnsignedLong(option); 3765 option=GetImageOption(image_info,"endian"); 3766 if (option != (const char *) NULL) 3767 image->endian=(EndianType) ParseCommandOption(MagickEndianOptions, 3768 MagickFalse,option); 3769 option=GetImageOption(image_info,"filter"); 3770 if (option != (const char *) NULL) 3771 image->filter=(FilterType) ParseCommandOption(MagickFilterOptions, 3772 MagickFalse,option); 3773 option=GetImageOption(image_info,"fuzz"); 3774 if (option != (const char *) NULL) 3775 image->fuzz=StringToDoubleInterval(option,(double) QuantumRange+1.0); 3776 option=GetImageOption(image_info,"gravity"); 3777 if (option != (const char *) NULL) 3778 image->gravity=(GravityType) ParseCommandOption(MagickGravityOptions, 3779 MagickFalse,option); 3780 option=GetImageOption(image_info,"green-primary"); 3781 if (option != (const char *) NULL) 3782 { 3783 flags=ParseGeometry(option,&geometry_info); 3784 image->chromaticity.green_primary.x=geometry_info.rho; 3785 image->chromaticity.green_primary.y=geometry_info.sigma; 3786 if ((flags & SigmaValue) == 0) 3787 image->chromaticity.green_primary.y=image->chromaticity.green_primary.x; 3788 } 3789 option=GetImageOption(image_info,"intent"); 3790 if (option != (const char *) NULL) 3791 image->rendering_intent=(RenderingIntent) ParseCommandOption( 3792 MagickIntentOptions,MagickFalse,option); 3793 option=GetImageOption(image_info,"intensity"); 3794 if (option != (const char *) NULL) 3795 image->intensity=(PixelIntensityMethod) ParseCommandOption( 3796 MagickPixelIntensityOptions,MagickFalse,option); 3797 option=GetImageOption(image_info,"interlace"); 3798 if (option != (const char *) NULL) 3799 image->interlace=(InterlaceType) ParseCommandOption(MagickInterlaceOptions, 3800 MagickFalse,option); 3801 option=GetImageOption(image_info,"interpolate"); 3802 if (option != (const char *) NULL) 3803 image->interpolate=(PixelInterpolateMethod) ParseCommandOption( 3804 MagickInterpolateOptions,MagickFalse,option); 3805 option=GetImageOption(image_info,"loop"); 3806 if (option != (const char *) NULL) 3807 image->iterations=StringToUnsignedLong(option); 3808 option=GetImageOption(image_info,"orient"); 3809 if (option != (const char *) NULL) 3810 image->orientation=(OrientationType) ParseCommandOption( 3811 MagickOrientationOptions,MagickFalse,option); 3812 option=GetImageOption(image_info,"page"); 3813 if (option != (const char *) NULL) 3814 { 3815 char 3816 *geometry; 3817 3818 geometry=GetPageGeometry(option); 3819 flags=ParseAbsoluteGeometry(geometry,&image->page); 3820 geometry=DestroyString(geometry); 3821 } 3822 option=GetImageOption(image_info,"quality"); 3823 if (option != (const char *) NULL) 3824 image->quality=StringToUnsignedLong(option); 3825 option=GetImageOption(image_info,"red-primary"); 3826 if (option != (const char *) NULL) 3827 { 3828 flags=ParseGeometry(option,&geometry_info); 3829 image->chromaticity.red_primary.x=geometry_info.rho; 3830 image->chromaticity.red_primary.y=geometry_info.sigma; 3831 if ((flags & SigmaValue) == 0) 3832 image->chromaticity.red_primary.y=image->chromaticity.red_primary.x; 3833 } 3834 if (image_info->quality != UndefinedCompressionQuality) 3835 image->quality=image_info->quality; 3836 option=GetImageOption(image_info,"scene"); 3837 if (option != (const char *) NULL) 3838 image->scene=StringToUnsignedLong(option); 3839 option=GetImageOption(image_info,"taint"); 3840 if (option != (const char *) NULL) 3841 image->taint=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions, 3842 MagickFalse,option); 3843 option=GetImageOption(image_info,"tile-offset"); 3844 if (option != (const char *) NULL) 3845 { 3846 char 3847 *geometry; 3848 3849 geometry=GetPageGeometry(option); 3850 flags=ParseAbsoluteGeometry(geometry,&image->tile_offset); 3851 geometry=DestroyString(geometry); 3852 } 3853 option=GetImageOption(image_info,"transparent-color"); 3854 if (option != (const char *) NULL) 3855 (void) QueryColorCompliance(option,AllCompliance,&image->transparent_color, 3856 exception); 3857 option=GetImageOption(image_info,"type"); 3858 if (option != (const char *) NULL) 3859 image->type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse, 3860 option); 3861 option=GetImageOption(image_info,"units"); 3862 units=image_info->units; 3863 if (option != (const char *) NULL) 3864 units=(ResolutionType) ParseCommandOption(MagickResolutionOptions, 3865 MagickFalse,option); 3866 if (units != UndefinedResolution) 3867 { 3868 if (image->units != units) 3869 switch (image->units) 3870 { 3871 case PixelsPerInchResolution: 3872 { 3873 if (units == PixelsPerCentimeterResolution) 3874 { 3875 image->resolution.x/=2.54; 3876 image->resolution.y/=2.54; 3877 } 3878 break; 3879 } 3880 case PixelsPerCentimeterResolution: 3881 { 3882 if (units == PixelsPerInchResolution) 3883 { 3884 image->resolution.x=(double) ((size_t) (100.0*2.54* 3885 image->resolution.x+0.5))/100.0; 3886 image->resolution.y=(double) ((size_t) (100.0*2.54* 3887 image->resolution.y+0.5))/100.0; 3888 } 3889 break; 3890 } 3891 default: 3892 break; 3893 } 3894 image->units=units; 3895 } 3896 option=GetImageOption(image_info,"virtual-pixel"); 3897 if (option != (const char *) NULL) 3898 (void) SetImageVirtualPixelMethod(image,(VirtualPixelMethod) 3899 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,option), 3900 exception); 3901 option=GetImageOption(image_info,"white-point"); 3902 if (option != (const char *) NULL) 3903 { 3904 flags=ParseGeometry(option,&geometry_info); 3905 image->chromaticity.white_point.x=geometry_info.rho; 3906 image->chromaticity.white_point.y=geometry_info.sigma; 3907 if ((flags & SigmaValue) == 0) 3908 image->chromaticity.white_point.y=image->chromaticity.white_point.x; 3909 } 3910 /* 3911 Pointer to allow the lookup of pre-image artifact will fallback to a global 3912 option setting/define. This saves a lot of duplication of global options 3913 into per-image artifacts, while ensuring only specifically set per-image 3914 artifacts are preserved when parenthesis ends. 3915 */ 3916 if (image->image_info != (ImageInfo *) NULL) 3917 image->image_info=DestroyImageInfo(image->image_info); 3918 image->image_info=CloneImageInfo(image_info); 3919 return(MagickTrue); 3920 } 3921