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,
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 height=source->extent.height-source->extent.y;
292 width=source->extent.width-source->extent.x;
293 #if defined(MAGICKCORE_OPENMP_SUPPORT)
294 #pragma omp parallel for schedule(static) shared(progress,status) \
295 if ((height*width) > 8192) \
296 num_threads(GetMagickResourceLimit(ThreadResource))
298 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
301 id = GetOpenMPThreadId();
306 register const Quantum
307 *restrict duplex_pixels,
314 *restrict destination_pixels;
316 if (status == MagickFalse)
318 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
319 source->extent.width,1,source->exception);
320 if (pixels == (const Quantum *) NULL)
325 for (x=0; x < (ssize_t) source->extent.width; x++)
327 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
328 pixels+=GetPixelChannels(source->image);
330 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
331 duplex->extent.width,1,duplex->exception);
332 if (duplex_pixels == (const Quantum *) NULL)
337 for (x=0; x < (ssize_t) duplex->extent.width; x++)
339 PixelSetQuantumPixel(duplex->image,duplex_pixels,
340 duplex->pixel_wands[id][x]);
341 duplex_pixels+=GetPixelChannels(duplex->image);
343 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
344 destination->extent.x,y,destination->extent.width,1,
345 destination->exception);
346 if (destination_pixels == (Quantum *) NULL)
351 for (x=0; x < (ssize_t) destination->extent.width; x++)
353 PixelSetQuantumPixel(destination->image,destination_pixels,
354 destination->pixel_wands[id][x]);
355 destination_pixels+=GetPixelChannels(destination->image);
357 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
359 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
360 destination->extent.x,y,destination->extent.width,1,
361 destination->exception);
362 for (x=0; x < (ssize_t) destination->extent.width; x++)
364 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
366 destination_pixels+=GetPixelChannels(destination->image);
368 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
369 if (sync == MagickFalse)
371 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
376 #if defined(MAGICKCORE_OPENMP_SUPPORT)
377 #pragma omp critical (MagickWand_DuplexTransferWandViewIterator)
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 == WandSignature);
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*MaxTextExtent,
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," (",MaxTextExtent);
439 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
440 wand_view->exception->severity,wand_view->exception->description),
442 (void) ConcatenateMagickString(description,")",MaxTextExtent);
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 == WandSignature);
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)
538 assert(source != (WandView *) NULL);
539 assert(source->signature == WandSignature);
540 if (get == (GetWandViewMethod) NULL)
542 source_image=source->wand->images;
545 height=source->extent.height-source->extent.y;
546 width=source->extent.width-source->extent.x;
547 #if defined(MAGICKCORE_OPENMP_SUPPORT)
548 #pragma omp parallel for schedule(static) shared(progress,status) \
549 if ((height*width) > 8192) \
550 num_threads(GetMagickResourceLimit(ThreadResource))
552 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
555 id = GetOpenMPThreadId();
557 register const Quantum
563 if (status == MagickFalse)
565 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
566 source->extent.width,1,source->exception);
567 if (pixels == (const Quantum *) NULL)
572 for (x=0; x < (ssize_t) source->extent.width; x++)
574 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
575 pixels+=GetPixelChannels(source->image);
577 if (get(source,y,id,context) == MagickFalse)
579 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
584 #if defined(MAGICKCORE_OPENMP_SUPPORT)
585 #pragma omp critical (MagickWand_GetWandViewIterator)
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 == WandSignature);
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 == WandSignature);
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 != WandSignature)
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=(size_t) GetMagickResourceLimit(ThreadResource);
731 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
732 sizeof(*pixel_wands));
733 if (pixel_wands == (PixelWand ***) NULL)
734 return((PixelWand ***) NULL);
735 (void) ResetMagickMemory(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 == WandSignature);
755 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
756 if (wand_view == (WandView *) NULL)
757 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
758 GetExceptionMessage(errno));
759 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
760 wand_view->id=AcquireWandId();
761 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%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=WandSignature;
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 == WandSignature);
817 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
818 if (wand_view == (WandView *) NULL)
819 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
820 GetExceptionMessage(errno));
821 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
822 wand_view->id=AcquireWandId();
823 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%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=WandSignature;
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 == WandSignature);
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)
938 assert(destination != (WandView *) NULL);
939 assert(destination->signature == WandSignature);
940 if (set == (SetWandViewMethod) NULL)
942 destination_image=destination->wand->images;
943 status=SetImageStorageClass(destination_image,DirectClass,
944 destination->exception);
945 if (status == MagickFalse)
949 height=destination->extent.height-destination->extent.y;
950 width=destination->extent.width-destination->extent.x;
951 #if defined(MAGICKCORE_OPENMP_SUPPORT)
952 #pragma omp parallel for schedule(static) shared(progress,status) \
953 if ((height*width) > 8192) \
954 num_threads(GetMagickResourceLimit(ThreadResource))
956 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
959 id = GetOpenMPThreadId();
970 if (status == MagickFalse)
972 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
973 y,destination->extent.width,1,destination->exception);
974 if (pixels == (Quantum *) NULL)
979 if (set(destination,y,id,context) == MagickFalse)
981 for (x=0; x < (ssize_t) destination->extent.width; x++)
983 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
985 pixels+=GetPixelChannels(destination->image);
987 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
988 if (sync == MagickFalse)
990 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
995 #if defined(MAGICKCORE_OPENMP_SUPPORT)
996 #pragma omp critical (MagickWand_SetWandViewIterator)
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)
1075 assert(source != (WandView *) NULL);
1076 assert(source->signature == WandSignature);
1077 if (transfer == (TransferWandViewMethod) NULL)
1078 return(MagickFalse);
1079 source_image=source->wand->images;
1080 destination_image=destination->wand->images;
1081 status=SetImageStorageClass(destination_image,DirectClass,
1082 destination->exception);
1083 if (status == MagickFalse)
1084 return(MagickFalse);
1087 height=source->extent.height-source->extent.y;
1088 width=source->extent.width-source->extent.x;
1089 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1090 #pragma omp parallel for schedule(static) shared(progress,status) \
1091 if ((height*width) > 8192) \
1092 num_threads(GetMagickResourceLimit(ThreadResource))
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)
1232 assert(source != (WandView *) NULL);
1233 assert(source->signature == WandSignature);
1234 if (update == (UpdateWandViewMethod) NULL)
1235 return(MagickFalse);
1236 source_image=source->wand->images;
1237 status=SetImageStorageClass(source_image,DirectClass,source->exception);
1238 if (status == MagickFalse)
1239 return(MagickFalse);
1242 height=source->extent.height-source->extent.y;
1243 width=source->extent.width-source->extent.x;
1244 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1245 #pragma omp parallel for schedule(static) shared(progress,status) \
1246 if ((height*width) > 8192) \
1247 num_threads(GetMagickResourceLimit(ThreadResource))
1249 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1252 id = GetOpenMPThreadId();
1263 if (status == MagickFalse)
1265 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1266 source->extent.width,1,source->exception);
1267 if (pixels == (Quantum *) NULL)
1272 for (x=0; x < (ssize_t) source->extent.width; x++)
1274 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1275 pixels+=GetPixelChannels(source->image);
1277 if (update(source,y,id,context) == MagickFalse)
1279 for (x=0; x < (ssize_t) source->extent.width; x++)
1281 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
1282 pixels+=GetPixelChannels(source->image);
1284 sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
1285 if (sync == MagickFalse)
1287 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1292 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1293 #pragma omp critical (MagickWand_UpdateWandViewIterator)
1295 proceed=SetImageProgress(source_image,source->description,progress++,
1296 source->extent.height);
1297 if (proceed == MagickFalse)