MagickWand  7.1.0
wand-view.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % W W AAA N N DDDD %
6 % W W A A NN N D D %
7 % W W W AAAAA N N N D D %
8 % WW WW A A N NN D D %
9 % W W A A N N DDDD %
10 % %
11 % V V IIIII EEEEE W W %
12 % V V I E W W %
13 % V V I EEE W W W %
14 % V V I E WW WW %
15 % V IIIII EEEEE W W %
16 % %
17 % %
18 % MagickWand Wand View Methods %
19 % %
20 % Software Design %
21 % Cristy %
22 % March 2003 %
23 % %
24 % %
25 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
27 % %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
30 % %
31 % https://imagemagick.org/script/license.php %
32 % %
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. %
38 % %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 %
41 %
42 %
43 */
44 
45 /*
46  Include declarations.
47 */
48 #include "MagickWand/studio.h"
49 #include "MagickWand/MagickWand.h"
51 #include "MagickWand/wand.h"
52 #include "MagickCore/monitor-private.h"
53 #include "MagickCore/thread-private.h"
54 /*
55  Define declarations.
56 */
57 #define WandViewId "WandView"
58 
59 /*
60  Typedef declarations.
61 */
62 struct _WandView
63 {
64  size_t
65  id;
66 
67  char
69  *description;
70 
71  RectangleInfo
73 
75  *wand;
76 
77  Image
79 
80  CacheView
81  *view;
82 
83  PixelWand
85 
86  ExceptionInfo
88 
89  MagickBooleanType
91 
92  size_t
94 };
95 
96 /*
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 % %
99 % %
100 % %
101 % C l o n e W a n d V i e w %
102 % %
103 % %
104 % %
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 %
107 % CloneWandView() makes a copy of the specified wand view.
108 %
109 % The format of the CloneWandView method is:
110 %
111 % WandView *CloneWandView(const WandView *wand_view)
112 %
113 % A description of each parameter follows:
114 %
115 % o wand_view: the wand view.
116 %
117 */
119 {
120  WandView
121  *clone_view;
122 
123  ssize_t
124  i;
125 
126  assert(wand_view != (WandView *) NULL);
127  assert(wand_view->signature == MagickWandSignature);
128  if (wand_view->debug != MagickFalse)
129  (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
130  clone_view=(WandView *) AcquireCriticalMemory(sizeof(*clone_view));
131  (void) memset(clone_view,0,sizeof(*clone_view));
132  clone_view->id=AcquireWandId();
133  (void) FormatLocaleString(clone_view->name,MagickPathExtent,"%s-%.20g",
134  WandViewId,(double) clone_view->id);
135  clone_view->description=ConstantString(wand_view->description);
136  clone_view->image=CloneImage(wand_view->image,0,0,MagickTrue,
137  wand_view->exception);
138  clone_view->view=CloneCacheView(wand_view->view);
139  clone_view->extent=wand_view->extent;
140  clone_view->exception=AcquireExceptionInfo();
141  InheritException(clone_view->exception,wand_view->exception);
142  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
143  clone_view->pixel_wands[i]=ClonePixelWands((const PixelWand **)
144  wand_view->pixel_wands[i],wand_view->extent.width);
145  clone_view->debug=wand_view->debug;
146  if (clone_view->debug != MagickFalse)
147  (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",clone_view->name);
148  clone_view->signature=MagickWandSignature;
149  return(clone_view);
150 }
151 
152 /*
153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 % %
155 % %
156 % %
157 % D e s t r o y W a n d V i e w %
158 % %
159 % %
160 % %
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162 %
163 % DestroyWandView() deallocates memory associated with a wand view.
164 %
165 % The format of the DestroyWandView method is:
166 %
167 % WandView *DestroyWandView(WandView *wand_view)
168 %
169 % A description of each parameter follows:
170 %
171 % o wand_view: the wand view.
172 %
173 */
174 
175 static PixelWand ***DestroyPixelsThreadSet(PixelWand ***pixel_wands,
176  const size_t number_wands)
177 {
178  ssize_t
179  i;
180 
181  assert(pixel_wands != (PixelWand ***) NULL);
182  for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++)
183  if (pixel_wands[i] != (PixelWand **) NULL)
184  pixel_wands[i]=DestroyPixelWands(pixel_wands[i],number_wands);
185  pixel_wands=(PixelWand ***) RelinquishMagickMemory(pixel_wands);
186  return(pixel_wands);
187 }
188 
190 {
191  assert(wand_view != (WandView *) NULL);
192  assert(wand_view->signature == MagickWandSignature);
193  wand_view->pixel_wands=DestroyPixelsThreadSet(wand_view->pixel_wands,
194  wand_view->extent.width);
195  wand_view->image=DestroyImage(wand_view->image);
196  wand_view->view=DestroyCacheView(wand_view->view);
197  wand_view->exception=DestroyExceptionInfo(wand_view->exception);
198  wand_view->signature=(~MagickWandSignature);
199  RelinquishWandId(wand_view->id);
200  wand_view=(WandView *) RelinquishMagickMemory(wand_view);
201  return(wand_view);
202 }
203 
204 /*
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206 % %
207 % %
208 % %
209 % 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 %
210 % %
211 % %
212 % %
213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214 %
215 % DuplexTransferWandViewIterator() iterates over three wand views in
216 % parallel and calls your transfer method for each scanline of the view. The
217 % source and duplex pixel extent is not confined to the image canvas-- that is
218 % you can include negative offsets or widths or heights that exceed the image
219 % dimension. However, the destination wand view is confined to the image
220 % canvas-- that is no negative offsets or widths or heights that exceed the
221 % image dimension are permitted.
222 %
223 % The callback signature is:
224 %
225 % MagickBooleanType DuplexTransferImageViewMethod(const WandView *source,
226 % const WandView *duplex,WandView *destination,const ssize_t y,
227 % const int thread_id,void *context)
228 %
229 % Use this pragma if the view is not single threaded:
230 %
231 % #pragma omp critical
232 %
233 % to define a section of code in your callback transfer method that must be
234 % executed by a single thread at a time.
235 %
236 % The format of the DuplexTransferWandViewIterator method is:
237 %
238 % MagickBooleanType DuplexTransferWandViewIterator(WandView *source,
239 % WandView *duplex,WandView *destination,
240 % DuplexTransferWandViewMethod transfer,void *context)
241 %
242 % A description of each parameter follows:
243 %
244 % o source: the source wand view.
245 %
246 % o duplex: the duplex wand view.
247 %
248 % o destination: the destination wand view.
249 %
250 % o transfer: the transfer callback method.
251 %
252 % o context: the user defined context.
253 %
254 */
256  WandView *duplex,WandView *destination,DuplexTransferWandViewMethod transfer,
257  void *context)
258 {
259  Image
260  *destination_image,
261  *source_image;
262 
263  MagickBooleanType
264  status;
265 
266  MagickOffsetType
267  progress;
268 
269 #if defined(MAGICKCORE_OPENMP_SUPPORT)
270  size_t
271  height;
272 #endif
273 
274  ssize_t
275  y;
276 
277  assert(source != (WandView *) NULL);
278  assert(source->signature == MagickWandSignature);
279  if (transfer == (DuplexTransferWandViewMethod) NULL)
280  return(MagickFalse);
281  source_image=source->wand->images;
282  destination_image=destination->wand->images;
283  status=SetImageStorageClass(destination_image,DirectClass,
284  destination->exception);
285  if (status == MagickFalse)
286  return(MagickFalse);
287  status=MagickTrue;
288  progress=0;
289 #if defined(MAGICKCORE_OPENMP_SUPPORT)
290  height=source->extent.height-source->extent.y;
291  #pragma omp parallel for schedule(static) shared(progress,status) \
292  magick_number_threads(source_image,destination_image,height,1)
293 #endif
294  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
295  {
296  const int
297  id = GetOpenMPThreadId();
298 
299  MagickBooleanType
300  sync;
301 
302  const Quantum
303  *magick_restrict duplex_pixels,
304  *magick_restrict pixels;
305 
306  ssize_t
307  x;
308 
309  Quantum
310  *magick_restrict destination_pixels;
311 
312  if (status == MagickFalse)
313  continue;
314  pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
315  source->extent.width,1,source->exception);
316  if (pixels == (const Quantum *) NULL)
317  {
318  status=MagickFalse;
319  continue;
320  }
321  for (x=0; x < (ssize_t) source->extent.width; x++)
322  {
323  PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
324  pixels+=GetPixelChannels(source->image);
325  }
326  duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
327  duplex->extent.width,1,duplex->exception);
328  if (duplex_pixels == (const Quantum *) NULL)
329  {
330  status=MagickFalse;
331  continue;
332  }
333  for (x=0; x < (ssize_t) duplex->extent.width; x++)
334  {
335  PixelSetQuantumPixel(duplex->image,duplex_pixels,
336  duplex->pixel_wands[id][x]);
337  duplex_pixels+=GetPixelChannels(duplex->image);
338  }
339  destination_pixels=GetCacheViewAuthenticPixels(destination->view,
340  destination->extent.x,y,destination->extent.width,1,
341  destination->exception);
342  if (destination_pixels == (Quantum *) NULL)
343  {
344  status=MagickFalse;
345  continue;
346  }
347  for (x=0; x < (ssize_t) destination->extent.width; x++)
348  {
349  PixelSetQuantumPixel(destination->image,destination_pixels,
350  destination->pixel_wands[id][x]);
351  destination_pixels+=GetPixelChannels(destination->image);
352  }
353  if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
354  status=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++)
359  {
360  PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
361  destination_pixels);
362  destination_pixels+=GetPixelChannels(destination->image);
363  }
364  sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
365  if (sync == MagickFalse)
366  status=MagickFalse;
367  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
368  {
369  MagickBooleanType
370  proceed;
371 
372 #if defined(MAGICKCORE_OPENMP_SUPPORT)
373  #pragma omp atomic
374 #endif
375  progress++;
376  proceed=SetImageProgress(source_image,source->description,progress,
377  source->extent.height);
378  if (proceed == MagickFalse)
379  status=MagickFalse;
380  }
381  }
382  return(status);
383 }
384 
385 /*
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 % %
388 % %
389 % %
390 % G e t W a n d V i e w E x c e p t i o n %
391 % %
392 % %
393 % %
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %
396 % GetWandViewException() returns the severity, reason, and description of any
397 % error that occurs when utilizing a wand view.
398 %
399 % The format of the GetWandViewException method is:
400 %
401 % char *GetWandViewException(const WandView *wand_view,
402 % ExceptionType *severity)
403 %
404 % A description of each parameter follows:
405 %
406 % o wand_view: the pixel wand_view.
407 %
408 % o severity: the severity of the error is returned here.
409 %
410 */
411 WandExport char *GetWandViewException(const WandView *wand_view,
412  ExceptionType *severity)
413 {
414  char
415  *description;
416 
417  assert(wand_view != (const WandView *) NULL);
418  assert(wand_view->signature == MagickWandSignature);
419  if (wand_view->debug != MagickFalse)
420  (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand_view->name);
421  assert(severity != (ExceptionType *) NULL);
422  *severity=wand_view->exception->severity;
423  description=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
424  sizeof(*description));
425  if (description == (char *) NULL)
426  ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
427  wand_view->name);
428  *description='\0';
429  if (wand_view->exception->reason != (char *) NULL)
430  (void) CopyMagickString(description,GetLocaleExceptionMessage(
431  wand_view->exception->severity,wand_view->exception->reason),
433  if (wand_view->exception->description != (char *) NULL)
434  {
435  (void) ConcatenateMagickString(description," (",MagickPathExtent);
436  (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
437  wand_view->exception->severity,wand_view->exception->description),
439  (void) ConcatenateMagickString(description,")",MagickPathExtent);
440  }
441  return(description);
442 }
443 
444 /*
445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 % %
447 % %
448 % %
449 % G e t W a n d V i e w E x t e n t %
450 % %
451 % %
452 % %
453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 %
455 % GetWandViewExtent() returns the wand view extent.
456 %
457 % The format of the GetWandViewExtent method is:
458 %
459 % RectangleInfo GetWandViewExtent(const WandView *wand_view)
460 %
461 % A description of each parameter follows:
462 %
463 % o wand_view: the wand view.
464 %
465 */
466 WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
467 {
468  assert(wand_view != (WandView *) NULL);
469  assert(wand_view->signature == MagickWandSignature);
470  return(wand_view->extent);
471 }
472 
473 /*
474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475 % %
476 % %
477 % %
478 % G e t W a n d V i e w I t e r a t o r %
479 % %
480 % %
481 % %
482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483 %
484 % GetWandViewIterator() iterates over the wand view in parallel and calls
485 % your get method for each scanline of the view. The pixel extent is
486 % not confined to the image canvas-- that is you can include negative offsets
487 % or widths or heights that exceed the image dimension. Any updates to
488 % the pixels in your callback are ignored.
489 %
490 % The callback signature is:
491 %
492 % MagickBooleanType GetImageViewMethod(const WandView *source,
493 % const ssize_t y,const int thread_id,void *context)
494 %
495 % Use this pragma if the view is not single threaded:
496 %
497 % #pragma omp critical
498 %
499 % to define a section of code in your callback get method that must be
500 % executed by a single thread at a time.
501 %
502 % The format of the GetWandViewIterator method is:
503 %
504 % MagickBooleanType GetWandViewIterator(WandView *source,
505 % GetWandViewMethod get,void *context)
506 %
507 % A description of each parameter follows:
508 %
509 % o source: the source wand view.
510 %
511 % o get: the get callback method.
512 %
513 % o context: the user defined context.
514 %
515 */
516 WandExport MagickBooleanType GetWandViewIterator(WandView *source,
517  GetWandViewMethod get,void *context)
518 {
519  Image
520  *source_image;
521 
522  MagickBooleanType
523  status;
524 
525  MagickOffsetType
526  progress;
527 
528 #if defined(MAGICKCORE_OPENMP_SUPPORT)
529  size_t
530  height;
531 #endif
532 
533  ssize_t
534  y;
535 
536  assert(source != (WandView *) NULL);
537  assert(source->signature == MagickWandSignature);
538  if (get == (GetWandViewMethod) NULL)
539  return(MagickFalse);
540  source_image=source->wand->images;
541  status=MagickTrue;
542  progress=0;
543 #if defined(MAGICKCORE_OPENMP_SUPPORT)
544  height=source->extent.height-source->extent.y;
545  #pragma omp parallel for schedule(static) shared(progress,status) \
546  magick_number_threads(source_image,source_image,height,1)
547 #endif
548  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
549  {
550  const int
551  id = GetOpenMPThreadId();
552 
553  const Quantum
554  *pixels;
555 
556  ssize_t
557  x;
558 
559  if (status == MagickFalse)
560  continue;
561  pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
562  source->extent.width,1,source->exception);
563  if (pixels == (const Quantum *) NULL)
564  {
565  status=MagickFalse;
566  continue;
567  }
568  for (x=0; x < (ssize_t) source->extent.width; x++)
569  {
570  PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
571  pixels+=GetPixelChannels(source->image);
572  }
573  if (get(source,y,id,context) == MagickFalse)
574  status=MagickFalse;
575  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
576  {
577  MagickBooleanType
578  proceed;
579 
580 #if defined(MAGICKCORE_OPENMP_SUPPORT)
581  #pragma omp atomic
582 #endif
583  progress++;
584  proceed=SetImageProgress(source_image,source->description,progress,
585  source->extent.height);
586  if (proceed == MagickFalse)
587  status=MagickFalse;
588  }
589  }
590  return(status);
591 }
592 
593 /*
594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595 % %
596 % %
597 % %
598 % G e t W a n d V i e w P i x e l s %
599 % %
600 % %
601 % %
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 %
604 % GetWandViewPixels() returns the wand view pixel_wands.
605 %
606 % The format of the GetWandViewPixels method is:
607 %
608 % PixelWand *GetWandViewPixels(const WandView *wand_view)
609 %
610 % A description of each parameter follows:
611 %
612 % o wand_view: the wand view.
613 %
614 */
616 {
617  const int
618  id = GetOpenMPThreadId();
619 
620  assert(wand_view != (WandView *) NULL);
621  assert(wand_view->signature == MagickWandSignature);
622  return(wand_view->pixel_wands[id]);
623 }
624 
625 /*
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 % %
628 % %
629 % %
630 % G e t W a n d V i e w W a n d %
631 % %
632 % %
633 % %
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 %
636 % GetWandViewWand() returns the magick wand associated with the wand view.
637 %
638 % The format of the GetWandViewWand method is:
639 %
640 % MagickWand *GetWandViewWand(const WandView *wand_view)
641 %
642 % A description of each parameter follows:
643 %
644 % o wand_view: the wand view.
645 %
646 */
648 {
649  assert(wand_view != (WandView *) NULL);
650  assert(wand_view->signature == MagickWandSignature);
651  return(wand_view->wand);
652 }
653 
654 /*
655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 % %
657 % %
658 % %
659 % I s W a n d V i e w %
660 % %
661 % %
662 % %
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664 %
665 % IsWandView() returns MagickTrue if the parameter is verified as a wand
666 % view object.
667 %
668 % The format of the IsWandView method is:
669 %
670 % MagickBooleanType IsWandView(const WandView *wand_view)
671 %
672 % A description of each parameter follows:
673 %
674 % o wand_view: the wand view.
675 %
676 */
677 WandExport MagickBooleanType IsWandView(const WandView *wand_view)
678 {
679  size_t
680  length;
681 
682  if (wand_view == (const WandView *) NULL)
683  return(MagickFalse);
684  if (wand_view->signature != MagickWandSignature)
685  return(MagickFalse);
686  length=strlen(WandViewId);
687  if (LocaleNCompare(wand_view->name,WandViewId,length) != 0)
688  return(MagickFalse);
689  return(MagickTrue);
690 }
691 
692 /*
693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694 % %
695 % %
696 % %
697 % N e w W a n d V i e w %
698 % %
699 % %
700 % %
701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 %
703 % NewWandView() returns a wand view required for all other methods in the
704 % Wand View API.
705 %
706 % The format of the NewWandView method is:
707 %
708 % WandView *NewWandView(MagickWand *wand)
709 %
710 % A description of each parameter follows:
711 %
712 % o wand: the wand.
713 %
714 */
715 
716 static PixelWand ***AcquirePixelsThreadSet(const size_t number_wands)
717 {
718  PixelWand
719  ***pixel_wands;
720 
721  ssize_t
722  i;
723 
724  size_t
725  number_threads;
726 
727  number_threads=GetOpenMPMaximumThreads();
728  pixel_wands=(PixelWand ***) AcquireQuantumMemory(number_threads,
729  sizeof(*pixel_wands));
730  if (pixel_wands == (PixelWand ***) NULL)
731  return((PixelWand ***) NULL);
732  (void) memset(pixel_wands,0,number_threads*sizeof(*pixel_wands));
733  for (i=0; i < (ssize_t) number_threads; i++)
734  {
735  pixel_wands[i]=NewPixelWands(number_wands);
736  if (pixel_wands[i] == (PixelWand **) NULL)
737  return(DestroyPixelsThreadSet(pixel_wands,number_wands));
738  }
739  return(pixel_wands);
740 }
741 
743 {
744  ExceptionInfo
745  *exception;
746 
747  WandView
748  *wand_view;
749 
750  assert(wand != (MagickWand *) NULL);
751  assert(wand->signature == MagickWandSignature);
752  wand_view=(WandView *) AcquireCriticalMemory(sizeof(*wand_view));
753  (void) memset(wand_view,0,sizeof(*wand_view));
754  wand_view->id=AcquireWandId();
755  (void) FormatLocaleString(wand_view->name,MagickPathExtent,"%s-%.20g",
756  WandViewId,(double) wand_view->id);
757  wand_view->description=ConstantString("WandView");
758  wand_view->wand=wand;
759  exception=AcquireExceptionInfo();
760  wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
761  wand_view->extent.width=wand->images->columns;
762  wand_view->extent.height=wand->images->rows;
763  wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
764  wand_view->exception=exception;
765  if (wand_view->pixel_wands == (PixelWand ***) NULL)
766  ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
767  GetExceptionMessage(errno));
768  wand_view->debug=IsEventLogging();
769  wand_view->signature=MagickWandSignature;
770  return(wand_view);
771 }
772 
773 /*
774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
775 % %
776 % %
777 % %
778 % N e w W a n d V i e w E x t e n t %
779 % %
780 % %
781 % %
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783 %
784 % NewWandViewExtent() returns a wand view required for all other methods
785 % in the Wand View API.
786 %
787 % The format of the NewWandViewExtent method is:
788 %
789 % WandView *NewWandViewExtent(MagickWand *wand,const ssize_t x,
790 % const ssize_t y,const size_t width,const size_t height)
791 %
792 % A description of each parameter follows:
793 %
794 % o wand: the magick wand.
795 %
796 % o x,y,columns,rows: These values define the perimeter of a extent of
797 % pixel_wands view.
798 %
799 */
801  const ssize_t y,const size_t width,const size_t height)
802 {
803  ExceptionInfo
804  *exception;
805 
806  WandView
807  *wand_view;
808 
809  assert(wand != (MagickWand *) NULL);
810  assert(wand->signature == MagickWandSignature);
811  wand_view=(WandView *) AcquireCriticalMemory(sizeof(*wand_view));
812  (void) memset(wand_view,0,sizeof(*wand_view));
813  wand_view->id=AcquireWandId();
814  (void) FormatLocaleString(wand_view->name,MagickPathExtent,"%s-%.20g",
815  WandViewId,(double) wand_view->id);
816  wand_view->description=ConstantString("WandView");
817  exception=AcquireExceptionInfo();
818  wand_view->view=AcquireVirtualCacheView(wand_view->wand->images,exception);
819  wand_view->wand=wand;
820  wand_view->extent.width=width;
821  wand_view->extent.height=height;
822  wand_view->extent.x=x;
823  wand_view->extent.y=y;
824  wand_view->exception=exception;
825  wand_view->pixel_wands=AcquirePixelsThreadSet(wand_view->extent.width);
826  if (wand_view->pixel_wands == (PixelWand ***) NULL)
827  ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
828  GetExceptionMessage(errno));
829  wand_view->debug=IsEventLogging();
830  wand_view->signature=MagickWandSignature;
831  return(wand_view);
832 }
833 
834 /*
835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836 % %
837 % %
838 % %
839 % S e t W a n d V i e w D e s c r i p t i o n %
840 % %
841 % %
842 % %
843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844 %
845 % SetWandViewDescription() associates a description with an image view.
846 %
847 % The format of the SetWandViewDescription method is:
848 %
849 % void SetWandViewDescription(WandView *image_view,const char *description)
850 %
851 % A description of each parameter follows:
852 %
853 % o wand_view: the wand view.
854 %
855 % o description: the wand view description.
856 %
857 */
858 MagickExport void SetWandViewDescription(WandView *wand_view,
859  const char *description)
860 {
861  assert(wand_view != (WandView *) NULL);
862  assert(wand_view->signature == MagickWandSignature);
863  wand_view->description=ConstantString(description);
864 }
865 
866 /*
867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868 % %
869 % %
870 % %
871 % S e t W a n d V i e w I t e r a t o r %
872 % %
873 % %
874 % %
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 %
877 % SetWandViewIterator() iterates over the wand view in parallel and calls
878 % your set method for each scanline of the view. The pixel extent is
879 % confined to the image canvas-- that is no negative offsets or widths or
880 % heights that exceed the image dimension. The pixels are initiallly
881 % undefined and any settings you make in the callback method are automagically
882 % synced back to your image.
883 %
884 % The callback signature is:
885 %
886 % MagickBooleanType SetImageViewMethod(ImageView *destination,
887 % const ssize_t y,const int thread_id,void *context)
888 %
889 % Use this pragma if the view is not single threaded:
890 %
891 % #pragma omp critical
892 %
893 % to define a section of code in your callback set method that must be
894 % executed by a single thread at a time.
895 %
896 % The format of the SetWandViewIterator method is:
897 %
898 % MagickBooleanType SetWandViewIterator(WandView *destination,
899 % SetWandViewMethod set,void *context)
900 %
901 % A description of each parameter follows:
902 %
903 % o destination: the wand view.
904 %
905 % o set: the set callback method.
906 %
907 % o context: the user defined context.
908 %
909 */
910 WandExport MagickBooleanType SetWandViewIterator(WandView *destination,
911  SetWandViewMethod set,void *context)
912 {
913  Image
914  *destination_image;
915 
916  MagickBooleanType
917  status;
918 
919  MagickOffsetType
920  progress;
921 
922 #if defined(MAGICKCORE_OPENMP_SUPPORT)
923  size_t
924  height;
925 #endif
926 
927  ssize_t
928  y;
929 
930  assert(destination != (WandView *) NULL);
931  assert(destination->signature == MagickWandSignature);
932  if (set == (SetWandViewMethod) NULL)
933  return(MagickFalse);
934  destination_image=destination->wand->images;
935  status=SetImageStorageClass(destination_image,DirectClass,
936  destination->exception);
937  if (status == MagickFalse)
938  return(MagickFalse);
939  status=MagickTrue;
940  progress=0;
941 #if defined(MAGICKCORE_OPENMP_SUPPORT)
942  height=destination->extent.height-destination->extent.y;
943  #pragma omp parallel for schedule(static) shared(progress,status) \
944  magick_number_threads(destination_image,destination_image,height,1)
945 #endif
946  for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
947  {
948  const int
949  id = GetOpenMPThreadId();
950 
951  MagickBooleanType
952  sync;
953 
954  ssize_t
955  x;
956 
957  Quantum
958  *magick_restrict pixels;
959 
960  if (status == MagickFalse)
961  continue;
962  pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
963  y,destination->extent.width,1,destination->exception);
964  if (pixels == (Quantum *) NULL)
965  {
966  status=MagickFalse;
967  continue;
968  }
969  if (set(destination,y,id,context) == MagickFalse)
970  status=MagickFalse;
971  for (x=0; x < (ssize_t) destination->extent.width; x++)
972  {
973  PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
974  pixels);
975  pixels+=GetPixelChannels(destination->image);
976  }
977  sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
978  if (sync == MagickFalse)
979  status=MagickFalse;
980  if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
981  {
982  MagickBooleanType
983  proceed;
984 
985 #if defined(MAGICKCORE_OPENMP_SUPPORT)
986  #pragma omp atomic
987 #endif
988  progress++;
989  proceed=SetImageProgress(destination_image,destination->description,
990  progress,destination->extent.height);
991  if (proceed == MagickFalse)
992  status=MagickFalse;
993  }
994  }
995  return(status);
996 }
997 
998 /*
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000 % %
1001 % %
1002 % %
1003 % T r a n s f e r W a n d V i e w I t e r a t o r %
1004 % %
1005 % %
1006 % %
1007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008 %
1009 % TransferWandViewIterator() iterates over two wand views in parallel and
1010 % calls your transfer method for each scanline of the view. The source pixel
1011 % extent is not confined to the image canvas-- that is you can include
1012 % negative offsets or widths or heights that exceed the image dimension.
1013 % However, the destination wand view is confined to the image canvas-- that
1014 % is no negative offsets or widths or heights that exceed the image dimension
1015 % are permitted.
1016 %
1017 % The callback signature is:
1018 %
1019 % MagickBooleanType TransferImageViewMethod(const WandView *source,
1020 % WandView *destination,const ssize_t y,const int thread_id,
1021 % void *context)
1022 %
1023 % Use this pragma if the view is not single threaded:
1024 %
1025 % #pragma omp critical
1026 %
1027 % to define a section of code in your callback transfer method that must be
1028 % executed by a single thread at a time.
1029 %
1030 % The format of the TransferWandViewIterator method is:
1031 %
1032 % MagickBooleanType TransferWandViewIterator(WandView *source,
1033 % WandView *destination,TransferWandViewMethod transfer,void *context)
1034 %
1035 % A description of each parameter follows:
1036 %
1037 % o source: the source wand view.
1038 %
1039 % o destination: the destination wand view.
1040 %
1041 % o transfer: the transfer callback method.
1042 %
1043 % o context: the user defined context.
1044 %
1045 */
1047  WandView *destination,TransferWandViewMethod transfer,void *context)
1048 {
1049  Image
1050  *destination_image,
1051  *source_image;
1052 
1053  MagickBooleanType
1054  status;
1055 
1056  MagickOffsetType
1057  progress;
1058 
1059 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1060  size_t
1061  height;
1062 #endif
1063 
1064  ssize_t
1065  y;
1066 
1067  assert(source != (WandView *) NULL);
1068  assert(source->signature == MagickWandSignature);
1069  if (transfer == (TransferWandViewMethod) NULL)
1070  return(MagickFalse);
1071  source_image=source->wand->images;
1072  destination_image=destination->wand->images;
1073  status=SetImageStorageClass(destination_image,DirectClass,
1074  destination->exception);
1075  if (status == MagickFalse)
1076  return(MagickFalse);
1077  status=MagickTrue;
1078  progress=0;
1079 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1080  height=source->extent.height-source->extent.y;
1081  #pragma omp parallel for schedule(static) shared(progress,status) \
1082  magick_number_threads(source_image,destination_image,height,1)
1083 #endif
1084  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1085  {
1086  const int
1087  id = GetOpenMPThreadId();
1088 
1089  MagickBooleanType
1090  sync;
1091 
1092  const Quantum
1093  *magick_restrict pixels;
1094 
1095  ssize_t
1096  x;
1097 
1098  Quantum
1099  *magick_restrict destination_pixels;
1100 
1101  if (status == MagickFalse)
1102  continue;
1103  pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1104  source->extent.width,1,source->exception);
1105  if (pixels == (const Quantum *) NULL)
1106  {
1107  status=MagickFalse;
1108  continue;
1109  }
1110  for (x=0; x < (ssize_t) source->extent.width; x++)
1111  {
1112  PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1113  pixels+=GetPixelChannels(source->image);
1114  }
1115  destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1116  destination->extent.x,y,destination->extent.width,1,
1117  destination->exception);
1118  if (destination_pixels == (Quantum *) NULL)
1119  {
1120  status=MagickFalse;
1121  continue;
1122  }
1123  for (x=0; x < (ssize_t) destination->extent.width; x++)
1124  {
1125  PixelSetQuantumPixel(destination->image,destination_pixels,
1126  destination->pixel_wands[id][x]);
1127  destination_pixels+=GetPixelChannels(destination->image);
1128  }
1129  if (transfer(source,destination,y,id,context) == MagickFalse)
1130  status=MagickFalse;
1131  destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1132  destination->extent.x,y,destination->extent.width,1,
1133  destination->exception);
1134  for (x=0; x < (ssize_t) destination->extent.width; x++)
1135  {
1136  PixelGetQuantumPixel(destination->image,destination->pixel_wands[id][x],
1137  destination_pixels);
1138  destination_pixels+=GetPixelChannels(destination->image);
1139  }
1140  sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1141  if (sync == MagickFalse)
1142  status=MagickFalse;
1143  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1144  {
1145  MagickBooleanType
1146  proceed;
1147 
1148 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1149  #pragma omp atomic
1150 #endif
1151  progress++;
1152  proceed=SetImageProgress(source_image,source->description,progress,
1153  source->extent.height);
1154  if (proceed == MagickFalse)
1155  status=MagickFalse;
1156  }
1157  }
1158  return(status);
1159 }
1160 
1161 /*
1162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 % %
1164 % %
1165 % %
1166 % U p d a t e W a n d V i e w I t e r a t o r %
1167 % %
1168 % %
1169 % %
1170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1171 %
1172 % UpdateWandViewIterator() iterates over the wand view in parallel and calls
1173 % your update method for each scanline of the view. The pixel extent is
1174 % confined to the image canvas-- that is no negative offsets or widths or
1175 % heights that exceed the image dimension are permitted. Updates to pixels
1176 % in your callback are automagically synced back to the image.
1177 %
1178 % The callback signature is:
1179 %
1180 % MagickBooleanType UpdateImageViewMethod(WandView *source,const ssize_t y,
1181 % const int thread_id,void *context)
1182 %
1183 % Use this pragma if the view is not single threaded:
1184 %
1185 % #pragma omp critical
1186 %
1187 % to define a section of code in your callback update method that must be
1188 % executed by a single thread at a time.
1189 %
1190 % The format of the UpdateWandViewIterator method is:
1191 %
1192 % MagickBooleanType UpdateWandViewIterator(WandView *source,
1193 % UpdateWandViewMethod update,void *context)
1194 %
1195 % A description of each parameter follows:
1196 %
1197 % o source: the source wand view.
1198 %
1199 % o update: the update callback method.
1200 %
1201 % o context: the user defined context.
1202 %
1203 */
1204 WandExport MagickBooleanType UpdateWandViewIterator(WandView *source,
1205  UpdateWandViewMethod update,void *context)
1206 {
1207  Image
1208  *source_image;
1209 
1210  MagickBooleanType
1211  status;
1212 
1213  MagickOffsetType
1214  progress;
1215 
1216 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1217  size_t
1218  height;
1219 #endif
1220 
1221  ssize_t
1222  y;
1223 
1224  assert(source != (WandView *) NULL);
1225  assert(source->signature == MagickWandSignature);
1226  if (update == (UpdateWandViewMethod) NULL)
1227  return(MagickFalse);
1228  source_image=source->wand->images;
1229  status=SetImageStorageClass(source_image,DirectClass,source->exception);
1230  if (status == MagickFalse)
1231  return(MagickFalse);
1232  status=MagickTrue;
1233  progress=0;
1234 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1235  height=source->extent.height-source->extent.y;
1236  #pragma omp parallel for schedule(static) shared(progress,status) \
1237  magick_number_threads(source_image,source_image,height,1)
1238 #endif
1239  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1240  {
1241  const int
1242  id = GetOpenMPThreadId();
1243 
1244  MagickBooleanType
1245  sync;
1246 
1247  ssize_t
1248  x;
1249 
1250  Quantum
1251  *magick_restrict pixels;
1252 
1253  if (status == MagickFalse)
1254  continue;
1255  pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1256  source->extent.width,1,source->exception);
1257  if (pixels == (Quantum *) NULL)
1258  {
1259  status=MagickFalse;
1260  continue;
1261  }
1262  for (x=0; x < (ssize_t) source->extent.width; x++)
1263  {
1264  PixelSetQuantumPixel(source->image,pixels,source->pixel_wands[id][x]);
1265  pixels+=GetPixelChannels(source->image);
1266  }
1267  if (update(source,y,id,context) == MagickFalse)
1268  status=MagickFalse;
1269  for (x=0; x < (ssize_t) source->extent.width; x++)
1270  {
1271  PixelGetQuantumPixel(source->image,source->pixel_wands[id][x],pixels);
1272  pixels+=GetPixelChannels(source->image);
1273  }
1274  sync=SyncCacheViewAuthenticPixels(source->view,source->exception);
1275  if (sync == MagickFalse)
1276  status=MagickFalse;
1277  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1278  {
1279  MagickBooleanType
1280  proceed;
1281 
1282 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1283  #pragma omp atomic
1284 #endif
1285  progress++;
1286  proceed=SetImageProgress(source_image,source->description,progress,
1287  source->extent.height);
1288  if (proceed == MagickFalse)
1289  status=MagickFalse;
1290  }
1291  }
1292  return(status);
1293 }
WandExport MagickBooleanType GetWandViewIterator(WandView *source, GetWandViewMethod get, void *context)
Definition: wand-view.c:516
MagickBooleanType(* DuplexTransferWandViewMethod)(const WandView *, const WandView *, WandView *, const ssize_t, const int, void *)
Definition: wand-view.h:29
#define ThrowWandFatalException(severity, tag, context)
WandExport PixelWand ** ClonePixelWands(const PixelWand **wands, const size_t number_wands)
Definition: pixel-wand.c:192
CacheView * view
Definition: wand-view.c:81
#define MagickWandSignature
MagickBooleanType(*)(*)(*)(* TransferWandViewMethod)(const WandView *, WandView *, const ssize_t, const int, void *)
Definition: wand-view.h:33
PixelWand *** pixel_wands
Definition: wand-view.c:84
WandExport size_t AcquireWandId(void)
Definition: wand.c:74
WandExport WandView * NewWandView(MagickWand *wand)
Definition: wand-view.c:742
MagickBooleanType(*)(* GetWandViewMethod)(const WandView *, const ssize_t, const int, void *)
Definition: wand-view.h:31
#define WandExport
char * description
Definition: wand-view.c:68
size_t signature
Definition: wand-view.c:93
WandExport void PixelSetQuantumPixel(const Image *image, const Quantum *pixel, PixelWand *wand)
Definition: pixel-wand.c:2131
MagickBooleanType debug
Definition: wand-view.c:90
size_t id
Definition: wand-view.c:65
WandExport MagickBooleanType DuplexTransferWandViewIterator(WandView *source, WandView *duplex, WandView *destination, DuplexTransferWandViewMethod transfer, void *context)
Definition: wand-view.c:255
Image * image
Definition: wand-view.c:78
WandExport MagickBooleanType TransferWandViewIterator(WandView *source, WandView *destination, TransferWandViewMethod transfer, void *context)
Definition: wand-view.c:1046
WandExport WandView * DestroyWandView(WandView *wand_view)
Definition: wand-view.c:189
static PixelWand *** DestroyPixelsThreadSet(PixelWand ***pixel_wands, const size_t number_wands)
Definition: wand-view.c:175
static PixelWand *** AcquirePixelsThreadSet(const size_t number_wands)
Definition: wand-view.c:716
WandExport void RelinquishWandId(const size_t id)
Definition: wand.c:150
MagickBooleanType(*)(*)(*)(*)(* UpdateWandViewMethod)(WandView *, const ssize_t, const int, void *)
Definition: wand-view.h:35
WandExport PixelWand ** NewPixelWands(const size_t number_wands)
Definition: pixel-wand.c:433
#define MagickPathExtent
RectangleInfo extent
Definition: wand-view.c:72
MagickExport void SetWandViewDescription(WandView *wand_view, const char *description)
Definition: wand-view.c:858
#define WandViewId
Definition: wand-view.c:57
WandExport WandView * NewWandViewExtent(MagickWand *wand, const ssize_t x, const ssize_t y, const size_t width, const size_t height)
Definition: wand-view.c:800
WandExport PixelWand ** GetWandViewPixels(const WandView *wand_view)
Definition: wand-view.c:615
WandExport MagickWand * GetWandViewWand(const WandView *wand_view)
Definition: wand-view.c:647
char name[MagickPathExtent]
Definition: wand-view.c:68
WandExport RectangleInfo GetWandViewExtent(const WandView *wand_view)
Definition: wand-view.c:466
MagickBooleanType(*)(*)(* SetWandViewMethod)(WandView *, const ssize_t, const int, void *)
Definition: wand-view.h:32
WandExport PixelWand ** DestroyPixelWands(PixelWand **wand, const size_t number_wands)
Definition: pixel-wand.c:269
WandExport MagickBooleanType UpdateWandViewIterator(WandView *source, UpdateWandViewMethod update, void *context)
Definition: wand-view.c:1204
MagickWand * wand
Definition: wand-view.c:75
WandExport WandView * CloneWandView(const WandView *wand_view)
Definition: wand-view.c:118
WandExport MagickBooleanType SetWandViewIterator(WandView *destination, SetWandViewMethod set, void *context)
Definition: wand-view.c:910
#define magick_restrict
Definition: MagickWand.h:41
ExceptionInfo * exception
Definition: wand-view.c:87
WandExport MagickBooleanType IsWandView(const WandView *wand_view)
Definition: wand-view.c:677
WandExport void PixelGetQuantumPixel(const Image *image, const PixelWand *wand, Quantum *pixel)
Definition: pixel-wand.c:1302
WandExport char * GetWandViewException(const WandView *wand_view, ExceptionType *severity)
Definition: wand-view.c:411