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