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