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