1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % IIIII M M AAA GGGG EEEEE % 6 % I MM MM A A G E % 7 % I M M M AAAAA G GG EEE % 8 % I M M A A G G E % 9 % IIIII M M A A GGGG EEEEE % 10 % % 11 % V V IIIII EEEEE W W % 12 % V V I E W W % 13 % V V I EEE W W W % 14 % V V I E WW WW % 15 % V IIIII EEEEE W W % 16 % % 17 % % 18 % MagickCore Image View Methods % 19 % % 20 % Software Design % 21 % Cristy % 22 % March 2003 % 23 % % 24 % % 25 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 26 % dedicated to making software imaging solutions freely available. % 27 % % 28 % You may not use this file except in compliance with the License. You may % 29 % obtain a copy of the License at % 30 % % 31 % http://www.imagemagick.org/script/license.php % 32 % % 33 % Unless required by applicable law or agreed to in writing, software % 34 % distributed under the License is distributed on an "AS IS" BASIS, % 35 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 36 % See the License for the specific language governing permissions and % 37 % limitations under the License. % 38 % % 39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 40 % 41 % 42 % 43 */ 44 45 /* 47 Include declarations. 48 */ 49 #include "MagickCore/studio.h" 50 #include "MagickCore/MagickCore.h" 51 #include "MagickCore/exception-private.h" 52 #include "MagickCore/monitor-private.h" 53 #include "MagickCore/thread-private.h" 54 55 /* 57 Typedef declarations. 58 */ 59 struct _ImageView 60 { 61 char 62 *description; 63 64 RectangleInfo 65 extent; 66 67 Image 68 *image; 69 70 CacheView 71 *view; 72 73 ExceptionInfo 74 *exception; 75 76 MagickBooleanType 77 debug; 78 79 size_t 80 signature; 81 }; 82 83 /* 85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 % % 87 % % 88 % % 89 % C l o n e I m a g e V i e w % 90 % % 91 % % 92 % % 93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 94 % 95 % CloneImageView() makes a copy of the specified image view. 96 % 97 % The format of the CloneImageView method is: 98 % 99 % ImageView *CloneImageView(const ImageView *image_view) 100 % 101 % A description of each parameter follows: 102 % 103 % o image_view: the image view. 104 % 105 */ 106 MagickExport ImageView *CloneImageView(const ImageView *image_view) 107 { 108 ImageView 109 *clone_view; 110 111 assert(image_view != (ImageView *) NULL); 112 assert(image_view->signature == MagickCoreSignature); 113 clone_view=(ImageView *) AcquireMagickMemory(sizeof(*clone_view)); 114 if (clone_view == (ImageView *) NULL) 115 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 116 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view)); 117 clone_view->description=ConstantString(image_view->description); 118 clone_view->extent=image_view->extent; 119 clone_view->view=CloneCacheView(image_view->view); 120 clone_view->exception=AcquireExceptionInfo(); 121 InheritException(clone_view->exception,image_view->exception); 122 clone_view->debug=image_view->debug; 123 clone_view->signature=MagickCoreSignature; 124 return(clone_view); 125 } 126 127 /* 129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 130 % % 131 % % 132 % % 133 % D e s t r o y I m a g e V i e w % 134 % % 135 % % 136 % % 137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 138 % 139 % DestroyImageView() deallocates memory associated with a image view. 140 % 141 % The format of the DestroyImageView method is: 142 % 143 % ImageView *DestroyImageView(ImageView *image_view) 144 % 145 % A description of each parameter follows: 146 % 147 % o image_view: the image view. 148 % 149 */ 150 MagickExport ImageView *DestroyImageView(ImageView *image_view) 151 { 152 assert(image_view != (ImageView *) NULL); 153 assert(image_view->signature == MagickCoreSignature); 154 if (image_view->description != (char *) NULL) 155 image_view->description=DestroyString(image_view->description); 156 image_view->view=DestroyCacheView(image_view->view); 157 image_view->exception=DestroyExceptionInfo(image_view->exception); 158 image_view->signature=(~MagickCoreSignature); 159 image_view=(ImageView *) RelinquishMagickMemory(image_view); 160 return(image_view); 161 } 162 163 /* 165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 166 % % 167 % % 168 % % 169 % D u p l e x T r a n s f e r I m a g e V i e w I t e r a t o r % 170 % % 171 % % 172 % % 173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 174 % 175 % DuplexTransferImageViewIterator() iterates over three image views in 176 % parallel and calls your transfer method for each scanline of the view. The 177 % source and duplex pixel extent is not confined to the image canvas-- that is 178 % you can include negative offsets or widths or heights that exceed the image 179 % dimension. However, the destination image view is confined to the image 180 % canvas-- that is no negative offsets or widths or heights that exceed the 181 % image dimension are permitted. 182 % 183 % The callback signature is: 184 % 185 % MagickBooleanType DuplexTransferImageViewMethod(const ImageView *source, 186 % const ImageView *duplex,ImageView *destination,const ssize_t y, 187 % const int thread_id,void *context) 188 % 189 % Use this pragma if the view is not single threaded: 190 % 191 % #pragma omp critical 192 % 193 % to define a section of code in your callback transfer method that must be 194 % executed by a single thread at a time. 195 % 196 % The format of the DuplexTransferImageViewIterator method is: 197 % 198 % MagickBooleanType DuplexTransferImageViewIterator(ImageView *source, 199 % ImageView *duplex,ImageView *destination, 200 % DuplexTransferImageViewMethod transfer,void *context) 201 % 202 % A description of each parameter follows: 203 % 204 % o source: the source image view. 205 % 206 % o duplex: the duplex image view. 207 % 208 % o destination: the destination image view. 209 % 210 % o transfer: the transfer callback method. 211 % 212 % o context: the user defined context. 213 % 214 */ 215 MagickExport MagickBooleanType DuplexTransferImageViewIterator( 216 ImageView *source,ImageView *duplex,ImageView *destination, 217 DuplexTransferImageViewMethod transfer,void *context) 218 { 219 Image 220 *destination_image, 221 *source_image; 222 223 MagickBooleanType 224 status; 225 226 MagickOffsetType 227 progress; 228 229 #if defined(MAGICKCORE_OPENMP_SUPPORT) 230 size_t 231 height; 232 #endif 233 234 ssize_t 235 y; 236 237 assert(source != (ImageView *) NULL); 238 assert(source->signature == MagickCoreSignature); 239 if (transfer == (DuplexTransferImageViewMethod) NULL) 240 return(MagickFalse); 241 source_image=source->image; 242 destination_image=destination->image; 243 status=SetImageStorageClass(destination_image,DirectClass, 244 destination->exception); 245 if (status == MagickFalse) 246 return(MagickFalse); 247 status=MagickTrue; 248 progress=0; 249 #if defined(MAGICKCORE_OPENMP_SUPPORT) 250 height=source->extent.height-source->extent.y; 251 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 252 magick_threads(source_image,destination_image,height,1) 253 #endif 254 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 255 { 256 const int 257 id = GetOpenMPThreadId(); 258 259 MagickBooleanType 260 sync; 261 262 register const Quantum 263 *magick_restrict duplex_pixels, 264 *magick_restrict pixels; 265 266 register Quantum 267 *magick_restrict destination_pixels; 268 269 if (status == MagickFalse) 270 continue; 271 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y, 272 source->extent.width,1,source->exception); 273 if (pixels == (const Quantum *) NULL) 274 { 275 status=MagickFalse; 276 continue; 277 } 278 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y, 279 duplex->extent.width,1,duplex->exception); 280 if (duplex_pixels == (const Quantum *) NULL) 281 { 282 status=MagickFalse; 283 continue; 284 } 285 destination_pixels=GetCacheViewAuthenticPixels(destination->view, 286 destination->extent.x,y,destination->extent.width,1, 287 destination->exception); 288 if (destination_pixels == (Quantum *) NULL) 289 { 290 status=MagickFalse; 291 continue; 292 } 293 if (transfer(source,duplex,destination,y,id,context) == MagickFalse) 294 status=MagickFalse; 295 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception); 296 if (sync == MagickFalse) 297 status=MagickFalse; 298 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 299 { 300 MagickBooleanType 301 proceed; 302 303 #if defined(MAGICKCORE_OPENMP_SUPPORT) 304 #pragma omp critical (MagickCore_DuplexTransferImageViewIterator) 305 #endif 306 proceed=SetImageProgress(source_image,source->description,progress++, 307 source->extent.height); 308 if (proceed == MagickFalse) 309 status=MagickFalse; 310 } 311 } 312 return(status); 313 } 314 315 /* 317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 318 % % 319 % % 320 % % 321 % G e t I m a g e V i e w A u t h e n t i c M e t a c o n t e n t % 322 % % 323 % % 324 % % 325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 326 % 327 % GetImageViewAuthenticMetacontent() returns the image view authentic 328 % meta-content. 329 % 330 % The format of the GetImageViewAuthenticPixels method is: 331 % 332 % void *GetImageViewAuthenticMetacontent( 333 % const ImageView *image_view) 334 % 335 % A description of each parameter follows: 336 % 337 % o image_view: the image view. 338 % 339 */ 340 MagickExport void *GetImageViewAuthenticMetacontent( 341 const ImageView *image_view) 342 { 343 assert(image_view != (ImageView *) NULL); 344 assert(image_view->signature == MagickCoreSignature); 345 return(GetCacheViewAuthenticMetacontent(image_view->view)); 346 } 347 348 /* 350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 351 % % 352 % % 353 % % 354 % G e t I m a g e V i e w A u t h e n t i c P i x e l s % 355 % % 356 % % 357 % % 358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 359 % 360 % GetImageViewAuthenticPixels() returns the image view authentic pixels. 361 % 362 % The format of the GetImageViewAuthenticPixels method is: 363 % 364 % Quantum *GetImageViewAuthenticPixels(const ImageView *image_view) 365 % 366 % A description of each parameter follows: 367 % 368 % o image_view: the image view. 369 % 370 */ 371 MagickExport Quantum *GetImageViewAuthenticPixels( 372 const ImageView *image_view) 373 { 374 assert(image_view != (ImageView *) NULL); 375 assert(image_view->signature == MagickCoreSignature); 376 return(GetCacheViewAuthenticPixelQueue(image_view->view)); 377 } 378 379 /* 381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 382 % % 383 % % 384 % % 385 % G e t I m a g e V i e w E x c e p t i o n % 386 % % 387 % % 388 % % 389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 390 % 391 % GetImageViewException() returns the severity, reason, and description of any 392 % error that occurs when utilizing a image view. 393 % 394 % The format of the GetImageViewException method is: 395 % 396 % char *GetImageViewException(const PixelImage *image_view, 397 % ExceptionType *severity) 398 % 399 % A description of each parameter follows: 400 % 401 % o image_view: the pixel image_view. 402 % 403 % o severity: the severity of the error is returned here. 404 % 405 */ 406 MagickExport char *GetImageViewException(const ImageView *image_view, 407 ExceptionType *severity) 408 { 409 char 410 *description; 411 412 assert(image_view != (const ImageView *) NULL); 413 assert(image_view->signature == MagickCoreSignature); 414 assert(severity != (ExceptionType *) NULL); 415 *severity=image_view->exception->severity; 416 description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent, 417 sizeof(*description)); 418 if (description == (char *) NULL) 419 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 420 *description='\0'; 421 if (image_view->exception->reason != (char *) NULL) 422 (void) CopyMagickString(description,GetLocaleExceptionMessage( 423 image_view->exception->severity,image_view->exception->reason), 424 MagickPathExtent); 425 if (image_view->exception->description != (char *) NULL) 426 { 427 (void) ConcatenateMagickString(description," (",MagickPathExtent); 428 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage( 429 image_view->exception->severity,image_view->exception->description), 430 MagickPathExtent); 431 (void) ConcatenateMagickString(description,")",MagickPathExtent); 432 } 433 return(description); 434 } 435 436 /* 438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 439 % % 440 % % 441 % % 442 % G e t I m a g e V i e w E x t e n t % 443 % % 444 % % 445 % % 446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 447 % 448 % GetImageViewExtent() returns the image view extent. 449 % 450 % The format of the GetImageViewExtent method is: 451 % 452 % RectangleInfo GetImageViewExtent(const ImageView *image_view) 453 % 454 % A description of each parameter follows: 455 % 456 % o image_view: the image view. 457 % 458 */ 459 MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view) 460 { 461 assert(image_view != (ImageView *) NULL); 462 assert(image_view->signature == MagickCoreSignature); 463 return(image_view->extent); 464 } 465 466 /* 468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 469 % % 470 % % 471 % % 472 % G e t I m a g e V i e w I m a g e % 473 % % 474 % % 475 % % 476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 477 % 478 % GetImageViewImage() returns the image associated with the image view. 479 % 480 % The format of the GetImageViewImage method is: 481 % 482 % MagickCore *GetImageViewImage(const ImageView *image_view) 483 % 484 % A description of each parameter follows: 485 % 486 % o image_view: the image view. 487 % 488 */ 489 MagickExport Image *GetImageViewImage(const ImageView *image_view) 490 { 491 assert(image_view != (ImageView *) NULL); 492 assert(image_view->signature == MagickCoreSignature); 493 return(image_view->image); 494 } 495 496 /* 498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 499 % % 500 % % 501 % % 502 % G e t I m a g e V i e w I t e r a t o r % 503 % % 504 % % 505 % % 506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 507 % 508 % GetImageViewIterator() iterates over the image view in parallel and calls 509 % your get method for each scanline of the view. The pixel extent is 510 % not confined to the image canvas-- that is you can include negative offsets 511 % or widths or heights that exceed the image dimension. Any updates to 512 % the pixels in your callback are ignored. 513 % 514 % The callback signature is: 515 % 516 % MagickBooleanType GetImageViewMethod(const ImageView *source, 517 % const ssize_t y,const int thread_id,void *context) 518 % 519 % Use this pragma if the view is not single threaded: 520 % 521 % #pragma omp critical 522 % 523 % to define a section of code in your callback get method that must be 524 % executed by a single thread at a time. 525 % 526 % The format of the GetImageViewIterator method is: 527 % 528 % MagickBooleanType GetImageViewIterator(ImageView *source, 529 % GetImageViewMethod get,void *context) 530 % 531 % A description of each parameter follows: 532 % 533 % o source: the source image view. 534 % 535 % o get: the get callback method. 536 % 537 % o context: the user defined context. 538 % 539 */ 540 MagickExport MagickBooleanType GetImageViewIterator(ImageView *source, 541 GetImageViewMethod get,void *context) 542 { 543 Image 544 *source_image; 545 546 MagickBooleanType 547 status; 548 549 MagickOffsetType 550 progress; 551 552 #if defined(MAGICKCORE_OPENMP_SUPPORT) 553 size_t 554 height; 555 #endif 556 557 ssize_t 558 y; 559 560 assert(source != (ImageView *) NULL); 561 assert(source->signature == MagickCoreSignature); 562 if (get == (GetImageViewMethod) NULL) 563 return(MagickFalse); 564 source_image=source->image; 565 status=MagickTrue; 566 progress=0; 567 #if defined(MAGICKCORE_OPENMP_SUPPORT) 568 height=source->extent.height-source->extent.y; 569 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 570 magick_threads(source_image,source_image,height,1) 571 #endif 572 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 573 { 574 const int 575 id = GetOpenMPThreadId(); 576 577 register const Quantum 578 *pixels; 579 580 if (status == MagickFalse) 581 continue; 582 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y, 583 source->extent.width,1,source->exception); 584 if (pixels == (const Quantum *) NULL) 585 { 586 status=MagickFalse; 587 continue; 588 } 589 if (get(source,y,id,context) == MagickFalse) 590 status=MagickFalse; 591 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 592 { 593 MagickBooleanType 594 proceed; 595 596 #if defined(MAGICKCORE_OPENMP_SUPPORT) 597 #pragma omp critical (MagickCore_GetImageViewIterator) 598 #endif 599 proceed=SetImageProgress(source_image,source->description,progress++, 600 source->extent.height); 601 if (proceed == MagickFalse) 602 status=MagickFalse; 603 } 604 } 605 return(status); 606 } 607 608 /* 610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 611 % % 612 % % 613 % % 614 % G e t I m a g e V i e w V i r t u a l M e t a c o n t e n t % 615 % % 616 % % 617 % % 618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 619 % 620 % GetImageViewVirtualMetacontent() returns the image view virtual 621 % meta-content. 622 % 623 % The format of the GetImageViewVirtualMetacontent method is: 624 % 625 % const void *GetImageViewVirtualMetacontent( 626 % const ImageView *image_view) 627 % 628 % A description of each parameter follows: 629 % 630 % o image_view: the image view. 631 % 632 */ 633 MagickExport const void *GetImageViewVirtualMetacontent( 634 const ImageView *image_view) 635 { 636 assert(image_view != (ImageView *) NULL); 637 assert(image_view->signature == MagickCoreSignature); 638 return(GetCacheViewVirtualMetacontent(image_view->view)); 639 } 640 641 /* 643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 644 % % 645 % % 646 % % 647 % G e t I m a g e V i e w V i r t u a l P i x e l s % 648 % % 649 % % 650 % % 651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 652 % 653 % GetImageViewVirtualPixels() returns the image view virtual pixels. 654 % 655 % The format of the GetImageViewVirtualPixels method is: 656 % 657 % const Quantum *GetImageViewVirtualPixels(const ImageView *image_view) 658 % 659 % A description of each parameter follows: 660 % 661 % o image_view: the image view. 662 % 663 */ 664 MagickExport const Quantum *GetImageViewVirtualPixels( 665 const ImageView *image_view) 666 { 667 assert(image_view != (ImageView *) NULL); 668 assert(image_view->signature == MagickCoreSignature); 669 return(GetCacheViewVirtualPixelQueue(image_view->view)); 670 } 671 672 /* 674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 675 % % 676 % % 677 % % 678 % I s I m a g e V i e w % 679 % % 680 % % 681 % % 682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 683 % 684 % IsImageView() returns MagickTrue if the the parameter is verified as a image 685 % view object. 686 % 687 % The format of the IsImageView method is: 688 % 689 % MagickBooleanType IsImageView(const ImageView *image_view) 690 % 691 % A description of each parameter follows: 692 % 693 % o image_view: the image view. 694 % 695 */ 696 MagickExport MagickBooleanType IsImageView(const ImageView *image_view) 697 { 698 if (image_view == (const ImageView *) NULL) 699 return(MagickFalse); 700 if (image_view->signature != MagickCoreSignature) 701 return(MagickFalse); 702 return(MagickTrue); 703 } 704 705 /* 707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 708 % % 709 % % 710 % % 711 % N e w I m a g e V i e w % 712 % % 713 % % 714 % % 715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 716 % 717 % NewImageView() returns a image view required for all other methods in the 718 % Image View API. 719 % 720 % The format of the NewImageView method is: 721 % 722 % ImageView *NewImageView(MagickCore *wand,ExceptionInfo *exception) 723 % 724 % A description of each parameter follows: 725 % 726 % o image: the image. 727 % 728 % o exception: return any errors or warnings in this structure. 729 % 730 */ 731 MagickExport ImageView *NewImageView(Image *image,ExceptionInfo *exception) 732 { 733 ImageView 734 *image_view; 735 736 assert(image != (Image *) NULL); 737 assert(image->signature == MagickCoreSignature); 738 image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view)); 739 if (image_view == (ImageView *) NULL) 740 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 741 (void) ResetMagickMemory(image_view,0,sizeof(*image_view)); 742 image_view->description=ConstantString("ImageView"); 743 image_view->image=image; 744 image_view->view=AcquireVirtualCacheView(image_view->image,exception); 745 image_view->extent.width=image->columns; 746 image_view->extent.height=image->rows; 747 image_view->extent.x=0; 748 image_view->extent.y=0; 749 image_view->exception=AcquireExceptionInfo(); 750 image_view->debug=IsEventLogging(); 751 image_view->signature=MagickCoreSignature; 752 return(image_view); 753 } 754 755 /* 757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 758 % % 759 % % 760 % % 761 % N e w I m a g e V i e w R e g i o n % 762 % % 763 % % 764 % % 765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 766 % 767 % NewImageViewRegion() returns a image view required for all other methods 768 % in the Image View API. 769 % 770 % The format of the NewImageViewRegion method is: 771 % 772 % ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x, 773 % const ssize_t y,const size_t width,const size_t height, 774 % ExceptionInfo *exception) 775 % 776 % A description of each parameter follows: 777 % 778 % o wand: the magick wand. 779 % 780 % o x,y,columns,rows: These values define the perimeter of a extent of 781 % pixel_wands view. 782 % 783 % o exception: return any errors or warnings in this structure. 784 % 785 */ 786 MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x, 787 const ssize_t y,const size_t width,const size_t height, 788 ExceptionInfo *exception) 789 { 790 ImageView 791 *image_view; 792 793 assert(image != (Image *) NULL); 794 assert(image->signature == MagickCoreSignature); 795 image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view)); 796 if (image_view == (ImageView *) NULL) 797 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 798 (void) ResetMagickMemory(image_view,0,sizeof(*image_view)); 799 image_view->description=ConstantString("ImageView"); 800 image_view->view=AcquireVirtualCacheView(image_view->image,exception); 801 image_view->image=image; 802 image_view->extent.width=width; 803 image_view->extent.height=height; 804 image_view->extent.x=x; 805 image_view->extent.y=y; 806 image_view->exception=AcquireExceptionInfo(); 807 image_view->debug=IsEventLogging(); 808 image_view->signature=MagickCoreSignature; 809 return(image_view); 810 } 811 812 /* 814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 815 % % 816 % % 817 % % 818 % S e t I m a g e V i e w D e s c r i p t i o n % 819 % % 820 % % 821 % % 822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 823 % 824 % SetImageViewDescription() associates a description with an image view. 825 % 826 % The format of the SetImageViewDescription method is: 827 % 828 % void SetImageViewDescription(ImageView *image_view, 829 % const char *description) 830 % 831 % A description of each parameter follows: 832 % 833 % o image_view: the image view. 834 % 835 % o description: the image view description. 836 % 837 */ 838 MagickExport void SetImageViewDescription(ImageView *image_view, 839 const char *description) 840 { 841 assert(image_view != (ImageView *) NULL); 842 assert(image_view->signature == MagickCoreSignature); 843 image_view->description=ConstantString(description); 844 } 845 846 /* 848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 849 % % 850 % % 851 % % 852 % S e t I m a g e V i e w I t e r a t o r % 853 % % 854 % % 855 % % 856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 857 % 858 % SetImageViewIterator() iterates over the image view in parallel and calls 859 % your set method for each scanline of the view. The pixel extent is 860 % confined to the image canvas-- that is no negative offsets or widths or 861 % heights that exceed the image dimension. The pixels are initiallly 862 % undefined and any settings you make in the callback method are automagically 863 % synced back to your image. 864 % 865 % The callback signature is: 866 % 867 % MagickBooleanType SetImageViewMethod(ImageView *destination, 868 % const ssize_t y,const int thread_id,void *context) 869 % 870 % Use this pragma if the view is not single threaded: 871 % 872 % #pragma omp critical 873 % 874 % to define a section of code in your callback set method that must be 875 % executed by a single thread at a time. 876 % 877 % The format of the SetImageViewIterator method is: 878 % 879 % MagickBooleanType SetImageViewIterator(ImageView *destination, 880 % SetImageViewMethod set,void *context) 881 % 882 % A description of each parameter follows: 883 % 884 % o destination: the image view. 885 % 886 % o set: the set callback method. 887 % 888 % o context: the user defined context. 889 % 890 */ 891 MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination, 892 SetImageViewMethod set,void *context) 893 { 894 Image 895 *destination_image; 896 897 MagickBooleanType 898 status; 899 900 MagickOffsetType 901 progress; 902 903 #if defined(MAGICKCORE_OPENMP_SUPPORT) 904 size_t 905 height; 906 #endif 907 908 ssize_t 909 y; 910 911 assert(destination != (ImageView *) NULL); 912 assert(destination->signature == MagickCoreSignature); 913 if (set == (SetImageViewMethod) NULL) 914 return(MagickFalse); 915 destination_image=destination->image; 916 status=SetImageStorageClass(destination_image,DirectClass, 917 destination->exception); 918 if (status == MagickFalse) 919 return(MagickFalse); 920 status=MagickTrue; 921 progress=0; 922 #if defined(MAGICKCORE_OPENMP_SUPPORT) 923 height=destination->extent.height-destination->extent.y; 924 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 925 magick_threads(destination_image,destination_image,height,1) 926 #endif 927 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++) 928 { 929 const int 930 id = GetOpenMPThreadId(); 931 932 MagickBooleanType 933 sync; 934 935 register Quantum 936 *magick_restrict pixels; 937 938 if (status == MagickFalse) 939 continue; 940 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x, 941 y,destination->extent.width,1,destination->exception); 942 if (pixels == (Quantum *) NULL) 943 { 944 status=MagickFalse; 945 continue; 946 } 947 if (set(destination,y,id,context) == MagickFalse) 948 status=MagickFalse; 949 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception); 950 if (sync == MagickFalse) 951 status=MagickFalse; 952 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL) 953 { 954 MagickBooleanType 955 proceed; 956 957 #if defined(MAGICKCORE_OPENMP_SUPPORT) 958 #pragma omp critical (MagickCore_SetImageViewIterator) 959 #endif 960 proceed=SetImageProgress(destination_image,destination->description, 961 progress++,destination->extent.height); 962 if (proceed == MagickFalse) 963 status=MagickFalse; 964 } 965 } 966 return(status); 967 } 968 969 /* 971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 972 % % 973 % % 974 % % 975 % T r a n s f e r I m a g e V i e w I t e r a t o r % 976 % % 977 % % 978 % % 979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 980 % 981 % TransferImageViewIterator() iterates over two image views in parallel and 982 % calls your transfer method for each scanline of the view. The source pixel 983 % extent is not confined to the image canvas-- that is you can include 984 % negative offsets or widths or heights that exceed the image dimension. 985 % However, the destination image view is confined to the image canvas-- that 986 % is no negative offsets or widths or heights that exceed the image dimension 987 % are permitted. 988 % 989 % The callback signature is: 990 % 991 % MagickBooleanType TransferImageViewMethod(const ImageView *source, 992 % ImageView *destination,const ssize_t y,const int thread_id, 993 % void *context) 994 % 995 % Use this pragma if the view is not single threaded: 996 % 997 % #pragma omp critical 998 % 999 % to define a section of code in your callback transfer method that must be 1000 % executed by a single thread at a time. 1001 % 1002 % The format of the TransferImageViewIterator method is: 1003 % 1004 % MagickBooleanType TransferImageViewIterator(ImageView *source, 1005 % ImageView *destination,TransferImageViewMethod transfer,void *context) 1006 % 1007 % A description of each parameter follows: 1008 % 1009 % o source: the source image view. 1010 % 1011 % o destination: the destination image view. 1012 % 1013 % o transfer: the transfer callback method. 1014 % 1015 % o context: the user defined context. 1016 % 1017 */ 1018 MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source, 1019 ImageView *destination,TransferImageViewMethod transfer,void *context) 1020 { 1021 Image 1022 *destination_image, 1023 *source_image; 1024 1025 MagickBooleanType 1026 status; 1027 1028 MagickOffsetType 1029 progress; 1030 1031 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1032 size_t 1033 height; 1034 #endif 1035 1036 ssize_t 1037 y; 1038 1039 assert(source != (ImageView *) NULL); 1040 assert(source->signature == MagickCoreSignature); 1041 if (transfer == (TransferImageViewMethod) NULL) 1042 return(MagickFalse); 1043 source_image=source->image; 1044 destination_image=destination->image; 1045 status=SetImageStorageClass(destination_image,DirectClass, 1046 destination->exception); 1047 if (status == MagickFalse) 1048 return(MagickFalse); 1049 status=MagickTrue; 1050 progress=0; 1051 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1052 height=source->extent.height-source->extent.y; 1053 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 1054 magick_threads(source_image,destination_image,height,1) 1055 #endif 1056 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 1057 { 1058 const int 1059 id = GetOpenMPThreadId(); 1060 1061 MagickBooleanType 1062 sync; 1063 1064 register const Quantum 1065 *magick_restrict pixels; 1066 1067 register Quantum 1068 *magick_restrict destination_pixels; 1069 1070 if (status == MagickFalse) 1071 continue; 1072 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y, 1073 source->extent.width,1,source->exception); 1074 if (pixels == (const Quantum *) NULL) 1075 { 1076 status=MagickFalse; 1077 continue; 1078 } 1079 destination_pixels=GetCacheViewAuthenticPixels(destination->view, 1080 destination->extent.x,y,destination->extent.width,1, 1081 destination->exception); 1082 if (destination_pixels == (Quantum *) NULL) 1083 { 1084 status=MagickFalse; 1085 continue; 1086 } 1087 if (transfer(source,destination,y,id,context) == MagickFalse) 1088 status=MagickFalse; 1089 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception); 1090 if (sync == MagickFalse) 1091 status=MagickFalse; 1092 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 1093 { 1094 MagickBooleanType 1095 proceed; 1096 1097 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1098 #pragma omp critical (MagickCore_TransferImageViewIterator) 1099 #endif 1100 proceed=SetImageProgress(source_image,source->description,progress++, 1101 source->extent.height); 1102 if (proceed == MagickFalse) 1103 status=MagickFalse; 1104 } 1105 } 1106 return(status); 1107 } 1108 1109 /* 1111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1112 % % 1113 % % 1114 % % 1115 % U p d a t e I m a g e V i e w I t e r a t o r % 1116 % % 1117 % % 1118 % % 1119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1120 % 1121 % UpdateImageViewIterator() iterates over the image view in parallel and calls 1122 % your update method for each scanline of the view. The pixel extent is 1123 % confined to the image canvas-- that is no negative offsets or widths or 1124 % heights that exceed the image dimension are permitted. Updates to pixels 1125 % in your callback are automagically synced back to the image. 1126 % 1127 % The callback signature is: 1128 % 1129 % MagickBooleanType UpdateImageViewMethod(ImageView *source, 1130 % const ssize_t y,const int thread_id,void *context) 1131 % 1132 % Use this pragma if the view is not single threaded: 1133 % 1134 % #pragma omp critical 1135 % 1136 % to define a section of code in your callback update method that must be 1137 % executed by a single thread at a time. 1138 % 1139 % The format of the UpdateImageViewIterator method is: 1140 % 1141 % MagickBooleanType UpdateImageViewIterator(ImageView *source, 1142 % UpdateImageViewMethod update,void *context) 1143 % 1144 % A description of each parameter follows: 1145 % 1146 % o source: the source image view. 1147 % 1148 % o update: the update callback method. 1149 % 1150 % o context: the user defined context. 1151 % 1152 */ 1153 MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source, 1154 UpdateImageViewMethod update,void *context) 1155 { 1156 Image 1157 *source_image; 1158 1159 MagickBooleanType 1160 status; 1161 1162 MagickOffsetType 1163 progress; 1164 1165 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1166 size_t 1167 height; 1168 #endif 1169 1170 ssize_t 1171 y; 1172 1173 assert(source != (ImageView *) NULL); 1174 assert(source->signature == MagickCoreSignature); 1175 if (update == (UpdateImageViewMethod) NULL) 1176 return(MagickFalse); 1177 source_image=source->image; 1178 status=SetImageStorageClass(source_image,DirectClass,source->exception); 1179 if (status == MagickFalse) 1180 return(MagickFalse); 1181 status=MagickTrue; 1182 progress=0; 1183 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1184 height=source->extent.height-source->extent.y; 1185 #pragma omp parallel for schedule(static,4) shared(progress,status) \ 1186 magick_threads(source_image,source_image,height,1) 1187 #endif 1188 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++) 1189 { 1190 const int 1191 id = GetOpenMPThreadId(); 1192 1193 register Quantum 1194 *magick_restrict pixels; 1195 1196 if (status == MagickFalse) 1197 continue; 1198 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y, 1199 source->extent.width,1,source->exception); 1200 if (pixels == (Quantum *) NULL) 1201 { 1202 status=MagickFalse; 1203 continue; 1204 } 1205 if (update(source,y,id,context) == MagickFalse) 1206 status=MagickFalse; 1207 status=SyncCacheViewAuthenticPixels(source->view,source->exception); 1208 if (status == MagickFalse) 1209 status=MagickFalse; 1210 if (source_image->progress_monitor != (MagickProgressMonitor) NULL) 1211 { 1212 MagickBooleanType 1213 proceed; 1214 1215 #if defined(MAGICKCORE_OPENMP_SUPPORT) 1216 #pragma omp critical (MagickCore_UpdateImageViewIterator) 1217 #endif 1218 proceed=SetImageProgress(source_image,source->description,progress++, 1219 source->extent.height); 1220 if (proceed == MagickFalse) 1221 status=MagickFalse; 1222 } 1223 } 1224 return(status); 1225 } 1226