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