]> granicus.if.org Git - imagemagick/blob - MagickCore/image-view.c
(no commit message)
[imagemagick] / MagickCore / 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 "MagickCore/studio.h"
49 #include "MagickCore/MagickCore.h"
50 #include "MagickCore/exception-private.h"
51 #include "MagickCore/monitor-private.h"
52 #include "MagickCore/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   exception=destination->exception;
241   if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
242     return(MagickFalse);
243   status=MagickTrue;
244   progress=0;
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 Quantum
257       *restrict duplex_pixels,
258       *restrict pixels;
259
260     register Quantum
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 Quantum *) 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 Quantum *) 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 == (Quantum *) 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 M e t a c o n t e n t %
318 %                                                                             %
319 %                                                                             %
320 %                                                                             %
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 %
323 %  GetImageViewAuthenticMetacontent() returns the image view authentic
324 %  meta-content.
325 %
326 %  The format of the GetImageViewAuthenticPixels method is:
327 %
328 %      void *GetImageViewAuthenticMetacontent(
329 %        const ImageView *image_view)
330 %
331 %  A description of each parameter follows:
332 %
333 %    o image_view: the image view.
334 %
335 */
336 MagickExport void *GetImageViewAuthenticMetacontent(
337   const ImageView *image_view)
338 {
339   assert(image_view != (ImageView *) NULL);
340   assert(image_view->signature == MagickSignature);
341   return(GetCacheViewAuthenticMetacontent(image_view->view));
342 }
343 \f
344 /*
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 %                                                                             %
347 %                                                                             %
348 %                                                                             %
349 %   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                     %
350 %                                                                             %
351 %                                                                             %
352 %                                                                             %
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 %
355 %  GetImageViewAuthenticPixels() returns the image view authentic pixels.
356 %
357 %  The format of the GetImageViewAuthenticPixels method is:
358 %
359 %      Quantum *GetImageViewAuthenticPixels(const ImageView *image_view)
360 %
361 %  A description of each parameter follows:
362 %
363 %    o image_view: the image view.
364 %
365 */
366 MagickExport Quantum *GetImageViewAuthenticPixels(
367   const ImageView *image_view)
368 {
369   assert(image_view != (ImageView *) NULL);
370   assert(image_view->signature == MagickSignature);
371   return(GetCacheViewAuthenticPixelQueue(image_view->view));
372 }
373 \f
374 /*
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 %                                                                             %
377 %                                                                             %
378 %                                                                             %
379 %   G e t I m a g e V i e w E x c e p t i o n                                 %
380 %                                                                             %
381 %                                                                             %
382 %                                                                             %
383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384 %
385 %  GetImageViewException() returns the severity, reason, and description of any
386 %  error that occurs when utilizing a image view.
387 %
388 %  The format of the GetImageViewException method is:
389 %
390 %      char *GetImageViewException(const PixelImage *image_view,
391 %        ExceptionType *severity)
392 %
393 %  A description of each parameter follows:
394 %
395 %    o image_view: the pixel image_view.
396 %
397 %    o severity: the severity of the error is returned here.
398 %
399 */
400 MagickExport char *GetImageViewException(const ImageView *image_view,
401   ExceptionType *severity)
402 {
403   char
404     *description;
405
406   assert(image_view != (const ImageView *) NULL);
407   assert(image_view->signature == MagickSignature);
408   assert(severity != (ExceptionType *) NULL);
409   *severity=image_view->exception->severity;
410   description=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
411     sizeof(*description));
412   if (description == (char *) NULL)
413     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
414   *description='\0';
415   if (image_view->exception->reason != (char *) NULL)
416     (void) CopyMagickString(description,GetLocaleExceptionMessage(
417       image_view->exception->severity,image_view->exception->reason),
418         MaxTextExtent);
419   if (image_view->exception->description != (char *) NULL)
420     {
421       (void) ConcatenateMagickString(description," (",MaxTextExtent);
422       (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
423         image_view->exception->severity,image_view->exception->description),
424         MaxTextExtent);
425       (void) ConcatenateMagickString(description,")",MaxTextExtent);
426     }
427   return(description);
428 }
429 \f
430 /*
431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 %                                                                             %
433 %                                                                             %
434 %                                                                             %
435 %   G e t I m a g e V i e w E x t e n t                                       %
436 %                                                                             %
437 %                                                                             %
438 %                                                                             %
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 %
441 %  GetImageViewExtent() returns the image view extent.
442 %
443 %  The format of the GetImageViewExtent method is:
444 %
445 %      RectangleInfo GetImageViewExtent(const ImageView *image_view)
446 %
447 %  A description of each parameter follows:
448 %
449 %    o image_view: the image view.
450 %
451 */
452 MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
453 {
454   assert(image_view != (ImageView *) NULL);
455   assert(image_view->signature == MagickSignature);
456   return(image_view->extent);
457 }
458 \f
459 /*
460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 %                                                                             %
462 %                                                                             %
463 %                                                                             %
464 %   G e t I m a g e V i e w I m a g e                                         %
465 %                                                                             %
466 %                                                                             %
467 %                                                                             %
468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469 %
470 %  GetImageViewImage() returns the image associated with the image view.
471 %
472 %  The format of the GetImageViewImage method is:
473 %
474 %      MagickCore *GetImageViewImage(const ImageView *image_view)
475 %
476 %  A description of each parameter follows:
477 %
478 %    o image_view: the image view.
479 %
480 */
481 MagickExport Image *GetImageViewImage(const ImageView *image_view)
482 {
483   assert(image_view != (ImageView *) NULL);
484   assert(image_view->signature == MagickSignature);
485   return(image_view->image);
486 }
487 \f
488 /*
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 %                                                                             %
491 %                                                                             %
492 %                                                                             %
493 %   G e t I m a g e V i e w I t e r a t o r                                   %
494 %                                                                             %
495 %                                                                             %
496 %                                                                             %
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498 %
499 %  GetImageViewIterator() iterates over the image view in parallel and calls
500 %  your get method for each scanline of the view.  The pixel extent is
501 %  not confined to the image canvas-- that is you can include negative offsets
502 %  or widths or heights that exceed the image dimension.  Any updates to
503 %  the pixels in your callback are ignored.
504 %
505 %  The callback signature is:
506 %
507 %      MagickBooleanType GetImageViewMethod(const ImageView *source,
508 %        const ssize_t y,const int thread_id,void *context)
509 %
510 %  Use this pragma if the view is not single threaded:
511 %
512 %    #pragma omp critical
513 %
514 %  to define a section of code in your callback get method that must be
515 %  executed by a single thread at a time.
516 %
517 %  The format of the GetImageViewIterator method is:
518 %
519 %      MagickBooleanType GetImageViewIterator(ImageView *source,
520 %        GetImageViewMethod get,void *context)
521 %
522 %  A description of each parameter follows:
523 %
524 %    o source: the source image view.
525 %
526 %    o get: the get callback method.
527 %
528 %    o context: the user defined context.
529 %
530 */
531 MagickExport MagickBooleanType GetImageViewIterator(ImageView *source,
532   GetImageViewMethod get,void *context)
533 {
534   Image
535     *source_image;
536
537   MagickBooleanType
538     status;
539
540   MagickOffsetType
541     progress;
542
543   ssize_t
544     y;
545
546   assert(source != (ImageView *) NULL);
547   assert(source->signature == MagickSignature);
548   if (get == (GetImageViewMethod) NULL)
549     return(MagickFalse);
550   source_image=source->image;
551   status=MagickTrue;
552   progress=0;
553 #if defined(MAGICKCORE_OPENMP_SUPPORT)
554   #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
555 #endif
556   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
557   {
558     const int
559       id = GetOpenMPThreadId();
560
561     register const Quantum
562       *pixels;
563
564     if (status == MagickFalse)
565       continue;
566     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
567       source->extent.width,1,source->exception);
568     if (pixels == (const Quantum *) NULL)
569       {
570         status=MagickFalse;
571         continue;
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 critical (MagickCore_GetImageViewIterator)
582 #endif
583         proceed=SetImageProgress(source_image,source->description,progress++,
584           source->extent.height);
585         if (proceed == MagickFalse)
586           status=MagickFalse;
587       }
588   }
589   return(status);
590 }
591 \f
592 /*
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594 %                                                                             %
595 %                                                                             %
596 %                                                                             %
597 %   G e t I m a g e V i e w V i r t u a l M e t a c o n t e n t     %
598 %                                                                             %
599 %                                                                             %
600 %                                                                             %
601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602 %
603 %  GetImageViewVirtualMetacontent() returns the image view virtual
604 %  meta-content.
605 %
606 %  The format of the GetImageViewVirtualMetacontent method is:
607 %
608 %      const void *GetImageViewVirtualMetacontent(
609 %        const ImageView *image_view)
610 %
611 %  A description of each parameter follows:
612 %
613 %    o image_view: the image view.
614 %
615 */
616 MagickExport const void *GetImageViewVirtualMetacontent(
617   const ImageView *image_view)
618 {
619   assert(image_view != (ImageView *) NULL);
620   assert(image_view->signature == MagickSignature);
621   return(GetCacheViewVirtualMetacontent(image_view->view));
622 }
623 \f
624 /*
625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626 %                                                                             %
627 %                                                                             %
628 %                                                                             %
629 %   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                         %
630 %                                                                             %
631 %                                                                             %
632 %                                                                             %
633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634 %
635 %  GetImageViewVirtualPixels() returns the image view virtual pixels.
636 %
637 %  The format of the GetImageViewVirtualPixels method is:
638 %
639 %      const Quantum *GetImageViewVirtualPixels(const ImageView *image_view)
640 %
641 %  A description of each parameter follows:
642 %
643 %    o image_view: the image view.
644 %
645 */
646 MagickExport const Quantum *GetImageViewVirtualPixels(
647   const ImageView *image_view)
648 {
649   assert(image_view != (ImageView *) NULL);
650   assert(image_view->signature == MagickSignature);
651   return(GetCacheViewVirtualPixelQueue(image_view->view));
652 }
653 \f
654 /*
655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 %                                                                             %
657 %                                                                             %
658 %                                                                             %
659 %   I s I m a g e V i e w                                                     %
660 %                                                                             %
661 %                                                                             %
662 %                                                                             %
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664 %
665 %  IsImageView() returns MagickTrue if the the parameter is verified as a image
666 %  view object.
667 %
668 %  The format of the IsImageView method is:
669 %
670 %      MagickBooleanType IsImageView(const ImageView *image_view)
671 %
672 %  A description of each parameter follows:
673 %
674 %    o image_view: the image view.
675 %
676 */
677 MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
678 {
679   if (image_view == (const ImageView *) NULL)
680     return(MagickFalse);
681   if (image_view->signature != MagickSignature)
682     return(MagickFalse);
683   return(MagickTrue);
684 }
685 \f
686 /*
687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 %                                                                             %
689 %                                                                             %
690 %                                                                             %
691 %   N e w I m a g e V i e w                                                   %
692 %                                                                             %
693 %                                                                             %
694 %                                                                             %
695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696 %
697 %  NewImageView() returns a image view required for all other methods in the
698 %  Image View API.
699 %
700 %  The format of the NewImageView method is:
701 %
702 %      ImageView *NewImageView(MagickCore *wand)
703 %
704 %  A description of each parameter follows:
705 %
706 %    o wand: the wand.
707 %
708 */
709 MagickExport ImageView *NewImageView(Image *image)
710 {
711   ImageView
712     *image_view;
713
714   assert(image != (Image *) NULL);
715   assert(image->signature == MagickSignature);
716   image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
717   if (image_view == (ImageView *) NULL)
718     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
719   (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
720   image_view->description=ConstantString("ImageView");
721   image_view->image=image;
722   image_view->view=AcquireCacheView(image_view->image);
723   image_view->extent.width=image->columns;
724   image_view->extent.height=image->rows;
725   image_view->extent.x=0;
726   image_view->extent.y=0;
727   image_view->number_threads=GetOpenMPMaximumThreads();
728   image_view->exception=AcquireExceptionInfo();
729   image_view->debug=IsEventLogging();
730   image_view->signature=MagickSignature;
731   return(image_view);
732 }
733 \f
734 /*
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
736 %                                                                             %
737 %                                                                             %
738 %                                                                             %
739 %   N e w I m a g e V i e w R e g i o n                                       %
740 %                                                                             %
741 %                                                                             %
742 %                                                                             %
743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
744 %
745 %  NewImageViewRegion() returns a image view required for all other methods
746 %  in the Image View API.
747 %
748 %  The format of the NewImageViewRegion method is:
749 %
750 %      ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
751 %        const ssize_t y,const size_t width,const size_t height)
752 %
753 %  A description of each parameter follows:
754 %
755 %    o wand: the magick wand.
756 %
757 %    o x,y,columns,rows:  These values define the perimeter of a extent of
758 %      pixel_wands view.
759 %
760 */
761 MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
762   const ssize_t y,const size_t width,const size_t height)
763 {
764   ImageView
765     *image_view;
766
767   assert(image != (Image *) NULL);
768   assert(image->signature == MagickSignature);
769   image_view=(ImageView *) AcquireMagickMemory(sizeof(*image_view));
770   if (image_view == (ImageView *) NULL)
771     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
772   (void) ResetMagickMemory(image_view,0,sizeof(*image_view));
773   image_view->description=ConstantString("ImageView");
774   image_view->view=AcquireCacheView(image_view->image);
775   image_view->image=image;
776   image_view->extent.width=width;
777   image_view->extent.height=height;
778   image_view->extent.x=x;
779   image_view->extent.y=y;
780   image_view->number_threads=GetOpenMPMaximumThreads();
781   image_view->exception=AcquireExceptionInfo();
782   image_view->debug=IsEventLogging();
783   image_view->signature=MagickSignature;
784   return(image_view);
785 }
786 \f
787 /*
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 %                                                                             %
790 %                                                                             %
791 %                                                                             %
792 %   S e t I m a g e V i e w D e s c r i p t i o n                             %
793 %                                                                             %
794 %                                                                             %
795 %                                                                             %
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797 %
798 %  SetImageViewDescription() associates a description with an image view.
799 %
800 %  The format of the SetImageViewDescription method is:
801 %
802 %      void SetImageViewDescription(ImageView *image_view,
803 %        const char *description)
804 %
805 %  A description of each parameter follows:
806 %
807 %    o image_view: the image view.
808 %
809 %    o description: the image view description.
810 %
811 */
812 MagickExport void SetImageViewDescription(ImageView *image_view,
813   const char *description)
814 {
815   assert(image_view != (ImageView *) NULL);
816   assert(image_view->signature == MagickSignature);
817   image_view->description=ConstantString(description);
818 }
819 \f
820 /*
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %                                                                             %
823 %                                                                             %
824 %                                                                             %
825 %   S e t I m a g e V i e w I t e r a t o r                                   %
826 %                                                                             %
827 %                                                                             %
828 %                                                                             %
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 %
831 %  SetImageViewIterator() iterates over the image view in parallel and calls
832 %  your set method for each scanline of the view.  The pixel extent is
833 %  confined to the image canvas-- that is no negative offsets or widths or
834 %  heights that exceed the image dimension.  The pixels are initiallly
835 %  undefined and any settings you make in the callback method are automagically
836 %  synced back to your image.
837 %
838 %  The callback signature is:
839 %
840 %      MagickBooleanType SetImageViewMethod(ImageView *destination,
841 %        const ssize_t y,const int thread_id,void *context)
842 %
843 %  Use this pragma if the view is not single threaded:
844 %
845 %    #pragma omp critical
846 %
847 %  to define a section of code in your callback set method that must be
848 %  executed by a single thread at a time.
849 %
850 %  The format of the SetImageViewIterator method is:
851 %
852 %      MagickBooleanType SetImageViewIterator(ImageView *destination,
853 %        SetImageViewMethod set,void *context)
854 %
855 %  A description of each parameter follows:
856 %
857 %    o destination: the image view.
858 %
859 %    o set: the set callback method.
860 %
861 %    o context: the user defined context.
862 %
863 */
864 MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
865   SetImageViewMethod set,void *context)
866 {
867   ExceptionInfo
868     *exception;
869
870   Image
871     *destination_image;
872
873   MagickBooleanType
874     status;
875
876   MagickOffsetType
877     progress;
878
879   ssize_t
880     y;
881
882   assert(destination != (ImageView *) NULL);
883   assert(destination->signature == MagickSignature);
884   if (set == (SetImageViewMethod) NULL)
885     return(MagickFalse);
886   destination_image=destination->image;
887   exception=destination->exception;
888   if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
889     return(MagickFalse);
890   status=MagickTrue;
891   progress=0;
892 #if defined(MAGICKCORE_OPENMP_SUPPORT)
893   #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(destination->number_threads)
894 #endif
895   for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
896   {
897     const int
898       id = GetOpenMPThreadId();
899
900     MagickBooleanType
901       sync;
902
903     register Quantum
904       *restrict pixels;
905
906     if (status == MagickFalse)
907       continue;
908     pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
909       y,destination->extent.width,1,exception);
910     if (pixels == (Quantum *) NULL)
911       {
912         InheritException(destination->exception,GetCacheViewException(
913           destination->view));
914         status=MagickFalse;
915         continue;
916       }
917     if (set(destination,y,id,context) == MagickFalse)
918       status=MagickFalse;
919     sync=SyncCacheViewAuthenticPixels(destination->view,exception);
920     if (sync == MagickFalse)
921       {
922         InheritException(destination->exception,GetCacheViewException(
923           destination->view));
924         status=MagickFalse;
925       }
926     if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
927       {
928         MagickBooleanType
929           proceed;
930
931 #if defined(MAGICKCORE_OPENMP_SUPPORT)
932   #pragma omp critical (MagickCore_SetImageViewIterator)
933 #endif
934         proceed=SetImageProgress(destination_image,destination->description,
935           progress++,destination->extent.height);
936         if (proceed == MagickFalse)
937           status=MagickFalse;
938       }
939   }
940   return(status);
941 }
942 \f
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 %                                                                             %
946 %                                                                             %
947 %                                                                             %
948 %   S e t I m a g e V i e w T h r e a d s                                     %
949 %                                                                             %
950 %                                                                             %
951 %                                                                             %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 %  SetImageViewThreads() sets the number of threads in a thread team.
955 %
956 %  The format of the SetImageViewDescription method is:
957 %
958 %      void SetImageViewThreads(ImageView *image_view,
959 %        const size_t number_threads)
960 %
961 %  A description of each parameter follows:
962 %
963 %    o image_view: the image view.
964 %
965 %    o number_threads: the number of threads in a thread team.
966 %
967 */
968 MagickExport void SetImageViewThreads(ImageView *image_view,
969   const size_t number_threads)
970 {
971   assert(image_view != (ImageView *) NULL);
972   assert(image_view->signature == MagickSignature);
973   image_view->number_threads=number_threads;
974   if (number_threads > GetOpenMPMaximumThreads())
975     image_view->number_threads=GetOpenMPMaximumThreads();
976 }
977 \f
978 /*
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 %                                                                             %
981 %                                                                             %
982 %                                                                             %
983 %   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                         %
984 %                                                                             %
985 %                                                                             %
986 %                                                                             %
987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
988 %
989 %  TransferImageViewIterator() iterates over two image views in parallel and
990 %  calls your transfer method for each scanline of the view.  The source pixel
991 %  extent is not confined to the image canvas-- that is you can include
992 %  negative offsets or widths or heights that exceed the image dimension.
993 %  However, the destination image view is confined to the image canvas-- that
994 %  is no negative offsets or widths or heights that exceed the image dimension
995 %  are permitted.
996 %
997 %  The callback signature is:
998 %
999 %      MagickBooleanType TransferImageViewMethod(const ImageView *source,
1000 %        ImageView *destination,const ssize_t y,const int thread_id,
1001 %        void *context)
1002 %
1003 %  Use this pragma if the view is not single threaded:
1004 %
1005 %    #pragma omp critical
1006 %
1007 %  to define a section of code in your callback transfer method that must be
1008 %  executed by a single thread at a time.
1009 %
1010 %  The format of the TransferImageViewIterator method is:
1011 %
1012 %      MagickBooleanType TransferImageViewIterator(ImageView *source,
1013 %        ImageView *destination,TransferImageViewMethod transfer,void *context)
1014 %
1015 %  A description of each parameter follows:
1016 %
1017 %    o source: the source image view.
1018 %
1019 %    o destination: the destination image view.
1020 %
1021 %    o transfer: the transfer callback method.
1022 %
1023 %    o context: the user defined context.
1024 %
1025 */
1026 MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
1027   ImageView *destination,TransferImageViewMethod transfer,void *context)
1028 {
1029   ExceptionInfo
1030     *exception;
1031
1032   Image
1033     *destination_image,
1034     *source_image;
1035
1036   MagickBooleanType
1037     status;
1038
1039   MagickOffsetType
1040     progress;
1041
1042   ssize_t
1043     y;
1044
1045   assert(source != (ImageView *) NULL);
1046   assert(source->signature == MagickSignature);
1047   if (transfer == (TransferImageViewMethod) NULL)
1048     return(MagickFalse);
1049   source_image=source->image;
1050   destination_image=destination->image;
1051   exception=destination->exception;
1052   if (SetImageStorageClass(destination_image,DirectClass,exception) == MagickFalse)
1053     return(MagickFalse);
1054   status=MagickTrue;
1055   progress=0;
1056 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1057   #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
1058 #endif
1059   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1060   {
1061     const int
1062       id = GetOpenMPThreadId();
1063
1064     MagickBooleanType
1065       sync;
1066
1067     register const Quantum
1068       *restrict pixels;
1069
1070     register Quantum
1071       *restrict destination_pixels;
1072
1073     if (status == MagickFalse)
1074       continue;
1075     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1076       source->extent.width,1,source->exception);
1077     if (pixels == (const Quantum *) NULL)
1078       {
1079         status=MagickFalse;
1080         continue;
1081       }
1082     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1083       destination->extent.x,y,destination->extent.width,1,exception);
1084     if (destination_pixels == (Quantum *) NULL)
1085       {
1086         status=MagickFalse;
1087         continue;
1088       }
1089     if (transfer(source,destination,y,id,context) == MagickFalse)
1090       status=MagickFalse;
1091     sync=SyncCacheViewAuthenticPixels(destination->view,exception);
1092     if (sync == MagickFalse)
1093       {
1094         InheritException(destination->exception,GetCacheViewException(
1095           source->view));
1096         status=MagickFalse;
1097       }
1098     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1099       {
1100         MagickBooleanType
1101           proceed;
1102
1103 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1104   #pragma omp critical (MagickCore_TransferImageViewIterator)
1105 #endif
1106         proceed=SetImageProgress(source_image,source->description,progress++,
1107           source->extent.height);
1108         if (proceed == MagickFalse)
1109           status=MagickFalse;
1110       }
1111   }
1112   return(status);
1113 }
1114 \f
1115 /*
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 %                                                                             %
1118 %                                                                             %
1119 %                                                                             %
1120 %   U p d a t e I m a g e V i e w I t e r a t o r                             %
1121 %                                                                             %
1122 %                                                                             %
1123 %                                                                             %
1124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1125 %
1126 %  UpdateImageViewIterator() iterates over the image view in parallel and calls
1127 %  your update method for each scanline of the view.  The pixel extent is
1128 %  confined to the image canvas-- that is no negative offsets or widths or
1129 %  heights that exceed the image dimension are permitted.  Updates to pixels
1130 %  in your callback are automagically synced back to the image.
1131 %
1132 %  The callback signature is:
1133 %
1134 %      MagickBooleanType UpdateImageViewMethod(ImageView *source,
1135 %        const ssize_t y,const int thread_id,void *context)
1136 %
1137 %  Use this pragma if the view is not single threaded:
1138 %
1139 %    #pragma omp critical
1140 %
1141 %  to define a section of code in your callback update method that must be
1142 %  executed by a single thread at a time.
1143 %
1144 %  The format of the UpdateImageViewIterator method is:
1145 %
1146 %      MagickBooleanType UpdateImageViewIterator(ImageView *source,
1147 %        UpdateImageViewMethod update,void *context)
1148 %
1149 %  A description of each parameter follows:
1150 %
1151 %    o source: the source image view.
1152 %
1153 %    o update: the update callback method.
1154 %
1155 %    o context: the user defined context.
1156 %
1157 */
1158 MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1159   UpdateImageViewMethod update,void *context)
1160 {
1161   ExceptionInfo
1162     *exception;
1163
1164   Image
1165     *source_image;
1166
1167   MagickBooleanType
1168     status;
1169
1170   MagickOffsetType
1171     progress;
1172
1173   ssize_t
1174     y;
1175
1176   assert(source != (ImageView *) NULL);
1177   assert(source->signature == MagickSignature);
1178   if (update == (UpdateImageViewMethod) NULL)
1179     return(MagickFalse);
1180   source_image=source->image;
1181   exception=source->exception;
1182   if (SetImageStorageClass(source_image,DirectClass,exception) == MagickFalse)
1183     return(MagickFalse);
1184   status=MagickTrue;
1185   progress=0;
1186 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1187   #pragma omp parallel for schedule(static,1) shared(progress,status) num_threads(source->number_threads)
1188 #endif
1189   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1190   {
1191     const int
1192       id = GetOpenMPThreadId();
1193
1194     register Quantum
1195       *restrict pixels;
1196
1197     if (status == MagickFalse)
1198       continue;
1199     pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1200       source->extent.width,1,exception);
1201     if (pixels == (Quantum *) NULL)
1202       {
1203         InheritException(source->exception,GetCacheViewException(source->view));
1204         status=MagickFalse;
1205         continue;
1206       }
1207     if (update(source,y,id,context) == MagickFalse)
1208       status=MagickFalse;
1209     if (SyncCacheViewAuthenticPixels(source->view,exception) == MagickFalse)
1210       {
1211         InheritException(source->exception,GetCacheViewException(source->view));
1212         status=MagickFalse;
1213       }
1214     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1215       {
1216         MagickBooleanType
1217           proceed;
1218
1219 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1220   #pragma omp critical (MagickCore_UpdateImageViewIterator)
1221 #endif
1222         proceed=SetImageProgress(source_image,source->description,progress++,
1223           source->extent.height);
1224         if (proceed == MagickFalse)
1225           status=MagickFalse;
1226       }
1227   }
1228   return(status);
1229 }