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-2019 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 % https://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"
68 name[MagickPathExtent],
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 == MagickWandSignature);
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) memset(clone_view,0,sizeof(*clone_view));
135 clone_view->id=AcquireWandId();
136 (void) FormatLocaleString(clone_view->name,MagickPathExtent,"%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=MagickWandSignature;
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 == MagickWandSignature);
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=(~MagickWandSignature);
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)
280 assert(source != (WandView *) NULL);
281 assert(source->signature == MagickWandSignature);
282 if (transfer == (DuplexTransferWandViewMethod) NULL)
284 source_image=source->wand->images;
285 destination_image=destination->wand->images;
286 status=SetImageStorageClass(destination_image,DirectClass,
287 destination->exception);
288 if (status == MagickFalse)
292 #if defined(MAGICKCORE_OPENMP_SUPPORT)
293 height=source->extent.height-source->extent.y;
294 #pragma omp parallel for schedule(static) shared(progress,status) \
295 magick_number_threads(source_image,destination_image,height,1)
297 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
300 id = GetOpenMPThreadId();
305 register const Quantum
306 *magick_restrict duplex_pixels,
307 *magick_restrict pixels;
313 *magick_restrict destination_pixels;
315 if (status == MagickFalse)
317 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
318 source->extent.width,1,source->exception);
319 if (pixels == (const Quantum *) NULL)
324 for (x=0; x < (ssize_t) source->extent.width; x++)
326 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
327 pixels+=GetPixelChannels(source->image);
329 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
330 duplex->extent.width,1,duplex->exception);
331 if (duplex_pixels == (const Quantum *) NULL)
336 for (x=0; x < (ssize_t) duplex->extent.width; x++)
338 PixelSetQuantumPixel(duplex->image,duplex_pixels,
339 duplex->pixel_wands[id][x]);
340 duplex_pixels+=GetPixelChannels(duplex->image);
342 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
343 destination->extent.x,y,destination->extent.width,1,
344 destination->exception);
345 if (destination_pixels == (Quantum *) NULL)
350 for (x=0; x < (ssize_t) destination->extent.width; x++)
352 PixelSetQuantumPixel(destination->image,destination_pixels,
353 destination->pixel_wands[id][x]);
354 destination_pixels+=GetPixelChannels(destination->image);
356 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
358 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
359 destination->extent.x,y,destination->extent.width,1,
360 destination->exception);
361 for (x=0; x < (ssize_t) destination->extent.width; x++)
363 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
365 destination_pixels+=GetPixelChannels(destination->image);
367 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
368 if (sync == MagickFalse)
370 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
375 #if defined(MAGICKCORE_OPENMP_SUPPORT)
379 proceed=SetImageProgress(source_image,source->description,progress,
380 source->extent.height);
381 if (proceed == MagickFalse)
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 % G e t W a n d V i e w E x c e p t i o n %
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 % GetWandViewException() returns the severity, reason, and description of any
400 % error that occurs when utilizing a wand view.
402 % The format of the GetWandViewException method is:
404 % char *GetWandViewException(const WandView *wand_view,
405 % ExceptionType *severity)
407 % A description of each parameter follows:
409 % o wand_view: the pixel wand_view.
411 % o severity: the severity of the error is returned here.
414 WandExport char *GetWandViewException(const WandView *wand_view,
415 ExceptionType *severity)
420 assert(wand_view != (const WandView *) NULL);
421 assert(wand_view->signature == MagickWandSignature);
422 if (wand_view->debug != MagickFalse)
423 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
424 assert(severity != (ExceptionType *) NULL);
425 *severity=wand_view->exception->severity;
426 description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
427 sizeof(*description));
428 if (description == (char *) NULL)
429 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
432 if (wand_view->exception->reason != (char *) NULL)
433 (void) CopyMagickString(description,GetLocaleExceptionMessage(
434 wand_view->exception->severity,wand_view->exception->reason),
436 if (wand_view->exception->description != (char *) NULL)
438 (void) ConcatenateMagickString(description," (",MagickPathExtent);
439 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
440 wand_view->exception->severity,wand_view->exception->description),
442 (void) ConcatenateMagickString(description,")",MagickPathExtent);
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
452 % G e t W a n d V i e w E x t e n t %
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458 % GetWandViewExtent() returns the wand view extent.
460 % The format of the GetWandViewExtent method is:
462 % RectangleInfo GetWandViewExtent(const WandView *wand_view)
464 % A description of each parameter follows:
466 % o wand_view: the wand view.
469 WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
471 assert(wand_view != (WandView *) NULL);
472 assert(wand_view->signature == MagickWandSignature);
473 return(wand_view->extent);
477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 % G e t W a n d V i e w I t e r a t o r %
485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487 % GetWandViewIterator() iterates over the wand view in parallel and calls
488 % your get method for each scanline of the view. The pixel extent is
489 % not confined to the image canvas-- that is you can include negative offsets
490 % or widths or heights that exceed the image dimension. Any updates to
491 % the pixels in your callback are ignored.
493 % The callback signature is:
495 % MagickBooleanType GetImageViewMethod(const WandView *source,
496 % const ssize_t y,const int thread_id,void *context)
498 % Use this pragma if the view is not single threaded:
500 % #pragma omp critical
502 % to define a section of code in your callback get method that must be
503 % executed by a single thread at a time.
505 % The format of the GetWandViewIterator method is:
507 % MagickBooleanType GetWandViewIterator(WandView *source,
508 % GetWandViewMethod get,void *context)
510 % A description of each parameter follows:
512 % o source: the source wand view.
514 % o get: the get callback method.
516 % o context: the user defined context.
519 WandExport MagickBooleanType GetWandViewIterator(WandView *source,
520 GetWandViewMethod get,void *context)
531 #if defined(MAGICKCORE_OPENMP_SUPPORT)
539 assert(source != (WandView *) NULL);
540 assert(source->signature == MagickWandSignature);
541 if (get == (GetWandViewMethod) NULL)
543 source_image=source->wand->images;
546 #if defined(MAGICKCORE_OPENMP_SUPPORT)
547 height=source->extent.height-source->extent.y;
548 #pragma omp parallel for schedule(static) shared(progress,status) \
549 magick_number_threads(source_image,source_image,height,1)
551 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
554 id = GetOpenMPThreadId();
556 register const Quantum
562 if (status == MagickFalse)
564 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
565 source->extent.width,1,source->exception);
566 if (pixels == (const Quantum *) NULL)
571 for (x=0; x < (ssize_t) source->extent.width; x++)
573 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
574 pixels+=GetPixelChannels(source->image);
576 if (get(source,y,id,context) == MagickFalse)
578 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
583 #if defined(MAGICKCORE_OPENMP_SUPPORT)
587 proceed=SetImageProgress(source_image,source->description,progress,
588 source->extent.height);
589 if (proceed == MagickFalse)
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601 % G e t W a n d V i e w P i x e l s %
605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607 % GetWandViewPixels() returns the wand view pixel_wands.
609 % The format of the GetWandViewPixels method is:
611 % PixelWand *GetWandViewPixels(const WandView *wand_view)
613 % A description of each parameter follows:
615 % o wand_view: the wand view.
618 WandExport PixelWand **GetWandViewPixels(const WandView *wand_view)
621 id = GetOpenMPThreadId();
623 assert(wand_view != (WandView *) NULL);
624 assert(wand_view->signature == MagickWandSignature);
625 return(wand_view->pixel_wands[id]);
629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633 % G e t W a n d V i e w W a n d %
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 % GetWandViewWand() returns the magick wand associated with the wand view.
641 % The format of the GetWandViewWand method is:
643 % MagickWand *GetWandViewWand(const WandView *wand_view)
645 % A description of each parameter follows:
647 % o wand_view: the wand view.
650 WandExport MagickWand *GetWandViewWand(const WandView *wand_view)
652 assert(wand_view != (WandView *) NULL);
653 assert(wand_view->signature == MagickWandSignature);
654 return(wand_view->wand);
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662 % I s W a n d V i e w %
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668 % IsWandView() returns MagickTrue if the the parameter is verified as a wand
671 % The format of the IsWandView method is:
673 % MagickBooleanType IsWandView(const WandView *wand_view)
675 % A description of each parameter follows:
677 % o wand_view: the wand view.
680 WandExport MagickBooleanType IsWandView(const WandView *wand_view)
685 if (wand_view == (const WandView *) NULL)
687 if (wand_view->signature != MagickWandSignature)
689 length=strlen(WandViewId);
690 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
700 % N e w W a n d V i e w %
704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706 % NewWandView() returns a wand view required for all other methods in the
709 % The format of the NewWandView method is:
711 % WandView *NewWandView(MagickWand *wand)
713 % A description of each parameter follows:
719 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands)
730 number_threads=GetOpenMPMaximumThreads();
731 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
732 sizeof(*pixel_wands));
733 if (pixel_wands == (PixelWand ***) NULL)
734 return((PixelWand ***) NULL);
735 (void) memset(pixel_wands,0,number_threads*sizeof(*pixel_wands));
736 for (i=0; i < (ssize_t) number_threads; i++)
738 pixel_wands[i]=NewPixelWands(number_wands);
739 if (pixel_wands[i] == (PixelWand **) NULL)
740 return(DestroyPixelsThreadSet(pixel_wands,number_wands));
745 WandExport WandView *NewWandView(MagickWand *wand)
753 assert(wand != (MagickWand *) NULL);
754 assert(wand->signature == MagickWandSignature);
755 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
756 if (wand_view == (WandView *) NULL)
757 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
758 GetExceptionMessage(errno));
759 (void) memset(wand_view,0,sizeof(*wand_view));
760 wand_view->id=AcquireWandId();
761 (void) FormatLocaleString(wand_view->name,MagickPathExtent,"%s-%.20g",
762 WandViewId,(double) wand_view->id);
763 wand_view->description=ConstantString("WandView");
764 wand_view->wand=wand;
765 exception=AcquireExceptionInfo();
766 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
767 wand_view->extent.width=wand->images->columns;
768 wand_view->extent.height=wand->images->rows;
769 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
770 wand_view->exception=exception;
771 if (wand_view->pixel_wands == (PixelWand ***) NULL)
772 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
773 GetExceptionMessage(errno));
774 wand_view->debug=IsEventLogging();
775 wand_view->signature=MagickWandSignature;
780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784 % N e w W a n d V i e w E x t e n t %
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790 % NewWandViewExtent() returns a wand view required for all other methods
791 % in the Wand View API.
793 % The format of the NewWandViewExtent method is:
795 % WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
796 % const ssize_t y,const size_t width,const size_t height)
798 % A description of each parameter follows:
800 % o wand: the magick wand.
802 % o x,y,columns,rows: These values define the perimeter of a extent of
806 WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
807 const ssize_t y,const size_t width,const size_t height)
815 assert(wand != (MagickWand *) NULL);
816 assert(wand->signature == MagickWandSignature);
817 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
818 if (wand_view == (WandView *) NULL)
819 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
820 GetExceptionMessage(errno));
821 (void) memset(wand_view,0,sizeof(*wand_view));
822 wand_view->id=AcquireWandId();
823 (void) FormatLocaleString(wand_view->name,MagickPathExtent,"%s-%.20g",
824 WandViewId,(double) wand_view->id);
825 wand_view->description=ConstantString("WandView");
826 exception=AcquireExceptionInfo();
827 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
828 wand_view->wand=wand;
829 wand_view->extent.width=width;
830 wand_view->extent.height=height;
831 wand_view->extent.x=x;
832 wand_view->extent.y=y;
833 wand_view->exception=exception;
834 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
835 if (wand_view->pixel_wands == (PixelWand ***) NULL)
836 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
837 GetExceptionMessage(errno));
838 wand_view->debug=IsEventLogging();
839 wand_view->signature=MagickWandSignature;
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848 % S e t W a n d V i e w D e s c r i p t i o n %
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
854 % SetWandViewDescription() associates a description with an image view.
856 % The format of the SetWandViewDescription method is:
858 % void SetWandViewDescription(WandView *image_view,const char *description)
860 % A description of each parameter follows:
862 % o wand_view: the wand view.
864 % o description: the wand view description.
867 MagickExport void SetWandViewDescription(WandView *wand_view,
868 const char *description)
870 assert(wand_view != (WandView *) NULL);
871 assert(wand_view->signature == MagickWandSignature);
872 wand_view->description=ConstantString(description);
876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880 % S e t W a n d V i e w I t e r a t o r %
884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886 % SetWandViewIterator() iterates over the wand view in parallel and calls
887 % your set method for each scanline of the view. The pixel extent is
888 % confined to the image canvas-- that is no negative offsets or widths or
889 % heights that exceed the image dimension. The pixels are initiallly
890 % undefined and any settings you make in the callback method are automagically
891 % synced back to your image.
893 % The callback signature is:
895 % MagickBooleanType SetImageViewMethod(ImageView *destination,
896 % const ssize_t y,const int thread_id,void *context)
898 % Use this pragma if the view is not single threaded:
900 % #pragma omp critical
902 % to define a section of code in your callback set method that must be
903 % executed by a single thread at a time.
905 % The format of the SetWandViewIterator method is:
907 % MagickBooleanType SetWandViewIterator(WandView *destination,
908 % SetWandViewMethod set,void *context)
910 % A description of each parameter follows:
912 % o destination: the wand view.
914 % o set: the set callback method.
916 % o context: the user defined context.
919 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
920 SetWandViewMethod set,void *context)
931 #if defined(MAGICKCORE_OPENMP_SUPPORT)
939 assert(destination != (WandView *) NULL);
940 assert(destination->signature == MagickWandSignature);
941 if (set == (SetWandViewMethod) NULL)
943 destination_image=destination->wand->images;
944 status=SetImageStorageClass(destination_image,DirectClass,
945 destination->exception);
946 if (status == MagickFalse)
950 #if defined(MAGICKCORE_OPENMP_SUPPORT)
951 height=destination->extent.height-destination->extent.y;
952 #pragma omp parallel for schedule(static) shared(progress,status) \
953 magick_number_threads(destination_image,destination_image,height,1)
955 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
958 id = GetOpenMPThreadId();
967 *magick_restrict pixels;
969 if (status == MagickFalse)
971 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
972 y,destination->extent.width,1,destination->exception);
973 if (pixels == (Quantum *) NULL)
978 if (set(destination,y,id,context) == MagickFalse)
980 for (x=0; x < (ssize_t) destination->extent.width; x++)
982 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
984 pixels+=GetPixelChannels(destination->image);
986 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
987 if (sync == MagickFalse)
989 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
994 #if defined(MAGICKCORE_OPENMP_SUPPORT)
998 proceed=SetImageProgress(destination_image,destination->description,
999 progress,destination->extent.height);
1000 if (proceed == MagickFalse)
1008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 % T r a n s f e r W a n d V i e w I t e r a t o r %
1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 % TransferWandViewIterator() iterates over two wand views in parallel and
1019 % calls your transfer method for each scanline of the view. The source pixel
1020 % extent is not confined to the image canvas-- that is you can include
1021 % negative offsets or widths or heights that exceed the image dimension.
1022 % However, the destination wand view is confined to the image canvas-- that
1023 % is no negative offsets or widths or heights that exceed the image dimension
1026 % The callback signature is:
1028 % MagickBooleanType TransferImageViewMethod(const WandView *source,
1029 % WandView *destination,const ssize_t y,const int thread_id,
1032 % Use this pragma if the view is not single threaded:
1034 % #pragma omp critical
1036 % to define a section of code in your callback transfer method that must be
1037 % executed by a single thread at a time.
1039 % The format of the TransferWandViewIterator method is:
1041 % MagickBooleanType TransferWandViewIterator(WandView *source,
1042 % WandView *destination,TransferWandViewMethod transfer,void *context)
1044 % A description of each parameter follows:
1046 % o source: the source wand view.
1048 % o destination: the destination wand view.
1050 % o transfer: the transfer callback method.
1052 % o context: the user defined context.
1055 WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
1056 WandView *destination,TransferWandViewMethod transfer,void *context)
1068 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1076 assert(source != (WandView *) NULL);
1077 assert(source->signature == MagickWandSignature);
1078 if (transfer == (TransferWandViewMethod) NULL)
1079 return(MagickFalse);
1080 source_image=source->wand->images;
1081 destination_image=destination->wand->images;
1082 status=SetImageStorageClass(destination_image,DirectClass,
1083 destination->exception);
1084 if (status == MagickFalse)
1085 return(MagickFalse);
1088 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1089 height=source->extent.height-source->extent.y;
1090 #pragma omp parallel for schedule(static) shared(progress,status) \
1091 magick_number_threads(source_image,destination_image,height,1)
1093 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1096 id = GetOpenMPThreadId();
1101 register const Quantum
1102 *magick_restrict pixels;
1108 *magick_restrict destination_pixels;
1110 if (status == MagickFalse)
1112 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1113 source->extent.width,1,source->exception);
1114 if (pixels == (const Quantum *) NULL)
1119 for (x=0; x < (ssize_t) source->extent.width; x++)
1121 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1122 pixels+=GetPixelChannels(source->image);
1124 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1125 destination->extent.x,y,destination->extent.width,1,
1126 destination->exception);
1127 if (destination_pixels == (Quantum *) NULL)
1132 for (x=0; x < (ssize_t) destination->extent.width; x++)
1134 PixelSetQuantumPixel(destination->image,destination_pixels,
1135 destination->pixel_wands[id][x]);
1136 destination_pixels+=GetPixelChannels(destination->image);
1138 if (transfer(source,destination,y,id,context) == MagickFalse)
1140 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1141 destination->extent.x,y,destination->extent.width,1,
1142 destination->exception);
1143 for (x=0; x < (ssize_t) destination->extent.width; x++)
1145 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1146 destination_pixels);
1147 destination_pixels+=GetPixelChannels(destination->image);
1149 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1150 if (sync == MagickFalse)
1152 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1157 #if defined(MAGICKCORE_OPENMP_SUPPORT)
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)
1225 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1233 assert(source != (WandView *) NULL);
1234 assert(source->signature == MagickWandSignature);
1235 if (update == (UpdateWandViewMethod) NULL)
1236 return(MagickFalse);
1237 source_image=source->wand->images;
1238 status=SetImageStorageClass(source_image,DirectClass,source->exception);
1239 if (status == MagickFalse)
1240 return(MagickFalse);
1243 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1244 height=source->extent.height-source->extent.y;
1245 #pragma omp parallel for schedule(static) shared(progress,status) \
1246 magick_number_threads(source_image,source_image,height,1)
1248 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1251 id = GetOpenMPThreadId();
1260 *magick_restrict pixels;
1262 if (status == MagickFalse)
1264 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1265 source->extent.width,1,source->exception);
1266 if (pixels == (Quantum *) NULL)
1271 for (x=0; x < (ssize_t) source->extent.width; x++)
1273 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1274 pixels+=GetPixelChannels(source->image);
1276 if (update(source,y,id,context) == MagickFalse)
1278 for (x=0; x < (ssize_t) source->extent.width; x++)
1280 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
1281 pixels+=GetPixelChannels(source->image);
1283 sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
1284 if (sync == MagickFalse)
1286 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1291 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1295 proceed=SetImageProgress(source_image,source->description,progress,
1296 source->extent.height);
1297 if (proceed == MagickFalse)