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