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