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"
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) 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 WandView *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) 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)
738 assert(wand != (MagickWand *) NULL);
739 assert(wand->signature == WandSignature);
740 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
741 if (wand_view == (WandView *) NULL)
742 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
743 GetExceptionMessage(errno));
744 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
745 wand_view->id=AcquireWandId();
746 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
747 WandViewId,(double) wand_view->id);
748 wand_view->description=ConstantString("WandView");
749 wand_view->wand=wand;
750 exception=AcquireExceptionInfo();
751 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
752 wand_view->extent.width=wand->images->columns;
753 wand_view->extent.height=wand->images->rows;
754 wand_view->number_threads=GetOpenMPMaximumThreads();
755 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
756 wand_view->number_threads);
757 wand_view->exception=exception;
758 if (wand_view->pixel_wands == (PixelWand ***) NULL)
759 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
760 GetExceptionMessage(errno));
761 wand_view->debug=IsEventLogging();
762 wand_view->signature=WandSignature;
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771 % N e w W a n d V i e w E x t e n t %
775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
777 % NewWandViewExtent() returns a wand view required for all other methods
778 % in the Wand View API.
780 % The format of the NewWandViewExtent method is:
782 % WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
783 % const ssize_t y,const size_t width,const size_t height)
785 % A description of each parameter follows:
787 % o wand: the magick wand.
789 % o x,y,columns,rows: These values define the perimeter of a extent of
793 WandExport WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
794 const ssize_t y,const size_t width,const size_t height)
802 assert(wand != (MagickWand *) NULL);
803 assert(wand->signature == WandSignature);
804 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
805 if (wand_view == (WandView *) NULL)
806 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
807 GetExceptionMessage(errno));
808 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
809 wand_view->id=AcquireWandId();
810 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
811 WandViewId,(double) wand_view->id);
812 wand_view->description=ConstantString("WandView");
813 exception=AcquireExceptionInfo();
814 wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
815 wand_view->wand=wand;
816 wand_view->extent.width=width;
817 wand_view->extent.height=height;
818 wand_view->extent.x=x;
819 wand_view->extent.y=y;
820 wand_view->number_threads=GetOpenMPMaximumThreads();
821 wand_view->exception=exception;
822 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
823 wand_view->number_threads);
824 if (wand_view->pixel_wands == (PixelWand ***) NULL)
825 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
826 GetExceptionMessage(errno));
827 wand_view->debug=IsEventLogging();
828 wand_view->signature=WandSignature;
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 % S e t W a n d V i e w D e s c r i p t i o n %
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843 % SetWandViewDescription() associates a description with an image view.
845 % The format of the SetWandViewDescription method is:
847 % void SetWandViewDescription(WandView *image_view,const char *description)
849 % A description of each parameter follows:
851 % o wand_view: the wand view.
853 % o description: the wand view description.
856 MagickExport void SetWandViewDescription(WandView *wand_view,
857 const char *description)
859 assert(wand_view != (WandView *) NULL);
860 assert(wand_view->signature == WandSignature);
861 wand_view->description=ConstantString(description);
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869 % S e t W a n d V i e w I t e r a t o r %
873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875 % SetWandViewIterator() iterates over the wand view in parallel and calls
876 % your set method for each scanline of the view. The pixel extent is
877 % confined to the image canvas-- that is no negative offsets or widths or
878 % heights that exceed the image dimension. The pixels are initiallly
879 % undefined and any settings you make in the callback method are automagically
880 % synced back to your image.
882 % The callback signature is:
884 % MagickBooleanType SetImageViewMethod(ImageView *destination,
885 % const ssize_t y,const int thread_id,void *context)
887 % Use this pragma if the view is not single threaded:
889 % #pragma omp critical
891 % to define a section of code in your callback set method that must be
892 % executed by a single thread at a time.
894 % The format of the SetWandViewIterator method is:
896 % MagickBooleanType SetWandViewIterator(WandView *destination,
897 % SetWandViewMethod set,void *context)
899 % A description of each parameter follows:
901 % o destination: the wand view.
903 % o set: the set callback method.
905 % o context: the user defined context.
908 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
909 SetWandViewMethod set,void *context)
923 assert(destination != (WandView *) NULL);
924 assert(destination->signature == WandSignature);
925 if (set == (SetWandViewMethod) NULL)
927 destination_image=destination->wand->images;
928 status=SetImageStorageClass(destination_image,DirectClass,
929 destination->exception);
930 if (status == MagickFalse)
934 #if defined(MAGICKCORE_OPENMP_SUPPORT)
935 #pragma omp parallel for schedule(static) shared(progress,status) num_threads(destination->number_threads)
937 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
940 id = GetOpenMPThreadId();
951 if (status == MagickFalse)
953 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
954 y,destination->extent.width,1,destination->exception);
955 if (pixels == (Quantum *) NULL)
960 if (set(destination,y,id,context) == MagickFalse)
962 for (x=0; x < (ssize_t) destination->extent.width; x++)
964 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
966 pixels+=GetPixelChannels(destination->image);
968 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
969 if (sync == MagickFalse)
971 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
976 #if defined(MAGICKCORE_OPENMP_SUPPORT)
977 #pragma omp critical (MagickWand_SetWandViewIterator)
979 proceed=SetImageProgress(destination_image,destination->description,
980 progress++,destination->extent.height);
981 if (proceed == MagickFalse)
989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
993 % S e t W a n d V i e w T h r e a d s %
997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999 % SetWandViewThreads() sets the number of threads in a thread team.
1001 % The format of the SetWandViewDescription method is:
1003 % void SetWandViewThreads(WandView *image_view,
1004 % const size_t number_threads)
1006 % A description of each parameter follows:
1008 % o image_view: the image view.
1010 % o number_threads: the number of threads in a thread team.
1013 MagickExport void SetWandViewThreads(WandView *image_view,
1014 const size_t number_threads)
1016 assert(image_view != (WandView *) NULL);
1017 assert(image_view->signature == MagickSignature);
1018 image_view->number_threads=number_threads;
1019 if (number_threads > GetOpenMPMaximumThreads())
1020 image_view->number_threads=GetOpenMPMaximumThreads();
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1028 % T r a n s f e r W a n d V i e w I t e r a t o r %
1032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 % TransferWandViewIterator() iterates over two wand views in parallel and
1035 % calls your transfer method for each scanline of the view. The source pixel
1036 % extent is not confined to the image canvas-- that is you can include
1037 % negative offsets or widths or heights that exceed the image dimension.
1038 % However, the destination wand view is confined to the image canvas-- that
1039 % is no negative offsets or widths or heights that exceed the image dimension
1042 % The callback signature is:
1044 % MagickBooleanType TransferImageViewMethod(const WandView *source,
1045 % WandView *destination,const ssize_t y,const int thread_id,
1048 % Use this pragma if the view is not single threaded:
1050 % #pragma omp critical
1052 % to define a section of code in your callback transfer method that must be
1053 % executed by a single thread at a time.
1055 % The format of the TransferWandViewIterator method is:
1057 % MagickBooleanType TransferWandViewIterator(WandView *source,
1058 % WandView *destination,TransferWandViewMethod transfer,void *context)
1060 % A description of each parameter follows:
1062 % o source: the source wand view.
1064 % o destination: the destination wand view.
1066 % o transfer: the transfer callback method.
1068 % o context: the user defined context.
1071 WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
1072 WandView *destination,TransferWandViewMethod transfer,void *context)
1087 assert(source != (WandView *) NULL);
1088 assert(source->signature == WandSignature);
1089 if (transfer == (TransferWandViewMethod) NULL)
1090 return(MagickFalse);
1091 source_image=source->wand->images;
1092 destination_image=destination->wand->images;
1093 status=SetImageStorageClass(destination_image,DirectClass,
1094 destination->exception);
1095 if (status == MagickFalse)
1096 return(MagickFalse);
1099 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1100 #pragma omp parallel for schedule(static) shared(progress,status) num_threads(source->number_threads)
1102 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1105 id = GetOpenMPThreadId();
1110 register const Quantum
1117 *restrict destination_pixels;
1119 if (status == MagickFalse)
1121 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1122 source->extent.width,1,source->exception);
1123 if (pixels == (const Quantum *) NULL)
1128 for (x=0; x < (ssize_t) source->extent.width; x++)
1130 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1131 pixels+=GetPixelChannels(source->image);
1133 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1134 destination->extent.x,y,destination->extent.width,1,
1135 destination->exception);
1136 if (destination_pixels == (Quantum *) NULL)
1141 for (x=0; x < (ssize_t) destination->extent.width; x++)
1143 PixelSetQuantumPixel(destination->image,destination_pixels,
1144 destination->pixel_wands[id][x]);
1145 destination_pixels+=GetPixelChannels(destination->image);
1147 if (transfer(source,destination,y,id,context) == MagickFalse)
1149 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1150 destination->extent.x,y,destination->extent.width,1,
1151 destination->exception);
1152 for (x=0; x < (ssize_t) destination->extent.width; x++)
1154 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1155 destination_pixels);
1156 destination_pixels+=GetPixelChannels(destination->image);
1158 sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1159 if (sync == MagickFalse)
1161 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1166 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1167 #pragma omp critical (MagickWand_TransferWandViewIterator)
1169 proceed=SetImageProgress(source_image,source->description,progress++,
1170 source->extent.height);
1171 if (proceed == MagickFalse)
1179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 % U p d a t e W a n d V i e w I t e r a t o r %
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189 % UpdateWandViewIterator() iterates over the wand view in parallel and calls
1190 % your update method for each scanline of the view. The pixel extent is
1191 % confined to the image canvas-- that is no negative offsets or widths or
1192 % heights that exceed the image dimension are permitted. Updates to pixels
1193 % in your callback are automagically synced back to the image.
1195 % The callback signature is:
1197 % MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
1198 % const int thread_id,void *context)
1200 % Use this pragma if the view is not single threaded:
1202 % #pragma omp critical
1204 % to define a section of code in your callback update method that must be
1205 % executed by a single thread at a time.
1207 % The format of the UpdateWandViewIterator method is:
1209 % MagickBooleanType UpdateWandViewIterator(WandView *source,
1210 % UpdateWandViewMethod update,void *context)
1212 % A description of each parameter follows:
1214 % o source: the source wand view.
1216 % o update: the update callback method.
1218 % o context: the user defined context.
1221 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
1222 UpdateWandViewMethod update,void *context)
1236 assert(source != (WandView *) NULL);
1237 assert(source->signature == WandSignature);
1238 if (update == (UpdateWandViewMethod) NULL)
1239 return(MagickFalse);
1240 source_image=source->wand->images;
1241 status=SetImageStorageClass(source_image,DirectClass,source->exception);
1242 if (status == MagickFalse)
1243 return(MagickFalse);
1246 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1247 #pragma omp parallel for schedule(static) shared(progress,status) num_threads(source->number_threads)
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)