2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 % W W W AAAAA N N N D D %
11 % V V IIIII EEEEE W W %
18 % MagickWand Wand View Methods %
25 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
31 % http://www.imagemagick.org/script/license.php %
33 % Unless required by applicable law or agreed to in writing, software %
34 % distributed under the License is distributed on an "AS IS" BASIS, %
35 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
36 % See the License for the specific language governing permissions and %
37 % limitations under the License. %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 #include "MagickWand/studio.h"
49 #include "MagickWand/MagickWand.h"
50 #include "MagickWand/magick-wand-private.h"
51 #include "MagickWand/wand.h"
52 #include "MagickCore/monitor-private.h"
53 #include "MagickCore/thread-private.h"
57 #define WandViewId "WandView"
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % C l o n e W a n d V i e w %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 % CloneWandView() makes a copy of the specified wand view.
112 % The format of the CloneWandView method is:
114 % WandView *CloneWandView(const WandView *wand_view)
116 % A description of each parameter follows:
118 % o wand_view: the wand view.
121 WandExport WandView *CloneWandView(const WandView *wand_view)
129 assert(wand_view != (WandView *) NULL);
130 assert(wand_view->signature == WandSignature);
131 if (wand_view->debug != MagickFalse)
132 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
133 clone_view=(WandView *) AcquireMagickMemory(sizeof(*clone_view));
134 if (clone_view == (WandView *) NULL)
135 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
137 (void) ResetMagickMemory(clone_view,0,sizeof(*clone_view));
138 clone_view->id=AcquireWandId();
139 (void) FormatLocaleString(clone_view->name,MaxTextExtent,"%s-%.20g",
140 WandViewId,(double) clone_view->id);
141 clone_view->description=ConstantString(wand_view->description);
142 clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
143 wand_view->exception);
144 clone_view->view=CloneCacheView(wand_view->view);
145 clone_view->extent=wand_view->extent;
146 clone_view->number_threads=wand_view->number_threads;
147 clone_view->exception=AcquireExceptionInfo();
148 InheritException(clone_view->exception,wand_view->exception);
149 for (i=0; i < (ssize_t) wand_view->number_threads; i++)
150 clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
151 wand_view->pixel_wands[i],wand_view->extent.width);
152 clone_view->debug=wand_view->debug;
153 if (clone_view->debug != MagickFalse)
154 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
155 clone_view->signature=WandSignature;
160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 % D e s t r o y W a n d V i e w %
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 % DestroyWandView() deallocates memory associated with a wand view.
172 % The format of the DestroyWandView method is:
174 % WandView *DestroyWandView(WandView *wand_view)
176 % A description of each parameter follows:
178 % o wand_view: the wand view.
182 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
183 const size_t number_wands,const size_t number_threads)
188 assert(pixel_wands != (PixelWand ***) NULL);
189 for (i=0; i < (ssize_t) number_threads; i++)
190 if (pixel_wands[i] != (PixelWand **) NULL)
191 pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
192 pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
196 WandExport WandView *DestroyWandView(WandView *wand_view)
198 assert(wand_view != (WandView *) NULL);
199 assert(wand_view->signature == WandSignature);
200 wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands,
201 wand_view->extent.width,wand_view->number_threads);
202 wand_view->image=DestroyImage(wand_view->image);
203 wand_view->view=DestroyCacheView(wand_view->view);
204 wand_view->exception=DestroyExceptionInfo(wand_view->exception);
205 wand_view->signature=(~WandSignature);
206 RelinquishWandId(wand_view->id);
207 wand_view=(WandView *) RelinquishMagickMemory(wand_view);
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 % D u p l e x T r a n s f e r W a n d V i e w I t e r a t o r %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 % DuplexTransferWandViewIterator() iterates over three wand views in
223 % parallel and calls your transfer method for each scanline of the view. The
224 % source and duplex pixel extent is not confined to the image canvas-- that is
225 % you can include negative offsets or widths or heights that exceed the image
226 % dimension. However, the destination wand view is confined to the image
227 % canvas-- that is no negative offsets or widths or heights that exceed the
228 % image dimension are permitted.
230 % The callback signature is:
232 % MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
233 % const WandView *duplex,WandView *destination,const ssize_t y,
234 % const int thread_id,void *context)
236 % Use this pragma if the view is not single threaded:
238 % #pragma omp critical
240 % to define a section of code in your callback transfer method that must be
241 % executed by a single thread at a time.
243 % The format of the DuplexTransferWandViewIterator method is:
245 % MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
246 % WandView *duplex,WandView *destination,
247 % DuplexTransferWandViewMethod transfer,void *context)
249 % A description of each parameter follows:
251 % o source: the source wand view.
253 % o duplex: the duplex wand view.
255 % o destination: the destination wand view.
257 % o transfer: the transfer callback method.
259 % o context: the user defined context.
262 WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
263 WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
282 assert(source != (WandView *) NULL);
283 assert(source->signature == WandSignature);
284 if (transfer == (DuplexTransferWandViewMethod) NULL)
286 source_image=source->wand->images;
287 destination_image=destination->wand->images;
288 exception=destination->exception;
289 if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
293 #if defined(MAGICKCORE_OPENMP_SUPPORT)
294 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
296 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
299 id = GetOpenMPThreadId();
304 register const Quantum
305 *restrict duplex_pixels,
312 *restrict destination_pixels;
314 if (status == MagickFalse)
316 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
317 source->extent.width,1,source->exception);
318 if (pixels == (const Quantum *) NULL)
323 for (x=0; x < (ssize_t) source->extent.width; x++)
325 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
326 pixels+=GetPixelChannels(source->image);
328 duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
329 duplex->extent.width,1,duplex->exception);
330 if (duplex_pixels == (const Quantum *) NULL)
335 for (x=0; x < (ssize_t) duplex->extent.width; x++)
337 PixelSetQuantumPixel(duplex->image,duplex_pixels,
338 duplex->pixel_wands[id][x]);
339 duplex_pixels+=GetPixelChannels(duplex->image);
341 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
342 destination->extent.x,y,destination->extent.width,1,exception);
343 if (destination_pixels == (Quantum *) NULL)
348 for (x=0; x < (ssize_t) destination->extent.width; x++)
350 PixelSetQuantumPixel(destination->image,destination_pixels,
351 destination->pixel_wands[id][x]);
352 destination_pixels+=GetPixelChannels(destination->image);
354 if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
356 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
357 destination->extent.x,y,destination->extent.width,1,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,exception);
365 if (sync == MagickFalse)
367 InheritException(destination->exception,GetCacheViewException(
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 PixelWand *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)
534 assert(source != (WandView *) NULL);
535 assert(source->signature == WandSignature);
536 if (get == (GetWandViewMethod) NULL)
538 source_image=source->wand->images;
541 #if defined(MAGICKCORE_OPENMP_SUPPORT)
542 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
544 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
547 id = GetOpenMPThreadId();
549 register const Quantum
555 if (status == MagickFalse)
557 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
558 source->extent.width,1,source->exception);
559 if (pixels == (const Quantum *) NULL)
564 for (x=0; x < (ssize_t) source->extent.width; x++)
566 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
567 pixels+=GetPixelChannels(source->image);
569 if (get(source,y,id,context) == MagickFalse)
571 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
576 #if defined(MAGICKCORE_OPENMP_SUPPORT)
577 #pragma omp critical (MagickWand_GetWandViewIterator)
579 proceed=SetImageProgress(source_image,source->description,progress++,
580 source->extent.height);
581 if (proceed == MagickFalse)
589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 % G e t W a n d V i e w P i x e l s %
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599 % GetWandViewPixels() returns the wand view pixel_wands.
601 % The format of the GetWandViewPixels method is:
603 % PixelWand *GetWandViewPixels(const WandView *wand_view)
605 % A description of each parameter follows:
607 % o wand_view: the wand view.
610 WandExport PixelWand **GetWandViewPixels(const WandView *wand_view)
613 id = GetOpenMPThreadId();
615 assert(wand_view != (WandView *) NULL);
616 assert(wand_view->signature == WandSignature);
617 return(wand_view->pixel_wands[id]);
621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625 % G e t W a n d V i e w W a n d %
629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631 % GetWandViewWand() returns the magick wand associated with the wand view.
633 % The format of the GetWandViewWand method is:
635 % MagickWand *GetWandViewWand(const WandView *wand_view)
637 % A description of each parameter follows:
639 % o wand_view: the wand view.
642 WandExport MagickWand *GetWandViewWand(const WandView *wand_view)
644 assert(wand_view != (WandView *) NULL);
645 assert(wand_view->signature == WandSignature);
646 return(wand_view->wand);
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 % I s W a n d V i e w %
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660 % IsWandView() returns MagickTrue if the the parameter is verified as a wand
663 % The format of the IsWandView method is:
665 % MagickBooleanType IsWandView(const WandView *wand_view)
667 % A description of each parameter follows:
669 % o wand_view: the wand view.
672 WandExport MagickBooleanType IsWandView(const WandView *wand_view)
677 if (wand_view == (const WandView *) NULL)
679 if (wand_view->signature != WandSignature)
681 length=strlen(WandViewId);
682 if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 % N e w W a n d V i e w %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698 % NewWandView() returns a wand view required for all other methods in the
701 % The format of the NewWandView method is:
703 % WandView *NewWandView(MagickWand *wand)
705 % A description of each parameter follows:
711 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands,
712 const size_t number_threads)
720 pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
721 sizeof(*pixel_wands));
722 if (pixel_wands == (PixelWand ***) NULL)
723 return((PixelWand ***) NULL);
724 (void) ResetMagickMemory(pixel_wands,0,number_threads*sizeof(*pixel_wands));
725 for (i=0; i < (ssize_t) number_threads; i++)
727 pixel_wands[i]=NewPixelWands(number_wands);
728 if (pixel_wands[i] == (PixelWand **) NULL)
729 return(DestroyPixelsThreadSet(pixel_wands,number_wands,number_threads));
734 WandExport WandView *NewWandView(MagickWand *wand)
739 assert(wand != (MagickWand *) NULL);
740 assert(wand->signature == WandSignature);
741 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
742 if (wand_view == (WandView *) NULL)
743 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
744 GetExceptionMessage(errno));
745 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
746 wand_view->id=AcquireWandId();
747 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
748 WandViewId,(double) wand_view->id);
749 wand_view->description=ConstantString("WandView");
750 wand_view->wand=wand;
751 wand_view->view=AcquireCacheView(wand_view->wand->images);
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=AcquireExceptionInfo();
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)
799 assert(wand != (MagickWand *) NULL);
800 assert(wand->signature == WandSignature);
801 wand_view=(WandView *) AcquireMagickMemory(sizeof(*wand_view));
802 if (wand_view == (WandView *) NULL)
803 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
804 GetExceptionMessage(errno));
805 (void) ResetMagickMemory(wand_view,0,sizeof(*wand_view));
806 wand_view->id=AcquireWandId();
807 (void) FormatLocaleString(wand_view->name,MaxTextExtent,"%s-%.20g",
808 WandViewId,(double) wand_view->id);
809 wand_view->description=ConstantString("WandView");
810 wand_view->view=AcquireCacheView(wand_view->wand->images);
811 wand_view->wand=wand;
812 wand_view->extent.width=width;
813 wand_view->extent.height=height;
814 wand_view->extent.x=x;
815 wand_view->extent.y=y;
816 wand_view->number_threads=GetOpenMPMaximumThreads();
817 wand_view->exception=AcquireExceptionInfo();
818 wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width,
819 wand_view->number_threads);
820 if (wand_view->pixel_wands == (PixelWand ***) NULL)
821 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
822 GetExceptionMessage(errno));
823 wand_view->debug=IsEventLogging();
824 wand_view->signature=WandSignature;
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % S e t W a n d V i e w D e s c r i p t i o n %
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
839 % SetWandViewDescription() associates a description with an image view.
841 % The format of the SetWandViewDescription method is:
843 % void SetWandViewDescription(WandView *image_view,const char *description)
845 % A description of each parameter follows:
847 % o wand_view: the wand view.
849 % o description: the wand view description.
852 MagickExport void SetWandViewDescription(WandView *wand_view,
853 const char *description)
855 assert(wand_view != (WandView *) NULL);
856 assert(wand_view->signature == WandSignature);
857 wand_view->description=ConstantString(description);
861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 % S e t W a n d V i e w I t e r a t o r %
869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 % SetWandViewIterator() iterates over the wand view in parallel and calls
872 % your set method for each scanline of the view. The pixel extent is
873 % confined to the image canvas-- that is no negative offsets or widths or
874 % heights that exceed the image dimension. The pixels are initiallly
875 % undefined and any settings you make in the callback method are automagically
876 % synced back to your image.
878 % The callback signature is:
880 % MagickBooleanType SetImageViewMethod(ImageView *destination,
881 % const ssize_t y,const int thread_id,void *context)
883 % Use this pragma if the view is not single threaded:
885 % #pragma omp critical
887 % to define a section of code in your callback set method that must be
888 % executed by a single thread at a time.
890 % The format of the SetWandViewIterator method is:
892 % MagickBooleanType SetWandViewIterator(WandView *destination,
893 % SetWandViewMethod set,void *context)
895 % A description of each parameter follows:
897 % o destination: the wand view.
899 % o set: the set callback method.
901 % o context: the user defined context.
904 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
905 SetWandViewMethod set,void *context)
922 assert(destination != (WandView *) NULL);
923 assert(destination->signature == WandSignature);
924 if (set == (SetWandViewMethod) NULL)
926 destination_image=destination->wand->images;
927 exception=destination->exception;
928 if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
932 #if defined(MAGICKCORE_OPENMP_SUPPORT)
933 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(destination->number_threads)
935 for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
938 id = GetOpenMPThreadId();
949 if (status == MagickFalse)
951 pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
952 y,destination->extent.width,1,exception);
953 if (pixels == (Quantum *) NULL)
955 InheritException(destination->exception,GetCacheViewException(
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,exception);
969 if (sync == MagickFalse)
971 InheritException(destination->exception,GetCacheViewException(
975 if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
980 #if defined(MAGICKCORE_OPENMP_SUPPORT)
981 #pragma omp critical (MagickWand_SetWandViewIterator)
983 proceed=SetImageProgress(destination_image,destination->description,
984 progress++,destination->extent.height);
985 if (proceed == MagickFalse)
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 % S e t W a n d V i e w T h r e a d s %
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 % SetWandViewThreads() sets the number of threads in a thread team.
1005 % The format of the SetWandViewDescription method is:
1007 % void SetWandViewThreads(WandView *image_view,
1008 % const size_t number_threads)
1010 % A description of each parameter follows:
1012 % o image_view: the image view.
1014 % o number_threads: the number of threads in a thread team.
1017 MagickExport void SetWandViewThreads(WandView *image_view,
1018 const size_t number_threads)
1020 assert(image_view != (WandView *) NULL);
1021 assert(image_view->signature == MagickSignature);
1022 image_view->number_threads=number_threads;
1023 if (number_threads > GetOpenMPMaximumThreads())
1024 image_view->number_threads=GetOpenMPMaximumThreads();
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032 % T r a n s f e r W a n d V i e w I t e r a t o r %
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 % TransferWandViewIterator() iterates over two wand views in parallel and
1039 % calls your transfer method for each scanline of the view. The source pixel
1040 % extent is not confined to the image canvas-- that is you can include
1041 % negative offsets or widths or heights that exceed the image dimension.
1042 % However, the destination wand view is confined to the image canvas-- that
1043 % is no negative offsets or widths or heights that exceed the image dimension
1046 % The callback signature is:
1048 % MagickBooleanType TransferImageViewMethod(const WandView *source,
1049 % WandView *destination,const ssize_t y,const int thread_id,
1052 % Use this pragma if the view is not single threaded:
1054 % #pragma omp critical
1056 % to define a section of code in your callback transfer method that must be
1057 % executed by a single thread at a time.
1059 % The format of the TransferWandViewIterator method is:
1061 % MagickBooleanType TransferWandViewIterator(WandView *source,
1062 % WandView *destination,TransferWandViewMethod transfer,void *context)
1064 % A description of each parameter follows:
1066 % o source: the source wand view.
1068 % o destination: the destination wand view.
1070 % o transfer: the transfer callback method.
1072 % o context: the user defined context.
1075 WandExport MagickBooleanType TransferWandViewIterator(WandView *source,
1076 WandView *destination,TransferWandViewMethod transfer,void *context)
1094 assert(source != (WandView *) NULL);
1095 assert(source->signature == WandSignature);
1096 if (transfer == (TransferWandViewMethod) NULL)
1097 return(MagickFalse);
1098 source_image=source->wand->images;
1099 destination_image=destination->wand->images;
1100 exception=destination->exception;
1101 if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
1102 return(MagickFalse);
1105 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1106 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
1108 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1111 id = GetOpenMPThreadId();
1116 register const Quantum
1123 *restrict destination_pixels;
1125 if (status == MagickFalse)
1127 pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1128 source->extent.width,1,source->exception);
1129 if (pixels == (const Quantum *) NULL)
1134 for (x=0; x < (ssize_t) source->extent.width; x++)
1136 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1137 pixels+=GetPixelChannels(source->image);
1139 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1140 destination->extent.x,y,destination->extent.width,1,exception);
1141 if (destination_pixels == (Quantum *) NULL)
1146 for (x=0; x < (ssize_t) destination->extent.width; x++)
1148 PixelSetQuantumPixel(destination->image,destination_pixels,
1149 destination->pixel_wands[id][x]);
1150 destination_pixels+=GetPixelChannels(destination->image);
1152 if (transfer(source,destination,y,id,context) == MagickFalse)
1154 destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1155 destination->extent.x,y,destination->extent.width,1,exception);
1156 for (x=0; x < (ssize_t) destination->extent.width; x++)
1158 PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1159 destination_pixels);
1160 destination_pixels+=GetPixelChannels(destination->image);
1162 sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1163 if (sync == MagickFalse)
1165 InheritException(destination->exception,GetCacheViewException(
1169 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1174 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1175 #pragma omp critical (MagickWand_TransferWandViewIterator)
1177 proceed=SetImageProgress(source_image,source->description,progress++,
1178 source->extent.height);
1179 if (proceed == MagickFalse)
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1191 % U p d a t e W a n d V i e w I t e r a t o r %
1195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1197 % UpdateWandViewIterator() iterates over the wand view in parallel and calls
1198 % your update method for each scanline of the view. The pixel extent is
1199 % confined to the image canvas-- that is no negative offsets or widths or
1200 % heights that exceed the image dimension are permitted. Updates to pixels
1201 % in your callback are automagically synced back to the image.
1203 % The callback signature is:
1205 % MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
1206 % const int thread_id,void *context)
1208 % Use this pragma if the view is not single threaded:
1210 % #pragma omp critical
1212 % to define a section of code in your callback update method that must be
1213 % executed by a single thread at a time.
1215 % The format of the UpdateWandViewIterator method is:
1217 % MagickBooleanType UpdateWandViewIterator(WandView *source,
1218 % UpdateWandViewMethod update,void *context)
1220 % A description of each parameter follows:
1222 % o source: the source wand view.
1224 % o update: the update callback method.
1226 % o context: the user defined context.
1229 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
1230 UpdateWandViewMethod update,void *context)
1247 assert(source != (WandView *) NULL);
1248 assert(source->signature == WandSignature);
1249 if (update == (UpdateWandViewMethod) NULL)
1250 return(MagickFalse);
1251 source_image=source->wand->images;
1252 exception=source->exception;
1253 if (SetImageStorageClass(source_image,DirectClass,exception) == MagickFalse)
1254 return(MagickFalse);
1257 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1258 #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
1260 for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1263 id = GetOpenMPThreadId();
1271 if (status == MagickFalse)
1273 pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1274 source->extent.width,1,exception);
1275 if (pixels == (Quantum *) NULL)
1277 InheritException(source->exception,GetCacheViewException(
1282 for (x=0; x < (ssize_t) source->extent.width; x++)
1284 PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1285 pixels+=GetPixelChannels(source->image);
1287 if (update(source,y,id,context) == MagickFalse)
1289 for (x=0; x < (ssize_t) source->extent.width; x++)
1291 PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
1292 pixels+=GetPixelChannels(source->image);
1294 if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1296 InheritException(source->exception,GetCacheViewException(source->view));
1299 if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1304 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1305 #pragma omp critical (MagickWand_UpdateWandViewIterator)
1307 proceed=SetImageProgress(source_image,source->description,progress++,
1308 source->extent.height);
1309 if (proceed == MagickFalse)