2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % IIIII M M AAA GGGG EEEEE %
7 % I M M M AAAAA G GG EEE %
9 % IIIII M M A A GGGG EEEEE %
11 % V V IIIII EEEEE W W %
18 % MagickCore Image View Methods %
25 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
31 % http://www.imagemagick.org/script/license.php %
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. %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 #include "magick/studio.h"
49 #include "magick/MagickCore.h"
50 #include "magick/exception-private.h"
51 #include "magick/monitor-private.h"
52 #include "magick/thread-private.h"
85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 % C l o n e I m a g e V i e w %
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95 % CloneImageView() makes a copy of the specified image view.
97 % The format of the CloneImageView method is:
99 % ImageView *CloneImageView(const ImageView *image_view)
101 % A description of each parameter follows:
103 % o image_view: the image view.
106 MagickExport ImageView *CloneImageView(const ImageView *image_view)
111 assert(image_view != (ImageView *) NULL);
112 assert(image_view->signature == MagickSignature);
113 clone_view=(ImageView *) AcquireAlignedMemory(1,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->number_threads=image_view->number_threads;
121 clone_view->exception=AcquireExceptionInfo();
122 InheritException(clone_view->exception,image_view->exception);
123 clone_view->debug=image_view->debug;
124 clone_view->signature=MagickSignature;
129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 % D e s t r o y I m a g e V i e w %
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 % DestroyImageView() deallocates memory associated with a image view.
141 % The format of the DestroyImageView method is:
143 % ImageView *DestroyImageView(ImageView *image_view)
145 % A description of each parameter follows:
147 % o image_view: the image view.
150 MagickExport ImageView *DestroyImageView(ImageView *image_view)
152 assert(image_view != (ImageView *) NULL);
153 assert(image_view->signature == MagickSignature);
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=(~MagickSignature);
159 image_view=(ImageView *) RelinquishMagickMemory(image_view);
164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 % 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 %
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 % DuplexTransferImageViewIterator() iterates over three image views in
175 % parallel and calls your transfer method for each scanline of the view. The
176 % source and duplex pixel extent is not confined to the image canvas-- that is
177 % you can include negative offsets or widths or heights that exceed the image
178 % dimension. However, the destination image view is confined to the image
179 % canvas-- that is no negative offsets or widths or heights that exceed the
180 % image dimension are permitted.
182 % The callback signature is:
184 % MagickBooleanType DuplexTransferImageViewMethod(const ImageView *source,
185 % const ImageView *duplex,ImageView *destination,const ssize_t y,
186 % const int thread_id,void *context)
188 % Use this pragma if the view is not single threaded:
190 % #pragma omp critical
192 % to define a section of code in your callback transfer method that must be
193 % executed by a single thread at a time.
195 % The format of the DuplexTransferImageViewIterator method is:
197 % MagickBooleanType DuplexTransferImageViewIterator(ImageView *source,
198 % ImageView *duplex,ImageView *destination,
199 % DuplexTransferImageViewMethod transfer,void *context)
201 % A description of each parameter follows:
203 % o source: the source image view.
205 % o duplex: the duplex image view.
207 % o destination: the destination image view.
209 % o transfer: the transfer callback method.
211 % o context: the user defined context.
214 MagickExport MagickBooleanType DuplexTransferImageViewIterator(
215 ImageView *source,ImageView *duplex,ImageView *destination,
216 DuplexTransferImageViewMethod transfer,void *context)
235 assert(source != (ImageView *) NULL);
236 assert(source->signature == MagickSignature);
237 if (transfer == (DuplexTransferImageViewMethod) NULL)
239 source_image=source->image;
240 duplex_image=duplex->image;
241 destination_image=destination->image;
242 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
246 exception=destination->exception;
247 #if defined(MAGICKCORE_OPENMP_SUPPORT)
248 #pragma omp parallel for schedule(static,1) shared(progress,status)
250 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
258 register const IndexPacket
259 *restrict duplex_indexes,
262 register const PixelPacket
263 *restrict duplex_pixels,
267 *restrict destination_indexes;
270 *restrict destination_pixels;
272 if (status == MagickFalse)
274 id=GetOpenMPThreadId();
275 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
276 source->extent.width,1,source->exception);
277 if (pixels == (const PixelPacket *) NULL)
282 indexes=GetCacheViewVirtualIndexQueue(source->view);
283 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
284 duplex->extent.width,1,duplex->exception);
285 if (duplex_pixels == (const PixelPacket *) NULL)
290 duplex_indexes=GetCacheViewVirtualIndexQueue(duplex->view);
291 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
292 destination->extent.x,y,destination->extent.width,1,exception);
293 if (destination_pixels == (PixelPacket *) NULL)
298 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
299 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
301 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
302 if (sync == MagickFalse)
304 InheritException(destination->exception,GetCacheViewException(
308 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
313 #if defined(MAGICKCORE_OPENMP_SUPPORT)
314 #pragma omp critical (MagickCore_DuplexTransferImageViewIterator)
316 proceed=SetImageProgress(source_image,source->description,progress++,
317 source->extent.height);
318 if (proceed == MagickFalse)
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 % G e t I m a g e V i e w A u t h e n t i c I n d e x e s %
334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 % GetImageViewAuthenticIndexes() returns the image view authentic indexes.
338 % The format of the GetImageViewAuthenticPixels method is:
340 % IndexPacket *GetImageViewAuthenticIndexes(const ImageView *image_view)
342 % A description of each parameter follows:
344 % o image_view: the image view.
347 MagickExport IndexPacket *GetImageViewAuthenticIndexes(
348 const ImageView *image_view)
350 assert(image_view != (ImageView *) NULL);
351 assert(image_view->signature == MagickSignature);
352 return(GetCacheViewAuthenticIndexQueue(image_view->view));
356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 % 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 %
364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 % GetImageViewAuthenticPixels() returns the image view authentic pixels.
368 % The format of the GetImageViewAuthenticPixels method is:
370 % PixelPacket *GetImageViewAuthenticPixels(const ImageView *image_view)
372 % A description of each parameter follows:
374 % o image_view: the image view.
377 MagickExport PixelPacket *GetImageViewAuthenticPixels(
378 const ImageView *image_view)
380 assert(image_view != (ImageView *) NULL);
381 assert(image_view->signature == MagickSignature);
382 return(GetCacheViewAuthenticPixelQueue(image_view->view));
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 % G e t I m a g e V i e w E x c e p t i o n %
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396 % GetImageViewException() returns the severity, reason, and description of any
397 % error that occurs when utilizing a image view.
399 % The format of the GetImageViewException method is:
401 % char *GetImageViewException(const PixelImage *image_view,
402 % ExceptionType *severity)
404 % A description of each parameter follows:
406 % o image_view: the pixel image_view.
408 % o severity: the severity of the error is returned here.
411 MagickExport char *GetImageViewException(const ImageView *image_view,
412 ExceptionType *severity)
417 assert(image_view != (const ImageView *) NULL);
418 assert(image_view->signature == MagickSignature);
419 assert(severity != (ExceptionType *) NULL);
420 *severity=image_view->exception->severity;
421 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
422 sizeof(*description));
423 if (description == (char *) NULL)
424 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
426 if (image_view->exception->reason != (char *) NULL)
427 (void) CopyMagickString(description,GetLocaleExceptionMessage(
428 image_view->exception->severity,image_view->exception->reason),
430 if (image_view->exception->description != (char *) NULL)
432 (void) ConcatenateMagickString(description," (",MaxTextExtent);
433 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
434 image_view->exception->severity,image_view->exception->description),
436 (void) ConcatenateMagickString(description,")",MaxTextExtent);
442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 % G e t I m a g e V i e w E x t e n t %
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
452 % GetImageViewExtent() returns the image view extent.
454 % The format of the GetImageViewExtent method is:
456 % RectangleInfo GetImageViewExtent(const ImageView *image_view)
458 % A description of each parameter follows:
460 % o image_view: the image view.
463 MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
465 assert(image_view != (ImageView *) NULL);
466 assert(image_view->signature == MagickSignature);
467 return(image_view->extent);
471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475 % G e t I m a g e V i e w I m a g e %
479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 % GetImageViewImage() returns the image associated with the image view.
483 % The format of the GetImageViewImage method is:
485 % MagickCore *GetImageViewImage(const ImageView *image_view)
487 % A description of each parameter follows:
489 % o image_view: the image view.
492 MagickExport Image *GetImageViewImage(const ImageView *image_view)
494 assert(image_view != (ImageView *) NULL);
495 assert(image_view->signature == MagickSignature);
496 return(image_view->image);
500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 % G e t I m a g e V i e w I t e r a t o r %
508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 % GetImageViewIterator() iterates over the image view in parallel and calls
511 % your get method for each scanline of the view. The pixel extent is
512 % not confined to the image canvas-- that is you can include negative offsets
513 % or widths or heights that exceed the image dimension. Any updates to
514 % the pixels in your callback are ignored.
516 % The callback signature is:
518 % MagickBooleanType GetImageViewMethod(const ImageView *source,
519 % const ssize_t y,const int thread_id,void *context)
521 % Use this pragma if the view is not single threaded:
523 % #pragma omp critical
525 % to define a section of code in your callback get method that must be
526 % executed by a single thread at a time.
528 % The format of the GetImageViewIterator method is:
530 % MagickBooleanType GetImageViewIterator(ImageView *source,
531 % GetImageViewMethod get,void *context)
533 % A description of each parameter follows:
535 % o source: the source image view.
537 % o get: the get callback method.
539 % o context: the user defined context.
542 MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
543 GetImageViewMethod get,void *context)
557 assert(source != (ImageView *) NULL);
558 assert(source->signature == MagickSignature);
559 if (get == (GetImageViewMethod) NULL)
561 source_image=source->image;
564 #if defined(MAGICKCORE_OPENMP_SUPPORT)
565 #pragma omp parallel for schedule(static,1) shared(progress,status)
567 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
572 register const IndexPacket
575 register const PixelPacket
578 if (status == MagickFalse)
580 id=GetOpenMPThreadId();
581 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
582 source->extent.width,1,source->exception);
583 if (pixels == (const PixelPacket *) NULL)
588 indexes=GetCacheViewVirtualIndexQueue(source->view);
589 if (get(source,y,id,context) == MagickFalse)
591 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
596 #if defined(MAGICKCORE_OPENMP_SUPPORT)
597 #pragma omp critical (MagickCore_GetImageViewIterator)
599 proceed=SetImageProgress(source_image,source->description,progress++,
600 source->extent.height);
601 if (proceed == MagickFalse)
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 % G e t I m a g e V i e w V i r t u a l I n d e x e s %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 % GetImageViewVirtualIndexes() returns the image view virtual indexes.
621 % The format of the GetImageViewVirtualIndexes method is:
623 % const IndexPacket *GetImageViewVirtualIndexes(
624 % const ImageView *image_view)
626 % A description of each parameter follows:
628 % o image_view: the image view.
631 MagickExport const IndexPacket *GetImageViewVirtualIndexes(
632 const ImageView *image_view)
634 assert(image_view != (ImageView *) NULL);
635 assert(image_view->signature == MagickSignature);
636 return(GetCacheViewVirtualIndexQueue(image_view->view));
640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 % 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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 % GetImageViewVirtualPixels() returns the image view virtual pixels.
652 % The format of the GetImageViewVirtualPixels method is:
654 % const PixelPacket *GetImageViewVirtualPixels(const ImageView *image_view)
656 % A description of each parameter follows:
658 % o image_view: the image view.
661 MagickExport const PixelPacket *GetImageViewVirtualPixels(
662 const ImageView *image_view)
664 assert(image_view != (ImageView *) NULL);
665 assert(image_view->signature == MagickSignature);
666 return(GetCacheViewVirtualPixelQueue(image_view->view));
670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
674 % I s I m a g e V i e w %
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
680 % IsImageView() returns MagickTrue if the the parameter is verified as a image
683 % The format of the IsImageView method is:
685 % MagickBooleanType IsImageView(const ImageView *image_view)
687 % A description of each parameter follows:
689 % o image_view: the image view.
692 MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
694 if (image_view == (const ImageView *) NULL)
696 if (image_view->signature != MagickSignature)
702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706 % N e w I m a g e V i e w %
710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 % NewImageView() returns a image view required for all other methods in the
715 % The format of the NewImageView method is:
717 % ImageView *NewImageView(MagickCore *wand)
719 % A description of each parameter follows:
724 MagickExport ImageView *NewImageView(Image *image)
729 assert(image != (Image *) NULL);
730 assert(image->signature == MagickSignature);
731 image_view=(ImageView *) AcquireAlignedMemory(1,sizeof(*image_view));
732 if (image_view == (ImageView *) NULL)
733 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
734 (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
735 image_view->description=ConstantString("ImageView");
736 image_view->image=image;
737 image_view->view=AcquireCacheView(image_view->image);
738 image_view->extent.width=image->columns;
739 image_view->extent.height=image->rows;
740 image_view->extent.x=0;
741 image_view->extent.y=0;
742 image_view->number_threads=GetOpenMPMaximumThreads();
743 image_view->exception=AcquireExceptionInfo();
744 image_view->debug=IsEventLogging();
745 image_view->signature=MagickSignature;
750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 % N e w I m a g e V i e w R e g i o n %
758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 % NewImageViewRegion() returns a image view required for all other methods
761 % in the Image View API.
763 % The format of the NewImageViewRegion method is:
765 % ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
766 % const ssize_t y,const size_t width,const size_t height)
768 % A description of each parameter follows:
770 % o wand: the magick wand.
772 % o x,y,columns,rows: These values define the perimeter of a extent of
776 MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
777 const ssize_t y,const size_t width,const size_t height)
782 assert(image != (Image *) NULL);
783 assert(image->signature == MagickSignature);
784 image_view=(ImageView *) AcquireAlignedMemory(1,sizeof(*image_view));
785 if (image_view == (ImageView *) NULL)
786 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
787 (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
788 image_view->description=ConstantString("ImageView");
789 image_view->view=AcquireCacheView(image_view->image);
790 image_view->image=image;
791 image_view->extent.width=width;
792 image_view->extent.height=height;
793 image_view->extent.x=x;
794 image_view->extent.y=y;
795 image_view->number_threads=GetOpenMPMaximumThreads();
796 image_view->exception=AcquireExceptionInfo();
797 image_view->debug=IsEventLogging();
798 image_view->signature=MagickSignature;
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807 % S e t I m a g e V i e w D e s c r i p t i o n %
811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813 % SetImageViewDescription() associates a description with an image view.
815 % The format of the SetImageViewDescription method is:
817 % void SetImageViewDescription(ImageView *image_view,
818 % const char *description)
820 % A description of each parameter follows:
822 % o image_view: the image view.
824 % o description: the image view description.
827 MagickExport void SetImageViewDescription(ImageView *image_view,
828 const char *description)
830 assert(image_view != (ImageView *) NULL);
831 assert(image_view->signature == MagickSignature);
832 image_view->description=ConstantString(description);
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
840 % S e t I m a g e V i e w I t e r a t o r %
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
846 % SetImageViewIterator() iterates over the image view in parallel and calls
847 % your set method for each scanline of the view. The pixel extent is
848 % confined to the image canvas-- that is no negative offsets or widths or
849 % heights that exceed the image dimension. The pixels are initiallly
850 % undefined and any settings you make in the callback method are automagically
851 % synced back to your image.
853 % The callback signature is:
855 % MagickBooleanType SetImageViewMethod(ImageView *destination,
856 % const ssize_t y,const int thread_id,void *context)
858 % Use this pragma if the view is not single threaded:
860 % #pragma omp critical
862 % to define a section of code in your callback set method that must be
863 % executed by a single thread at a time.
865 % The format of the SetImageViewIterator method is:
867 % MagickBooleanType SetImageViewIterator(ImageView *destination,
868 % SetImageViewMethod set,void *context)
870 % A description of each parameter follows:
872 % o destination: the image view.
874 % o set: the set callback method.
876 % o context: the user defined context.
879 MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
880 SetImageViewMethod set,void *context)
897 assert(destination != (ImageView *) NULL);
898 assert(destination->signature == MagickSignature);
899 if (set == (SetImageViewMethod) NULL)
901 destination_image=destination->image;
902 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
906 exception=destination->exception;
907 #if defined(MAGICKCORE_OPENMP_SUPPORT)
908 #pragma omp parallel for schedule(static,1) shared(progress,status)
910 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
924 if (status == MagickFalse)
926 id=GetOpenMPThreadId();
927 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
928 y,destination->extent.width,1,exception);
929 if (pixels == (PixelPacket *) NULL)
931 InheritException(destination->exception,GetCacheViewException(
936 indexes=GetCacheViewAuthenticIndexQueue(destination->view);
937 if (set(destination,y,id,context) == MagickFalse)
939 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
940 if (sync == MagickFalse)
942 InheritException(destination->exception,GetCacheViewException(
946 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
951 #if defined(MAGICKCORE_OPENMP_SUPPORT)
952 #pragma omp critical (MagickCore_SetImageViewIterator)
954 proceed=SetImageProgress(destination_image,destination->description,
955 progress++,destination->extent.height);
956 if (proceed == MagickFalse)
964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 % 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 %
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974 % TransferImageViewIterator() iterates over two image views in parallel and
975 % calls your transfer method for each scanline of the view. The source pixel
976 % extent is not confined to the image canvas-- that is you can include
977 % negative offsets or widths or heights that exceed the image dimension.
978 % However, the destination image view is confined to the image canvas-- that
979 % is no negative offsets or widths or heights that exceed the image dimension
982 % The callback signature is:
984 % MagickBooleanType TransferImageViewMethod(const ImageView *source,
985 % ImageView *destination,const ssize_t y,const int thread_id,
988 % Use this pragma if the view is not single threaded:
990 % #pragma omp critical
992 % to define a section of code in your callback transfer method that must be
993 % executed by a single thread at a time.
995 % The format of the TransferImageViewIterator method is:
997 % MagickBooleanType TransferImageViewIterator(ImageView *source,
998 % ImageView *destination,TransferImageViewMethod transfer,void *context)
1000 % A description of each parameter follows:
1002 % o source: the source image view.
1004 % o destination: the destination image view.
1006 % o transfer: the transfer callback method.
1008 % o context: the user defined context.
1011 MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
1012 ImageView *destination,TransferImageViewMethod transfer,void *context)
1030 assert(source != (ImageView *) NULL);
1031 assert(source->signature == MagickSignature);
1032 if (transfer == (TransferImageViewMethod) NULL)
1033 return(MagickFalse);
1034 source_image=source->image;
1035 destination_image=destination->image;
1036 if (SetImageStorageClass(destination_image,DirectClass) == MagickFalse)
1037 return(MagickFalse);
1040 exception=destination->exception;
1041 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1042 #pragma omp parallel for schedule(static,1) shared(progress,status)
1044 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1052 register const IndexPacket
1055 register const PixelPacket
1058 register IndexPacket
1059 *restrict destination_indexes;
1061 register PixelPacket
1062 *restrict destination_pixels;
1064 if (status == MagickFalse)
1066 id=GetOpenMPThreadId();
1067 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1068 source->extent.width,1,source->exception);
1069 if (pixels == (const PixelPacket *) NULL)
1074 indexes=GetCacheViewVirtualIndexQueue(source->view);
1075 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1076 destination->extent.x,y,destination->extent.width,1,exception);
1077 if (destination_pixels == (PixelPacket *) NULL)
1082 destination_indexes=GetCacheViewAuthenticIndexQueue(destination->view);
1083 if (transfer(source,destination,y,id,context) == MagickFalse)
1085 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1086 if (sync == MagickFalse)
1088 InheritException(destination->exception,GetCacheViewException(
1092 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1097 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1098 #pragma omp critical (MagickCore_TransferImageViewIterator)
1100 proceed=SetImageProgress(source_image,source->description,progress++,
1101 source->extent.height);
1102 if (proceed == MagickFalse)
1110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 % U p d a t e I m a g e V i e w I t e r a t o r %
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120 % UpdateImageViewIterator() iterates over the image view in parallel and calls
1121 % your update method for each scanline of the view. The pixel extent is
1122 % confined to the image canvas-- that is no negative offsets or widths or
1123 % heights that exceed the image dimension are permitted. Updates to pixels
1124 % in your callback are automagically synced back to the image.
1126 % The callback signature is:
1128 % MagickBooleanType UpdateImageViewMethod(ImageView *source,
1129 % const ssize_t y,const int thread_id,void *context)
1131 % Use this pragma if the view is not single threaded:
1133 % #pragma omp critical
1135 % to define a section of code in your callback update method that must be
1136 % executed by a single thread at a time.
1138 % The format of the UpdateImageViewIterator method is:
1140 % MagickBooleanType UpdateImageViewIterator(ImageView *source,
1141 % UpdateImageViewMethod update,void *context)
1143 % A description of each parameter follows:
1145 % o source: the source image view.
1147 % o update: the update callback method.
1149 % o context: the user defined context.
1152 MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1153 UpdateImageViewMethod update,void *context)
1170 assert(source != (ImageView *) NULL);
1171 assert(source->signature == MagickSignature);
1172 if (update == (UpdateImageViewMethod) NULL)
1173 return(MagickFalse);
1174 source_image=source->image;
1175 if (SetImageStorageClass(source_image,DirectClass) == MagickFalse)
1176 return(MagickFalse);
1179 exception=source->exception;
1180 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1181 #pragma omp parallel for schedule(static,1) shared(progress,status)
1183 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1188 register IndexPacket
1191 register PixelPacket
1194 if (status == MagickFalse)
1196 id=GetOpenMPThreadId();
1197 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1198 source->extent.width,1,exception);
1199 if (pixels == (PixelPacket *) NULL)
1201 InheritException(source->exception,GetCacheViewException(source->view));
1205 indexes=GetCacheViewAuthenticIndexQueue(source->view);
1206 if (update(source,y,id,context) == MagickFalse)
1208 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1210 InheritException(source->exception,GetCacheViewException(source->view));
1213 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1218 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1219 #pragma omp critical (MagickCore_UpdateImageViewIterator)
1221 proceed=SetImageProgress(source_image,source->description,progress++,
1222 source->extent.height);
1223 if (proceed == MagickFalse)