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-2011 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"
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % C l o n e W a n d V i e w %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 % CloneWandView() makes a copy of the specified wand view.
112 % The format of the CloneWandView method is:
114 % WandView *CloneWandView(const WandView *wand_view)
116 % A description of each parameter follows:
118 % o wand_view: the wand view.
121 WandExport WandView *CloneWandView(const WandView *wand_view)
129 assert(wand_view != (WandView *) NULL);
130 assert(wand_view->signature == WandSignature);
131 if (wand_view->debug != MagickFalse)
132 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
133 clone_view=(WandView *) AcquireMagickMemory(sizeof(*clone_view));
134 if (clone_view == (WandView *) NULL)
135 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
137 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
138 clone_view->id=AcquireWandId();
139 (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g",
140 WandViewId,(double) clone_view->id);
141 clone_view->description=ConstantString(wand_view->description);
142 clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
143 wand_view->exception);
144 clone_view->view=CloneCacheView(wand_view->view);
145 clone_view->extent=wand_view->extent;
146 clone_view->number_threads=wand_view->number_threads;
147 clone_view->exception=AcquireExceptionInfo();
148 InheritException(clone_view->exception,wand_view->exception);
149 for (i=0; i < (ssize_t) wand_view->number_threads; i++)
150 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
151 wand_view->pixel_wands[i],wand_view->extent.width);
152 clone_view->debug=wand_view->debug;
153 if (clone_view->debug != MagickFalse)
154 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
155 clone_view->signature=WandSignature;
160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 % D e s t r o y W a n d V i e w %
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 % DestroyWandView() deallocates memory associated with a wand view.
172 % The format of the DestroyWandView method is:
174 % WandView *DestroyWandView(WandView *wand_view)
176 % A description of each parameter follows:
178 % o wand_view: the wand view.
182 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
183 const size_t number_wands,const size_t number_threads)
188 assert(pixel_wands != (PixelWand ***) NULL);
189 for (i=0; i < (ssize_t) number_threads; i++)
190 if (pixel_wands[i] != (PixelWand **) NULL)
191 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
192 pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
196 WandExport WandView *DestroyWandView(WandView *wand_view)
198 assert(wand_view != (WandView *) NULL);
199 assert(wand_view->signature == WandSignature);
200 wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands,
201 wand_view->extent.width,wand_view->number_threads);
202 wand_view->image=DestroyImage(wand_view->image);
203 wand_view->view=DestroyCacheView(wand_view->view);
204 wand_view->exception=DestroyExceptionInfo(wand_view->exception);
205 wand_view->signature=(~WandSignature);
206 RelinquishWandId(wand_view->id);
207 wand_view=(WandView *) RelinquishMagickMemory(wand_view);
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 % 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 %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 % DuplexTransferWandViewIterator() iterates over three wand views in
223 % parallel and calls your transfer method for each scanline of the view. The
224 % source and duplex pixel extent is not confined to the image canvas-- that is
225 % you can include negative offsets or widths or heights that exceed the image
226 % dimension. However, the destination wand view is confined to the image
227 % canvas-- that is no negative offsets or widths or heights that exceed the
228 % image dimension are permitted.
230 % The callback signature is:
232 % MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
233 % const WandView *duplex,WandView *destination,const ssize_t y,
234 % const int thread_id,void *context)
236 % Use this pragma if the view is not single threaded:
238 % #pragma omp critical
240 % to define a section of code in your callback transfer method that must be
241 % executed by a single thread at a time.
243 % The format of the DuplexTransferWandViewIterator method is:
245 % MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
246 % WandView *duplex,WandView *destination,
247 % DuplexTransferWandViewMethod transfer,void *context)
249 % A description of each parameter follows:
251 % o source: the source wand view.
253 % o duplex: the duplex wand view.
255 % o destination: the destination wand view.
257 % o transfer: the transfer callback method.
259 % o context: the user defined context.
262 WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
263 WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
279 assert(source != (WandView *) NULL);
280 assert(source->signature == WandSignature);
281 if (transfer == (DuplexTransferWandViewMethod) NULL)
283 source_image=source->wand->images;
284 destination_image=destination->wand->images;
285 status=SetImageStorageClass(destination_image,DirectClass,
286 destination->exception);
287 if (status == MagickFalse)
291 #if defined(MAGICKCORE_OPENMP_SUPPORT)
292 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
294 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
297 id = GetOpenMPThreadId();
302 register const Quantum
303 *restrict duplex_pixels,
310 *restrict destination_pixels;
312 if (status == MagickFalse)
314 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
315 source->extent.width,1,source->exception);
316 if (pixels == (const Quantum *) NULL)
321 for (x=0; x < (ssize_t) source->extent.width; x++)
323 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
324 pixels+=GetPixelChannels(source->image);
326 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
327 duplex->extent.width,1,duplex->exception);
328 if (duplex_pixels == (const Quantum *) NULL)
333 for (x=0; x < (ssize_t) duplex->extent.width; x++)
335 PixelSetQuantumPixel(duplex->image,duplex_pixels,
336 duplex->pixel_wands[id][x]);
337 duplex_pixels+=GetPixelChannels(duplex->image);
339 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
340 destination->extent.x,y,destination->extent.width,1,
341 destination->exception);
342 if (destination_pixels == (Quantum *) NULL)
347 for (x=0; x < (ssize_t) destination->extent.width; x++)
349 PixelSetQuantumPixel(destination->image,destination_pixels,
350 destination->pixel_wands[id][x]);
351 destination_pixels+=GetPixelChannels(destination->image);
353 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
355 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
356 destination->extent.x,y,destination->extent.width,1,
357 destination->exception);
358 for (x=0; x < (ssize_t) destination->extent.width; x++)
360 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
362 destination_pixels+=GetPixelChannels(destination->image);
364 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
365 if (sync == MagickFalse)
367 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
372 #if defined(MAGICKCORE_OPENMP_SUPPORT)
373 #pragma omp critical (MagickWand_DuplexTransferWandViewIterator)
375 proceed=SetImageProgress(source_image,source->description,progress++,
376 source->extent.height);
377 if (proceed == MagickFalse)
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 % G e t W a n d V i e w E x c e p t i o n %
393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 % GetWandViewException() returns the severity, reason, and description of any
396 % error that occurs when utilizing a wand view.
398 % The format of the GetWandViewException method is:
400 % char *GetWandViewException(const PixelWand *wand_view,
401 % ExceptionType *severity)
403 % A description of each parameter follows:
405 % o wand_view: the pixel wand_view.
407 % o severity: the severity of the error is returned here.
410 WandExport char *GetWandViewException(const WandView *wand_view,
411 ExceptionType *severity)
416 assert(wand_view != (const WandView *) NULL);
417 assert(wand_view->signature == WandSignature);
418 if (wand_view->debug != MagickFalse)
419 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
420 assert(severity != (ExceptionType *) NULL);
421 *severity=wand_view->exception->severity;
422 description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
423 sizeof(*description));
424 if (description == (char *) NULL)
425 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
428 if (wand_view->exception->reason != (char *) NULL)
429 (void) CopyMagickString(description,GetLocaleExceptionMessage(
430 wand_view->exception->severity,wand_view->exception->reason),
432 if (wand_view->exception->description != (char *) NULL)
434 (void) ConcatenateMagickString(description," (",MaxTextExtent);
435 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
436 wand_view->exception->severity,wand_view->exception->description),
438 (void) ConcatenateMagickString(description,")",MaxTextExtent);
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 % G e t W a n d V i e w E x t e n t %
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 % GetWandViewExtent() returns the wand view extent.
456 % The format of the GetWandViewExtent method is:
458 % RectangleInfo GetWandViewExtent(const WandView *wand_view)
460 % A description of each parameter follows:
462 % o wand_view: the wand view.
465 WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
467 assert(wand_view != (WandView *) NULL);
468 assert(wand_view->signature == WandSignature);
469 return(wand_view->extent);
473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 % G e t W a n d V i e w I t e r a t o r %
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483 % GetWandViewIterator() iterates over the wand view in parallel and calls
484 % your get method for each scanline of the view. The pixel extent is
485 % not confined to the image canvas-- that is you can include negative offsets
486 % or widths or heights that exceed the image dimension. Any updates to
487 % the pixels in your callback are ignored.
489 % The callback signature is:
491 % MagickBooleanType GetImageViewMethod(const WandView *source,
492 % const ssize_t y,const int thread_id,void *context)
494 % Use this pragma if the view is not single threaded:
496 % #pragma omp critical
498 % to define a section of code in your callback get method that must be
499 % executed by a single thread at a time.
501 % The format of the GetWandViewIterator method is:
503 % MagickBooleanType GetWandViewIterator(WandView *source,
504 % GetWandViewMethod get,void *context)
506 % A description of each parameter follows:
508 % o source: the source wand view.
510 % o get: the get callback method.
512 % o context: the user defined context.
515 WandExport MagickBooleanType GetWandViewIterator(WandView *source,
516 GetWandViewMethod get,void *context)
530 assert(source != (WandView *) NULL);
531 assert(source->signature == WandSignature);
532 if (get == (GetWandViewMethod) NULL)
534 source_image=source->wand->images;
537 #if defined(MAGICKCORE_OPENMP_SUPPORT)
538 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
540 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
543 id = GetOpenMPThreadId();
545 register const Quantum
551 if (status == MagickFalse)
553 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
554 source->extent.width,1,source->exception);
555 if (pixels == (const Quantum *) NULL)
560 for (x=0; x < (ssize_t) source->extent.width; x++)
562 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
563 pixels+=GetPixelChannels(source->image);
565 if (get(source,y,id,context) == MagickFalse)
567 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
572 #if defined(MAGICKCORE_OPENMP_SUPPORT)
573 #pragma omp critical (MagickWand_GetWandViewIterator)
575 proceed=SetImageProgress(source_image,source->description,progress++,
576 source->extent.height);
577 if (proceed == MagickFalse)
585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 % G e t W a n d V i e w P i x e l s %
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595 % GetWandViewPixels() returns the wand view pixel_wands.
597 % The format of the GetWandViewPixels method is:
599 % PixelWand *GetWandViewPixels(const WandView *wand_view)
601 % A description of each parameter follows:
603 % o wand_view: the wand view.
606 WandExport PixelWand **GetWandViewPixels(const WandView *wand_view)
609 id = GetOpenMPThreadId();
611 assert(wand_view != (WandView *) NULL);
612 assert(wand_view->signature == WandSignature);
613 return(wand_view->pixel_wands[id]);
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621 % G e t W a n d V i e w W a n d %
625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 % GetWandViewWand() returns the magick wand associated with the wand view.
629 % The format of the GetWandViewWand method is:
631 % MagickWand *GetWandViewWand(const WandView *wand_view)
633 % A description of each parameter follows:
635 % o wand_view: the wand view.
638 WandExport MagickWand *GetWandViewWand(const WandView *wand_view)
640 assert(wand_view != (WandView *) NULL);
641 assert(wand_view->signature == WandSignature);
642 return(wand_view->wand);
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 % I s W a n d V i e w %
654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 % IsWandView() returns MagickTrue if the the parameter is verified as a wand
659 % The format of the IsWandView method is:
661 % MagickBooleanType IsWandView(const WandView *wand_view)
663 % A description of each parameter follows:
665 % o wand_view: the wand view.
668 WandExport MagickBooleanType IsWandView(const WandView *wand_view)
673 if (wand_view == (const WandView *) NULL)
675 if (wand_view->signature != WandSignature)
677 length=strlen(WandViewId);
678 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 % N e w W a n d V i e w %
692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694 % NewWandView() returns a wand view required for all other methods in the
697 % The format of the NewWandView method is:
699 % WandView *NewWandView(MagickWand *wand)
701 % A description of each parameter follows:
707 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands,
708 const size_t number_threads)
716 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
717 sizeof(*pixel_wands));
718 if (pixel_wands == (PixelWand ***) NULL)
719 return((PixelWand ***) NULL);
720 (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
721 for (i=0; i < (ssize_t) number_threads; i++)
723 pixel_wands[i]=NewPixelWands(number_wands);
724 if (pixel_wands[i] == (PixelWand **) NULL)
725 return(DestroyPixelsThreadSet(pixel_wands,number_wands,number_threads));
730 WandExport WandView *NewWandView(MagickWand *wand)
735 assert(wand != (MagickWand *) NULL);
736 assert(wand->signature == WandSignature);
737 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
738 if (wand_view == (WandView *) NULL)
739 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
740 GetExceptionMessage(errno));
741 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
742 wand_view->id=AcquireWandId();
743 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
744 WandViewId,(double) wand_view->id);
745 wand_view->description=ConstantString("WandView");
746 wand_view->wand=wand;
747 wand_view->view=AcquireCacheView(wand_view->wand->images);
748 wand_view->extent.width=wand->images->columns;
749 wand_view->extent.height=wand->images->rows;
750 wand_view->number_threads=GetOpenMPMaximumThreads();
751 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
752 wand_view->number_threads);
753 wand_view->exception=AcquireExceptionInfo();
754 if (wand_view->pixel_wands == (PixelWand ***) NULL)
755 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
756 GetExceptionMessage(errno));
757 wand_view->debug=IsEventLogging();
758 wand_view->signature=WandSignature;
763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 % N e w W a n d V i e w E x t e n t %
771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
773 % NewWandViewExtent() returns a wand view required for all other methods
774 % in the Wand View API.
776 % The format of the NewWandViewExtent method is:
778 % WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
779 % const ssize_t y,const size_t width,const size_t height)
781 % A description of each parameter follows:
783 % o wand: the magick wand.
785 % o x,y,columns,rows: These values define the perimeter of a extent of
789 WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
790 const ssize_t y,const size_t width,const size_t height)
795 assert(wand != (MagickWand *) NULL);
796 assert(wand->signature == WandSignature);
797 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
798 if (wand_view == (WandView *) NULL)
799 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
800 GetExceptionMessage(errno));
801 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
802 wand_view->id=AcquireWandId();
803 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
804 WandViewId,(double) wand_view->id);
805 wand_view->description=ConstantString("WandView");
806 wand_view->view=AcquireCacheView(wand_view->wand->images);
807 wand_view->wand=wand;
808 wand_view->extent.width=width;
809 wand_view->extent.height=height;
810 wand_view->extent.x=x;
811 wand_view->extent.y=y;
812 wand_view->number_threads=GetOpenMPMaximumThreads();
813 wand_view->exception=AcquireExceptionInfo();
814 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
815 wand_view->number_threads);
816 if (wand_view->pixel_wands == (PixelWand ***) NULL)
817 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
818 GetExceptionMessage(errno));
819 wand_view->debug=IsEventLogging();
820 wand_view->signature=WandSignature;
825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 % S e t W a n d V i e w D e s c r i p t i o n %
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 % SetWandViewDescription() associates a description with an image view.
837 % The format of the SetWandViewDescription method is:
839 % void SetWandViewDescription(WandView *image_view,const char *description)
841 % A description of each parameter follows:
843 % o wand_view: the wand view.
845 % o description: the wand view description.
848 MagickExport void SetWandViewDescription(WandView *wand_view,
849 const char *description)
851 assert(wand_view != (WandView *) NULL);
852 assert(wand_view->signature == WandSignature);
853 wand_view->description=ConstantString(description);
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 % S e t W a n d V i e w I t e r a t o r %
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867 % SetWandViewIterator() iterates over the wand view in parallel and calls
868 % your set method for each scanline of the view. The pixel extent is
869 % confined to the image canvas-- that is no negative offsets or widths or
870 % heights that exceed the image dimension. The pixels are initiallly
871 % undefined and any settings you make in the callback method are automagically
872 % synced back to your image.
874 % The callback signature is:
876 % MagickBooleanType SetImageViewMethod(ImageView *destination,
877 % const ssize_t y,const int thread_id,void *context)
879 % Use this pragma if the view is not single threaded:
881 % #pragma omp critical
883 % to define a section of code in your callback set method that must be
884 % executed by a single thread at a time.
886 % The format of the SetWandViewIterator method is:
888 % MagickBooleanType SetWandViewIterator(WandView *destination,
889 % SetWandViewMethod set,void *context)
891 % A description of each parameter follows:
893 % o destination: the wand view.
895 % o set: the set callback method.
897 % o context: the user defined context.
900 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
901 SetWandViewMethod set,void *context)
915 assert(destination != (WandView *) NULL);
916 assert(destination->signature == WandSignature);
917 if (set == (SetWandViewMethod) NULL)
919 destination_image=destination->wand->images;
920 status=SetImageStorageClass(destination_image,DirectClass,
921 destination->exception);
922 if (status == MagickFalse)
926 #if defined(MAGICKCORE_OPENMP_SUPPORT)
927 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(destination->number_threads)
929 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
932 id = GetOpenMPThreadId();
943 if (status == MagickFalse)
945 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
946 y,destination->extent.width,1,destination->exception);
947 if (pixels == (Quantum *) NULL)
952 if (set(destination,y,id,context) == MagickFalse)
954 for (x=0; x < (ssize_t) destination->extent.width; x++)
956 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
958 pixels+=GetPixelChannels(destination->image);
960 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
961 if (sync == MagickFalse)
963 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
968 #if defined(MAGICKCORE_OPENMP_SUPPORT)
969 #pragma omp critical (MagickWand_SetWandViewIterator)
971 proceed=SetImageProgress(destination_image,destination->description,
972 progress++,destination->extent.height);
973 if (proceed == MagickFalse)
981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 % S e t W a n d V i e w T h r e a d s %
989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 % SetWandViewThreads() sets the number of threads in a thread team.
993 % The format of the SetWandViewDescription method is:
995 % void SetWandViewThreads(WandView *image_view,
996 % const size_t number_threads)
998 % A description of each parameter follows:
1000 % o image_view: the image view.
1002 % o number_threads: the number of threads in a thread team.
1005 MagickExport void SetWandViewThreads(WandView *image_view,
1006 const size_t number_threads)
1008 assert(image_view != (WandView *) NULL);
1009 assert(image_view->signature == MagickSignature);
1010 image_view->number_threads=number_threads;
1011 if (number_threads > GetOpenMPMaximumThreads())
1012 image_view->number_threads=GetOpenMPMaximumThreads();
1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1020 % T r a n s f e r W a n d V i e w I t e r a t o r %
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 % TransferWandViewIterator() iterates over two wand views in parallel and
1027 % calls your transfer method for each scanline of the view. The source pixel
1028 % extent is not confined to the image canvas-- that is you can include
1029 % negative offsets or widths or heights that exceed the image dimension.
1030 % However, the destination wand view is confined to the image canvas-- that
1031 % is no negative offsets or widths or heights that exceed the image dimension
1034 % The callback signature is:
1036 % MagickBooleanType TransferImageViewMethod(const WandView *source,
1037 % WandView *destination,const ssize_t y,const int thread_id,
1040 % Use this pragma if the view is not single threaded:
1042 % #pragma omp critical
1044 % to define a section of code in your callback transfer method that must be
1045 % executed by a single thread at a time.
1047 % The format of the TransferWandViewIterator method is:
1049 % MagickBooleanType TransferWandViewIterator(WandView *source,
1050 % WandView *destination,TransferWandViewMethod transfer,void *context)
1052 % A description of each parameter follows:
1054 % o source: the source wand view.
1056 % o destination: the destination wand view.
1058 % o transfer: the transfer callback method.
1060 % o context: the user defined context.
1063 WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
1064 WandView *destination,TransferWandViewMethod transfer,void *context)
1079 assert(source != (WandView *) NULL);
1080 assert(source->signature == WandSignature);
1081 if (transfer == (TransferWandViewMethod) NULL)
1082 return(MagickFalse);
1083 source_image=source->wand->images;
1084 destination_image=destination->wand->images;
1085 status=SetImageStorageClass(destination_image,DirectClass,
1086 destination->exception);
1087 if (status == MagickFalse)
1088 return(MagickFalse);
1091 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1092 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
1094 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1097 id = GetOpenMPThreadId();
1102 register const Quantum
1109 *restrict destination_pixels;
1111 if (status == MagickFalse)
1113 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1114 source->extent.width,1,source->exception);
1115 if (pixels == (const Quantum *) NULL)
1120 for (x=0; x < (ssize_t) source->extent.width; x++)
1122 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1123 pixels+=GetPixelChannels(source->image);
1125 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1126 destination->extent.x,y,destination->extent.width,1,
1127 destination->exception);
1128 if (destination_pixels == (Quantum *) NULL)
1133 for (x=0; x < (ssize_t) destination->extent.width; x++)
1135 PixelSetQuantumPixel(destination->image,destination_pixels,
1136 destination->pixel_wands[id][x]);
1137 destination_pixels+=GetPixelChannels(destination->image);
1139 if (transfer(source,destination,y,id,context) == MagickFalse)
1141 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1142 destination->extent.x,y,destination->extent.width,1,
1143 destination->exception);
1144 for (x=0; x < (ssize_t) destination->extent.width; x++)
1146 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1147 destination_pixels);
1148 destination_pixels+=GetPixelChannels(destination->image);
1150 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1151 if (sync == MagickFalse)
1153 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1158 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1159 #pragma omp critical (MagickWand_TransferWandViewIterator)
1161 proceed=SetImageProgress(source_image,source->description,progress++,
1162 source->extent.height);
1163 if (proceed == MagickFalse)
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1175 % U p d a t e W a n d V i e w I t e r a t o r %
1179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1181 % UpdateWandViewIterator() iterates over the wand view in parallel and calls
1182 % your update method for each scanline of the view. The pixel extent is
1183 % confined to the image canvas-- that is no negative offsets or widths or
1184 % heights that exceed the image dimension are permitted. Updates to pixels
1185 % in your callback are automagically synced back to the image.
1187 % The callback signature is:
1189 % MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
1190 % const int thread_id,void *context)
1192 % Use this pragma if the view is not single threaded:
1194 % #pragma omp critical
1196 % to define a section of code in your callback update method that must be
1197 % executed by a single thread at a time.
1199 % The format of the UpdateWandViewIterator method is:
1201 % MagickBooleanType UpdateWandViewIterator(WandView *source,
1202 % UpdateWandViewMethod update,void *context)
1204 % A description of each parameter follows:
1206 % o source: the source wand view.
1208 % o update: the update callback method.
1210 % o context: the user defined context.
1213 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
1214 UpdateWandViewMethod update,void *context)
1228 assert(source != (WandView *) NULL);
1229 assert(source->signature == WandSignature);
1230 if (update == (UpdateWandViewMethod) NULL)
1231 return(MagickFalse);
1232 source_image=source->wand->images;
1233 status=SetImageStorageClass(source_image,DirectClass,source->exception);
1234 if (status == MagickFalse)
1235 return(MagickFalse);
1238 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1239 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
1241 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1244 id = GetOpenMPThreadId();
1255 if (status == MagickFalse)
1257 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1258 source->extent.width,1,source->exception);
1259 if (pixels == (Quantum *) NULL)
1264 for (x=0; x < (ssize_t) source->extent.width; x++)
1266 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1267 pixels+=GetPixelChannels(source->image);
1269 if (update(source,y,id,context) == MagickFalse)
1271 for (x=0; x < (ssize_t) source->extent.width; x++)
1273 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
1274 pixels+=GetPixelChannels(source->image);
1276 sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
1277 if (sync == MagickFalse)
1279 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1284 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1285 #pragma omp critical (MagickWand_UpdateWandViewIterator)
1287 proceed=SetImageProgress(source_image,source->description,progress++,
1288 source->extent.height);
1289 if (proceed == MagickFalse)