2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 % W W W AAAAA N N N D D %
11 % V V IIIII EEEEE W W %
18 % MagickWand Wand View Methods %
25 % Copyright 1999-2012 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 "MagickWand/studio.h"
49 #include "MagickWand/MagickWand.h"
50 #include "MagickWand/magick-wand-private.h"
51 #include "MagickWand/wand.h"
52 #include "MagickCore/monitor-private.h"
53 #include "MagickCore/thread-private.h"
57 #define WandViewId "WandView"
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101 % C l o n e W a n d V i e w %
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107 % CloneWandView() makes a copy of the specified wand view.
109 % The format of the CloneWandView method is:
111 % WandView *CloneWandView(const WandView *wand_view)
113 % A description of each parameter follows:
115 % o wand_view: the wand view.
118 WandExport WandView *CloneWandView(const WandView *wand_view)
126 assert(wand_view != (WandView *) NULL);
127 assert(wand_view->signature == WandSignature);
128 if (wand_view->debug != MagickFalse)
129 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
130 clone_view=(WandView *) AcquireMagickMemory(sizeof(*clone_view));
131 if (clone_view == (WandView *) NULL)
132 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
134 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
135 clone_view->id=AcquireWandId();
136 (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g",
137 WandViewId,(double) clone_view->id);
138 clone_view->description=ConstantString(wand_view->description);
139 clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
140 wand_view->exception);
141 clone_view->view=CloneCacheView(wand_view->view);
142 clone_view->extent=wand_view->extent;
143 clone_view->exception=AcquireExceptionInfo();
144 InheritException(clone_view->exception,wand_view->exception);
145 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
146 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
147 wand_view->pixel_wands[i],wand_view->extent.width);
148 clone_view->debug=wand_view->debug;
149 if (clone_view->debug != MagickFalse)
150 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
151 clone_view->signature=WandSignature;
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160 % D e s t r o y W a n d V i e w %
164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 % DestroyWandView() deallocates memory associated with a wand view.
168 % The format of the DestroyWandView method is:
170 % WandView *DestroyWandView(WandView *wand_view)
172 % A description of each parameter follows:
174 % o wand_view: the wand view.
178 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
179 const size_t number_wands)
184 assert(pixel_wands != (PixelWand ***) NULL);
185 for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
186 if (pixel_wands[i] != (PixelWand **) NULL)
187 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
188 pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
192 WandExport WandView *DestroyWandView(WandView *wand_view)
194 assert(wand_view != (WandView *) NULL);
195 assert(wand_view->signature == WandSignature);
196 wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands,
197 wand_view->extent.width);
198 wand_view->image=DestroyImage(wand_view->image);
199 wand_view->view=DestroyCacheView(wand_view->view);
200 wand_view->exception=DestroyExceptionInfo(wand_view->exception);
201 wand_view->signature=(~WandSignature);
202 RelinquishWandId(wand_view->id);
203 wand_view=(WandView *) RelinquishMagickMemory(wand_view);
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212 % D u p l e x T r a n s f e r W a n d V i e w I t e r a t o r %
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 % DuplexTransferWandViewIterator() iterates over three wand views in
219 % parallel and calls your transfer method for each scanline of the view. The
220 % source and duplex pixel extent is not confined to the image canvas-- that is
221 % you can include negative offsets or widths or heights that exceed the image
222 % dimension. However, the destination wand view is confined to the image
223 % canvas-- that is no negative offsets or widths or heights that exceed the
224 % image dimension are permitted.
226 % The callback signature is:
228 % MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
229 % const WandView *duplex,WandView *destination,const ssize_t y,
230 % const int thread_id,void *context)
232 % Use this pragma if the view is not single threaded:
234 % #pragma omp critical
236 % to define a section of code in your callback transfer method that must be
237 % executed by a single thread at a time.
239 % The format of the DuplexTransferWandViewIterator method is:
241 % MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
242 % WandView *duplex,WandView *destination,
243 % DuplexTransferWandViewMethod transfer,void *context)
245 % A description of each parameter follows:
247 % o source: the source wand view.
249 % o duplex: the duplex wand view.
251 % o destination: the destination wand view.
253 % o transfer: the transfer callback method.
255 % o context: the user defined context.
258 WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
259 WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
272 #if defined(MAGICKCORE_OPENMP_SUPPORT)
281 assert(source != (WandView *) NULL);
282 assert(source->signature == WandSignature);
283 if (transfer == (DuplexTransferWandViewMethod) NULL)
285 source_image=source->wand->images;
286 destination_image=destination->wand->images;
287 status=SetImageStorageClass(destination_image,DirectClass,
288 destination->exception);
289 if (status == MagickFalse)
293 #if defined(MAGICKCORE_OPENMP_SUPPORT)
294 height=source->extent.height-source->extent.y;
295 width=source->extent.width-source->extent.x;
296 #pragma omp parallel for schedule(static) shared(progress,status) \
297 dynamic_number_threads(source_image,width,height,1)
299 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
302 id = GetOpenMPThreadId();
307 register const Quantum
308 *restrict duplex_pixels,
315 *restrict destination_pixels;
317 if (status == MagickFalse)
319 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
320 source->extent.width,1,source->exception);
321 if (pixels == (const Quantum *) NULL)
326 for (x=0; x < (ssize_t) source->extent.width; x++)
328 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
329 pixels+=GetPixelChannels(source->image);
331 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
332 duplex->extent.width,1,duplex->exception);
333 if (duplex_pixels == (const Quantum *) NULL)
338 for (x=0; x < (ssize_t) duplex->extent.width; x++)
340 PixelSetQuantumPixel(duplex->image,duplex_pixels,
341 duplex->pixel_wands[id][x]);
342 duplex_pixels+=GetPixelChannels(duplex->image);
344 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
345 destination->extent.x,y,destination->extent.width,1,
346 destination->exception);
347 if (destination_pixels == (Quantum *) NULL)
352 for (x=0; x < (ssize_t) destination->extent.width; x++)
354 PixelSetQuantumPixel(destination->image,destination_pixels,
355 destination->pixel_wands[id][x]);
356 destination_pixels+=GetPixelChannels(destination->image);
358 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
360 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
361 destination->extent.x,y,destination->extent.width,1,
362 destination->exception);
363 for (x=0; x < (ssize_t) destination->extent.width; x++)
365 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
367 destination_pixels+=GetPixelChannels(destination->image);
369 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
370 if (sync == MagickFalse)
372 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
377 #if defined(MAGICKCORE_OPENMP_SUPPORT)
378 #pragma omp critical (MagickWand_DuplexTransferWandViewIterator)
380 proceed=SetImageProgress(source_image,source->description,progress++,
381 source->extent.height);
382 if (proceed == MagickFalse)
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 % G e t W a n d V i e w E x c e p t i o n %
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % GetWandViewException() returns the severity, reason, and description of any
401 % error that occurs when utilizing a wand view.
403 % The format of the GetWandViewException method is:
405 % char *GetWandViewException(const WandView *wand_view,
406 % ExceptionType *severity)
408 % A description of each parameter follows:
410 % o wand_view: the pixel wand_view.
412 % o severity: the severity of the error is returned here.
415 WandExport char *GetWandViewException(const WandView *wand_view,
416 ExceptionType *severity)
421 assert(wand_view != (const WandView *) NULL);
422 assert(wand_view->signature == WandSignature);
423 if (wand_view->debug != MagickFalse)
424 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
425 assert(severity != (ExceptionType *) NULL);
426 *severity=wand_view->exception->severity;
427 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
428 sizeof(*description));
429 if (description == (char *) NULL)
430 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
433 if (wand_view->exception->reason != (char *) NULL)
434 (void) CopyMagickString(description,GetLocaleExceptionMessage(
435 wand_view->exception->severity,wand_view->exception->reason),
437 if (wand_view->exception->description != (char *) NULL)
439 (void) ConcatenateMagickString(description," (",MaxTextExtent);
440 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
441 wand_view->exception->severity,wand_view->exception->description),
443 (void) ConcatenateMagickString(description,")",MaxTextExtent);
449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 % G e t W a n d V i e w E x t e n t %
457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 % GetWandViewExtent() returns the wand view extent.
461 % The format of the GetWandViewExtent method is:
463 % RectangleInfo GetWandViewExtent(const WandView *wand_view)
465 % A description of each parameter follows:
467 % o wand_view: the wand view.
470 WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
472 assert(wand_view != (WandView *) NULL);
473 assert(wand_view->signature == WandSignature);
474 return(wand_view->extent);
478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % G e t W a n d V i e w I t e r a t o r %
486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 % GetWandViewIterator() iterates over the wand view in parallel and calls
489 % your get method for each scanline of the view. The pixel extent is
490 % not confined to the image canvas-- that is you can include negative offsets
491 % or widths or heights that exceed the image dimension. Any updates to
492 % the pixels in your callback are ignored.
494 % The callback signature is:
496 % MagickBooleanType GetImageViewMethod(const WandView *source,
497 % const ssize_t y,const int thread_id,void *context)
499 % Use this pragma if the view is not single threaded:
501 % #pragma omp critical
503 % to define a section of code in your callback get method that must be
504 % executed by a single thread at a time.
506 % The format of the GetWandViewIterator method is:
508 % MagickBooleanType GetWandViewIterator(WandView *source,
509 % GetWandViewMethod get,void *context)
511 % A description of each parameter follows:
513 % o source: the source wand view.
515 % o get: the get callback method.
517 % o context: the user defined context.
520 WandExport MagickBooleanType GetWandViewIterator(WandView *source,
521 GetWandViewMethod get,void *context)
532 #if defined(MAGICKCORE_OPENMP_SUPPORT)
541 assert(source != (WandView *) NULL);
542 assert(source->signature == WandSignature);
543 if (get == (GetWandViewMethod) NULL)
545 source_image=source->wand->images;
548 #if defined(MAGICKCORE_OPENMP_SUPPORT)
549 height=source->extent.height-source->extent.y;
550 width=source->extent.width-source->extent.x;
551 #pragma omp parallel for schedule(static) shared(progress,status) \
552 dynamic_number_threads(source_image,width,height,1)
554 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
557 id = GetOpenMPThreadId();
559 register const Quantum
565 if (status == MagickFalse)
567 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
568 source->extent.width,1,source->exception);
569 if (pixels == (const Quantum *) NULL)
574 for (x=0; x < (ssize_t) source->extent.width; x++)
576 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
577 pixels+=GetPixelChannels(source->image);
579 if (get(source,y,id,context) == MagickFalse)
581 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
586 #if defined(MAGICKCORE_OPENMP_SUPPORT)
587 #pragma omp critical (MagickWand_GetWandViewIterator)
589 proceed=SetImageProgress(source_image,source->description,progress++,
590 source->extent.height);
591 if (proceed == MagickFalse)
599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 % G e t W a n d V i e w P i x e l s %
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 % GetWandViewPixels() returns the wand view pixel_wands.
611 % The format of the GetWandViewPixels method is:
613 % PixelWand *GetWandViewPixels(const WandView *wand_view)
615 % A description of each parameter follows:
617 % o wand_view: the wand view.
620 WandExport PixelWand **GetWandViewPixels(const WandView *wand_view)
623 id = GetOpenMPThreadId();
625 assert(wand_view != (WandView *) NULL);
626 assert(wand_view->signature == WandSignature);
627 return(wand_view->pixel_wands[id]);
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 % G e t W a n d V i e w W a n d %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641 % GetWandViewWand() returns the magick wand associated with the wand view.
643 % The format of the GetWandViewWand method is:
645 % MagickWand *GetWandViewWand(const WandView *wand_view)
647 % A description of each parameter follows:
649 % o wand_view: the wand view.
652 WandExport MagickWand *GetWandViewWand(const WandView *wand_view)
654 assert(wand_view != (WandView *) NULL);
655 assert(wand_view->signature == WandSignature);
656 return(wand_view->wand);
660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664 % I s W a n d V i e w %
668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 % IsWandView() returns MagickTrue if the the parameter is verified as a wand
673 % The format of the IsWandView method is:
675 % MagickBooleanType IsWandView(const WandView *wand_view)
677 % A description of each parameter follows:
679 % o wand_view: the wand view.
682 WandExport MagickBooleanType IsWandView(const WandView *wand_view)
687 if (wand_view == (const WandView *) NULL)
689 if (wand_view->signature != WandSignature)
691 length=strlen(WandViewId);
692 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 % N e w W a n d V i e w %
706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
708 % NewWandView() returns a wand view required for all other methods in the
711 % The format of the NewWandView method is:
713 % WandView *NewWandView(MagickWand *wand)
715 % A description of each parameter follows:
721 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands)
732 number_threads=GetOpenMPMaximumThreads();
733 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
734 sizeof(*pixel_wands));
735 if (pixel_wands == (PixelWand ***) NULL)
736 return((PixelWand ***) NULL);
737 (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
738 for (i=0; i < (ssize_t) number_threads; i++)
740 pixel_wands[i]=NewPixelWands(number_wands);
741 if (pixel_wands[i] == (PixelWand **) NULL)
742 return(DestroyPixelsThreadSet(pixel_wands,number_wands));
747 WandExport WandView *NewWandView(MagickWand *wand)
755 assert(wand != (MagickWand *) NULL);
756 assert(wand->signature == WandSignature);
757 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
758 if (wand_view == (WandView *) NULL)
759 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
760 GetExceptionMessage(errno));
761 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
762 wand_view->id=AcquireWandId();
763 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
764 WandViewId,(double) wand_view->id);
765 wand_view->description=ConstantString("WandView");
766 wand_view->wand=wand;
767 exception=AcquireExceptionInfo();
768 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
769 wand_view->extent.width=wand->images->columns;
770 wand_view->extent.height=wand->images->rows;
771 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
772 wand_view->exception=exception;
773 if (wand_view->pixel_wands == (PixelWand ***) NULL)
774 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
775 GetExceptionMessage(errno));
776 wand_view->debug=IsEventLogging();
777 wand_view->signature=WandSignature;
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786 % N e w W a n d V i e w E x t e n t %
790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792 % NewWandViewExtent() returns a wand view required for all other methods
793 % in the Wand View API.
795 % The format of the NewWandViewExtent method is:
797 % WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
798 % const ssize_t y,const size_t width,const size_t height)
800 % A description of each parameter follows:
802 % o wand: the magick wand.
804 % o x,y,columns,rows: These values define the perimeter of a extent of
808 WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
809 const ssize_t y,const size_t width,const size_t height)
817 assert(wand != (MagickWand *) NULL);
818 assert(wand->signature == WandSignature);
819 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
820 if (wand_view == (WandView *) NULL)
821 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
822 GetExceptionMessage(errno));
823 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
824 wand_view->id=AcquireWandId();
825 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
826 WandViewId,(double) wand_view->id);
827 wand_view->description=ConstantString("WandView");
828 exception=AcquireExceptionInfo();
829 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
830 wand_view->wand=wand;
831 wand_view->extent.width=width;
832 wand_view->extent.height=height;
833 wand_view->extent.x=x;
834 wand_view->extent.y=y;
835 wand_view->exception=exception;
836 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
837 if (wand_view->pixel_wands == (PixelWand ***) NULL)
838 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
839 GetExceptionMessage(errno));
840 wand_view->debug=IsEventLogging();
841 wand_view->signature=WandSignature;
846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 % S e t W a n d V i e w D e s c r i p t i o n %
854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 % SetWandViewDescription() associates a description with an image view.
858 % The format of the SetWandViewDescription method is:
860 % void SetWandViewDescription(WandView *image_view,const char *description)
862 % A description of each parameter follows:
864 % o wand_view: the wand view.
866 % o description: the wand view description.
869 MagickExport void SetWandViewDescription(WandView *wand_view,
870 const char *description)
872 assert(wand_view != (WandView *) NULL);
873 assert(wand_view->signature == WandSignature);
874 wand_view->description=ConstantString(description);
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882 % S e t W a n d V i e w I t e r a t o r %
886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888 % SetWandViewIterator() iterates over the wand view in parallel and calls
889 % your set method for each scanline of the view. The pixel extent is
890 % confined to the image canvas-- that is no negative offsets or widths or
891 % heights that exceed the image dimension. The pixels are initiallly
892 % undefined and any settings you make in the callback method are automagically
893 % synced back to your image.
895 % The callback signature is:
897 % MagickBooleanType SetImageViewMethod(ImageView *destination,
898 % const ssize_t y,const int thread_id,void *context)
900 % Use this pragma if the view is not single threaded:
902 % #pragma omp critical
904 % to define a section of code in your callback set method that must be
905 % executed by a single thread at a time.
907 % The format of the SetWandViewIterator method is:
909 % MagickBooleanType SetWandViewIterator(WandView *destination,
910 % SetWandViewMethod set,void *context)
912 % A description of each parameter follows:
914 % o destination: the wand view.
916 % o set: the set callback method.
918 % o context: the user defined context.
921 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
922 SetWandViewMethod set,void *context)
933 #if defined(MAGICKCORE_OPENMP_SUPPORT)
942 assert(destination != (WandView *) NULL);
943 assert(destination->signature == WandSignature);
944 if (set == (SetWandViewMethod) NULL)
946 destination_image=destination->wand->images;
947 status=SetImageStorageClass(destination_image,DirectClass,
948 destination->exception);
949 if (status == MagickFalse)
953 #if defined(MAGICKCORE_OPENMP_SUPPORT)
954 height=destination->extent.height-destination->extent.y;
955 width=destination->extent.width-destination->extent.x;
956 #pragma omp parallel for schedule(static) shared(progress,status) \
957 dynamic_number_threads(destination_image,width,height,1)
959 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
962 id = GetOpenMPThreadId();
973 if (status == MagickFalse)
975 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
976 y,destination->extent.width,1,destination->exception);
977 if (pixels == (Quantum *) NULL)
982 if (set(destination,y,id,context) == MagickFalse)
984 for (x=0; x < (ssize_t) destination->extent.width; x++)
986 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
988 pixels+=GetPixelChannels(destination->image);
990 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
991 if (sync == MagickFalse)
993 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
998 #if defined(MAGICKCORE_OPENMP_SUPPORT)
999 #pragma omp critical (MagickWand_SetWandViewIterator)
1001 proceed=SetImageProgress(destination_image,destination->description,
1002 progress++,destination->extent.height);
1003 if (proceed == MagickFalse)
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1015 % T r a n s f e r W a n d V i e w I t e r a t o r %
1019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1021 % TransferWandViewIterator() iterates over two wand views in parallel and
1022 % calls your transfer method for each scanline of the view. The source pixel
1023 % extent is not confined to the image canvas-- that is you can include
1024 % negative offsets or widths or heights that exceed the image dimension.
1025 % However, the destination wand view is confined to the image canvas-- that
1026 % is no negative offsets or widths or heights that exceed the image dimension
1029 % The callback signature is:
1031 % MagickBooleanType TransferImageViewMethod(const WandView *source,
1032 % WandView *destination,const ssize_t y,const int thread_id,
1035 % Use this pragma if the view is not single threaded:
1037 % #pragma omp critical
1039 % to define a section of code in your callback transfer method that must be
1040 % executed by a single thread at a time.
1042 % The format of the TransferWandViewIterator method is:
1044 % MagickBooleanType TransferWandViewIterator(WandView *source,
1045 % WandView *destination,TransferWandViewMethod transfer,void *context)
1047 % A description of each parameter follows:
1049 % o source: the source wand view.
1051 % o destination: the destination wand view.
1053 % o transfer: the transfer callback method.
1055 % o context: the user defined context.
1058 WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
1059 WandView *destination,TransferWandViewMethod transfer,void *context)
1071 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1080 assert(source != (WandView *) NULL);
1081 assert(source->signature == WandSignature);
1082 if (transfer == (TransferWandViewMethod) NULL)
1083 return(MagickFalse);
1084 source_image=source->wand->images;
1085 destination_image=destination->wand->images;
1086 status=SetImageStorageClass(destination_image,DirectClass,
1087 destination->exception);
1088 if (status == MagickFalse)
1089 return(MagickFalse);
1092 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1093 height=source->extent.height-source->extent.y;
1094 width=source->extent.width-source->extent.x;
1095 #pragma omp parallel for schedule(static) shared(progress,status) \
1096 dynamic_number_threads(source_image,width,height,1)
1098 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1101 id = GetOpenMPThreadId();
1106 register const Quantum
1113 *restrict destination_pixels;
1115 if (status == MagickFalse)
1117 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1118 source->extent.width,1,source->exception);
1119 if (pixels == (const Quantum *) NULL)
1124 for (x=0; x < (ssize_t) source->extent.width; x++)
1126 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1127 pixels+=GetPixelChannels(source->image);
1129 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1130 destination->extent.x,y,destination->extent.width,1,
1131 destination->exception);
1132 if (destination_pixels == (Quantum *) NULL)
1137 for (x=0; x < (ssize_t) destination->extent.width; x++)
1139 PixelSetQuantumPixel(destination->image,destination_pixels,
1140 destination->pixel_wands[id][x]);
1141 destination_pixels+=GetPixelChannels(destination->image);
1143 if (transfer(source,destination,y,id,context) == MagickFalse)
1145 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1146 destination->extent.x,y,destination->extent.width,1,
1147 destination->exception);
1148 for (x=0; x < (ssize_t) destination->extent.width; x++)
1150 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1151 destination_pixels);
1152 destination_pixels+=GetPixelChannels(destination->image);
1154 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1155 if (sync == MagickFalse)
1157 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1162 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1163 #pragma omp critical (MagickWand_TransferWandViewIterator)
1165 proceed=SetImageProgress(source_image,source->description,progress++,
1166 source->extent.height);
1167 if (proceed == MagickFalse)
1175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179 % U p d a t e W a n d V i e w I t e r a t o r %
1183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 % UpdateWandViewIterator() iterates over the wand view in parallel and calls
1186 % your update method for each scanline of the view. The pixel extent is
1187 % confined to the image canvas-- that is no negative offsets or widths or
1188 % heights that exceed the image dimension are permitted. Updates to pixels
1189 % in your callback are automagically synced back to the image.
1191 % The callback signature is:
1193 % MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
1194 % const int thread_id,void *context)
1196 % Use this pragma if the view is not single threaded:
1198 % #pragma omp critical
1200 % to define a section of code in your callback update method that must be
1201 % executed by a single thread at a time.
1203 % The format of the UpdateWandViewIterator method is:
1205 % MagickBooleanType UpdateWandViewIterator(WandView *source,
1206 % UpdateWandViewMethod update,void *context)
1208 % A description of each parameter follows:
1210 % o source: the source wand view.
1212 % o update: the update callback method.
1214 % o context: the user defined context.
1217 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
1218 UpdateWandViewMethod update,void *context)
1229 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1238 assert(source != (WandView *) NULL);
1239 assert(source->signature == WandSignature);
1240 if (update == (UpdateWandViewMethod) NULL)
1241 return(MagickFalse);
1242 source_image=source->wand->images;
1243 status=SetImageStorageClass(source_image,DirectClass,source->exception);
1244 if (status == MagickFalse)
1245 return(MagickFalse);
1248 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1249 height=source->extent.height-source->extent.y;
1250 width=source->extent.width-source->extent.x;
1251 #pragma omp parallel for schedule(static) shared(progress,status) \
1252 dynamic_number_threads(source_image,width,height,1)
1254 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1257 id = GetOpenMPThreadId();
1268 if (status == MagickFalse)
1270 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1271 source->extent.width,1,source->exception);
1272 if (pixels == (Quantum *) NULL)
1277 for (x=0; x < (ssize_t) source->extent.width; x++)
1279 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1280 pixels+=GetPixelChannels(source->image);
1282 if (update(source,y,id,context) == MagickFalse)
1284 for (x=0; x < (ssize_t) source->extent.width; x++)
1286 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
1287 pixels+=GetPixelChannels(source->image);
1289 sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
1290 if (sync == MagickFalse)
1292 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1297 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1298 #pragma omp critical (MagickWand_UpdateWandViewIterator)
1300 proceed=SetImageProgress(source_image,source->description,progress++,
1301 source->extent.height);
1302 if (proceed == MagickFalse)