• 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-2021 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 %    https://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/memory-private.h"
52 #include "MagickCore/monitor-private.h"
53 #include "MagickCore/thread-private.h"
54 
55 /*
56   Typedef declarations.
57 */
58 struct _ImageView
59 {
60   char
61     *description;
62 
63   RectangleInfo
64     extent;
65 
66   Image
67     *image;
68 
69   CacheView
70     *view;
71 
72   ExceptionInfo
73     *exception;
74 
75   MagickBooleanType
76     debug;
77 
78   size_t
79     signature;
80 };
81 
82 /*
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 %                                                                             %
85 %                                                                             %
86 %                                                                             %
87 %   C l o n e I m a g e V i e w                                               %
88 %                                                                             %
89 %                                                                             %
90 %                                                                             %
91 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92 %
93 %  CloneImageView() makes a copy of the specified image view.
94 %
95 %  The format of the CloneImageView method is:
96 %
97 %      ImageView *CloneImageView(const ImageView *image_view)
98 %
99 %  A description of each parameter follows:
100 %
101 %    o image_view: the image view.
102 %
103 */
CloneImageView(const ImageView * image_view)104 MagickExport ImageView *CloneImageView(const ImageView *image_view)
105 {
106   ImageView
107     *clone_view;
108 
109   assert(image_view != (ImageView *) NULL);
110   assert(image_view->signature == MagickCoreSignature);
111   clone_view=(ImageView *) AcquireCriticalMemory(sizeof(*clone_view));
112   (void) memset(clone_view,0,sizeof(*clone_view));
113   clone_view->description=ConstantString(image_view->description);
114   clone_view->extent=image_view->extent;
115   clone_view->view=CloneCacheView(image_view->view);
116   clone_view->exception=AcquireExceptionInfo();
117   InheritException(clone_view->exception,image_view->exception);
118   clone_view->debug=image_view->debug;
119   clone_view->signature=MagickCoreSignature;
120   return(clone_view);
121 }
122 
123 /*
124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 %                                                                             %
126 %                                                                             %
127 %                                                                             %
128 %   D e s t r o y I m a g e V i e w                                           %
129 %                                                                             %
130 %                                                                             %
131 %                                                                             %
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 %
134 %  DestroyImageView() deallocates memory associated with a image view.
135 %
136 %  The format of the DestroyImageView method is:
137 %
138 %      ImageView *DestroyImageView(ImageView *image_view)
139 %
140 %  A description of each parameter follows:
141 %
142 %    o image_view: the image view.
143 %
144 */
DestroyImageView(ImageView * image_view)145 MagickExport ImageView *DestroyImageView(ImageView *image_view)
146 {
147   assert(image_view != (ImageView *) NULL);
148   assert(image_view->signature == MagickCoreSignature);
149   if (image_view->description != (char *) NULL)
150     image_view->description=DestroyString(image_view->description);
151   image_view->view=DestroyCacheView(image_view->view);
152   image_view->exception=DestroyExceptionInfo(image_view->exception);
153   image_view->signature=(~MagickCoreSignature);
154   image_view=(ImageView *) RelinquishMagickMemory(image_view);
155   return(image_view);
156 }
157 
158 /*
159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160 %                                                                             %
161 %                                                                             %
162 %                                                                             %
163 %   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             %
164 %                                                                             %
165 %                                                                             %
166 %                                                                             %
167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 %
169 %  DuplexTransferImageViewIterator() iterates over three image views in
170 %  parallel and calls your transfer method for each scanline of the view.  The
171 %  source and duplex pixel extent is not confined to the image canvas-- that is
172 %  you can include negative offsets or widths or heights that exceed the image
173 %  dimension.  However, the destination image view is confined to the image
174 %  canvas-- that is no negative offsets or widths or heights that exceed the
175 %  image dimension are permitted.
176 %
177 %  The callback signature is:
178 %
179 %      MagickBooleanType DuplexTransferImageViewMethod(const ImageView *source,
180 %        const ImageView *duplex,ImageView *destination,const ssize_t y,
181 %        const int thread_id,void *context)
182 %
183 %  Use this pragma if the view is not single threaded:
184 %
185 %    #pragma omp critical
186 %
187 %  to define a section of code in your callback transfer method that must be
188 %  executed by a single thread at a time.
189 %
190 %  The format of the DuplexTransferImageViewIterator method is:
191 %
192 %      MagickBooleanType DuplexTransferImageViewIterator(ImageView *source,
193 %        ImageView *duplex,ImageView *destination,
194 %        DuplexTransferImageViewMethod transfer,void *context)
195 %
196 %  A description of each parameter follows:
197 %
198 %    o source: the source image view.
199 %
200 %    o duplex: the duplex image view.
201 %
202 %    o destination: the destination image view.
203 %
204 %    o transfer: the transfer callback method.
205 %
206 %    o context: the user defined context.
207 %
208 */
DuplexTransferImageViewIterator(ImageView * source,ImageView * duplex,ImageView * destination,DuplexTransferImageViewMethod transfer,void * context)209 MagickExport MagickBooleanType DuplexTransferImageViewIterator(
210   ImageView *source,ImageView *duplex,ImageView *destination,
211   DuplexTransferImageViewMethod transfer,void *context)
212 {
213   Image
214     *destination_image,
215     *source_image;
216 
217   MagickBooleanType
218     status;
219 
220   MagickOffsetType
221     progress;
222 
223 #if defined(MAGICKCORE_OPENMP_SUPPORT)
224   size_t
225     height;
226 #endif
227 
228   ssize_t
229     y;
230 
231   assert(source != (ImageView *) NULL);
232   assert(source->signature == MagickCoreSignature);
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   height=source->extent.height-source->extent.y;
245   #pragma omp parallel for schedule(static) shared(progress,status) \
246     magick_number_threads(source_image,destination_image,height,1)
247 #endif
248   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
249   {
250     const int
251       id = GetOpenMPThreadId();
252 
253     MagickBooleanType
254       sync;
255 
256     const Quantum
257       *magick_restrict duplex_pixels,
258       *magick_restrict pixels;
259 
260     Quantum
261       *magick_restrict destination_pixels;
262 
263     if (status == MagickFalse)
264       continue;
265     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
266       source->extent.width,1,source->exception);
267     if (pixels == (const Quantum *) NULL)
268       {
269         status=MagickFalse;
270         continue;
271       }
272     duplex_pixels=GetCacheViewVirtualPixels(duplex->view,duplex->extent.x,y,
273       duplex->extent.width,1,duplex->exception);
274     if (duplex_pixels == (const Quantum *) NULL)
275       {
276         status=MagickFalse;
277         continue;
278       }
279     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
280       destination->extent.x,y,destination->extent.width,1,
281       destination->exception);
282     if (destination_pixels == (Quantum *) NULL)
283       {
284         status=MagickFalse;
285         continue;
286       }
287     if (transfer(source,duplex,destination,y,id,context) == MagickFalse)
288       status=MagickFalse;
289     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
290     if (sync == MagickFalse)
291       status=MagickFalse;
292     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
293       {
294         MagickBooleanType
295           proceed;
296 
297 #if defined(MAGICKCORE_OPENMP_SUPPORT)
298         #pragma omp atomic
299 #endif
300         progress++;
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(MagickPathExtent,
409     2*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) shared(progress,status) \
559     magick_number_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     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 atomic
587 #endif
588         progress++;
589         proceed=SetImageProgress(source_image,source->description,progress,
590           source->extent.height);
591         if (proceed == MagickFalse)
592           status=MagickFalse;
593       }
594   }
595   return(status);
596 }
597 
598 /*
599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600 %                                                                             %
601 %                                                                             %
602 %                                                                             %
603 %   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     %
604 %                                                                             %
605 %                                                                             %
606 %                                                                             %
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 %
609 %  GetImageViewVirtualMetacontent() returns the image view virtual
610 %  meta-content.
611 %
612 %  The format of the GetImageViewVirtualMetacontent method is:
613 %
614 %      const void *GetImageViewVirtualMetacontent(
615 %        const ImageView *image_view)
616 %
617 %  A description of each parameter follows:
618 %
619 %    o image_view: the image view.
620 %
621 */
GetImageViewVirtualMetacontent(const ImageView * image_view)622 MagickExport const void *GetImageViewVirtualMetacontent(
623   const ImageView *image_view)
624 {
625   assert(image_view != (ImageView *) NULL);
626   assert(image_view->signature == MagickCoreSignature);
627   return(GetCacheViewVirtualMetacontent(image_view->view));
628 }
629 
630 /*
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 %                                                                             %
633 %                                                                             %
634 %                                                                             %
635 %   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                         %
636 %                                                                             %
637 %                                                                             %
638 %                                                                             %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 %
641 %  GetImageViewVirtualPixels() returns the image view virtual pixels.
642 %
643 %  The format of the GetImageViewVirtualPixels method is:
644 %
645 %      const Quantum *GetImageViewVirtualPixels(const ImageView *image_view)
646 %
647 %  A description of each parameter follows:
648 %
649 %    o image_view: the image view.
650 %
651 */
GetImageViewVirtualPixels(const ImageView * image_view)652 MagickExport const Quantum *GetImageViewVirtualPixels(
653   const ImageView *image_view)
654 {
655   assert(image_view != (ImageView *) NULL);
656   assert(image_view->signature == MagickCoreSignature);
657   return(GetCacheViewVirtualPixelQueue(image_view->view));
658 }
659 
660 /*
661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662 %                                                                             %
663 %                                                                             %
664 %                                                                             %
665 %   I s I m a g e V i e w                                                     %
666 %                                                                             %
667 %                                                                             %
668 %                                                                             %
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 %
671 %  IsImageView() returns MagickTrue if the parameter is verified as a image
672 %  view object.
673 %
674 %  The format of the IsImageView method is:
675 %
676 %      MagickBooleanType IsImageView(const ImageView *image_view)
677 %
678 %  A description of each parameter follows:
679 %
680 %    o image_view: the image view.
681 %
682 */
IsImageView(const ImageView * image_view)683 MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
684 {
685   if (image_view == (const ImageView *) NULL)
686     return(MagickFalse);
687   if (image_view->signature != MagickCoreSignature)
688     return(MagickFalse);
689   return(MagickTrue);
690 }
691 
692 /*
693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694 %                                                                             %
695 %                                                                             %
696 %                                                                             %
697 %   N e w I m a g e V i e w                                                   %
698 %                                                                             %
699 %                                                                             %
700 %                                                                             %
701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 %
703 %  NewImageView() returns a image view required for all other methods in the
704 %  Image View API.
705 %
706 %  The format of the NewImageView method is:
707 %
708 %      ImageView *NewImageView(MagickCore *wand,ExceptionInfo *exception)
709 %
710 %  A description of each parameter follows:
711 %
712 %    o image: the image.
713 %
714 %    o exception: return any errors or warnings in this structure.
715 %
716 */
NewImageView(Image * image,ExceptionInfo * exception)717 MagickExport ImageView *NewImageView(Image *image,ExceptionInfo *exception)
718 {
719   ImageView
720     *image_view;
721 
722   assert(image != (Image *) NULL);
723   assert(image->signature == MagickCoreSignature);
724   image_view=(ImageView *) AcquireCriticalMemory(sizeof(*image_view));
725   (void) memset(image_view,0,sizeof(*image_view));
726   image_view->description=ConstantString("ImageView");
727   image_view->image=image;
728   image_view->view=AcquireVirtualCacheView(image_view->image,exception);
729   image_view->extent.width=image->columns;
730   image_view->extent.height=image->rows;
731   image_view->extent.x=0;
732   image_view->extent.y=0;
733   image_view->exception=AcquireExceptionInfo();
734   image_view->debug=IsEventLogging();
735   image_view->signature=MagickCoreSignature;
736   return(image_view);
737 }
738 
739 /*
740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
741 %                                                                             %
742 %                                                                             %
743 %                                                                             %
744 %   N e w I m a g e V i e w R e g i o n                                       %
745 %                                                                             %
746 %                                                                             %
747 %                                                                             %
748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 %
750 %  NewImageViewRegion() returns a image view required for all other methods
751 %  in the Image View API.
752 %
753 %  The format of the NewImageViewRegion method is:
754 %
755 %      ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
756 %        const ssize_t y,const size_t width,const size_t height,
757 %        ExceptionInfo *exception)
758 %
759 %  A description of each parameter follows:
760 %
761 %    o wand: the magick wand.
762 %
763 %    o x,y,columns,rows:  These values define the perimeter of a extent of
764 %      pixel_wands view.
765 %
766 %    o exception: return any errors or warnings in this structure.
767 %
768 */
NewImageViewRegion(Image * image,const ssize_t x,const ssize_t y,const size_t width,const size_t height,ExceptionInfo * exception)769 MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
770   const ssize_t y,const size_t width,const size_t height,
771   ExceptionInfo *exception)
772 {
773   ImageView
774     *image_view;
775 
776   assert(image != (Image *) NULL);
777   assert(image->signature == MagickCoreSignature);
778   image_view=(ImageView *) AcquireCriticalMemory(sizeof(*image_view));
779   (void) memset(image_view,0,sizeof(*image_view));
780   image_view->description=ConstantString("ImageView");
781   image_view->view=AcquireVirtualCacheView(image_view->image,exception);
782   image_view->image=image;
783   image_view->extent.width=width;
784   image_view->extent.height=height;
785   image_view->extent.x=x;
786   image_view->extent.y=y;
787   image_view->exception=AcquireExceptionInfo();
788   image_view->debug=IsEventLogging();
789   image_view->signature=MagickCoreSignature;
790   return(image_view);
791 }
792 
793 /*
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %                                                                             %
796 %                                                                             %
797 %                                                                             %
798 %   S e t I m a g e V i e w D e s c r i p t i o n                             %
799 %                                                                             %
800 %                                                                             %
801 %                                                                             %
802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803 %
804 %  SetImageViewDescription() associates a description with an image view.
805 %
806 %  The format of the SetImageViewDescription method is:
807 %
808 %      void SetImageViewDescription(ImageView *image_view,
809 %        const char *description)
810 %
811 %  A description of each parameter follows:
812 %
813 %    o image_view: the image view.
814 %
815 %    o description: the image view description.
816 %
817 */
SetImageViewDescription(ImageView * image_view,const char * description)818 MagickExport void SetImageViewDescription(ImageView *image_view,
819   const char *description)
820 {
821   assert(image_view != (ImageView *) NULL);
822   assert(image_view->signature == MagickCoreSignature);
823   image_view->description=ConstantString(description);
824 }
825 
826 /*
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828 %                                                                             %
829 %                                                                             %
830 %                                                                             %
831 %   S e t I m a g e V i e w I t e r a t o r                                   %
832 %                                                                             %
833 %                                                                             %
834 %                                                                             %
835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836 %
837 %  SetImageViewIterator() iterates over the image view in parallel and calls
838 %  your set method for each scanline of the view.  The pixel extent is
839 %  confined to the image canvas-- that is no negative offsets or widths or
840 %  heights that exceed the image dimension.  The pixels are initiallly
841 %  undefined and any settings you make in the callback method are automagically
842 %  synced back to your image.
843 %
844 %  The callback signature is:
845 %
846 %      MagickBooleanType SetImageViewMethod(ImageView *destination,
847 %        const ssize_t y,const int thread_id,void *context)
848 %
849 %  Use this pragma if the view is not single threaded:
850 %
851 %    #pragma omp critical
852 %
853 %  to define a section of code in your callback set method that must be
854 %  executed by a single thread at a time.
855 %
856 %  The format of the SetImageViewIterator method is:
857 %
858 %      MagickBooleanType SetImageViewIterator(ImageView *destination,
859 %        SetImageViewMethod set,void *context)
860 %
861 %  A description of each parameter follows:
862 %
863 %    o destination: the image view.
864 %
865 %    o set: the set callback method.
866 %
867 %    o context: the user defined context.
868 %
869 */
SetImageViewIterator(ImageView * destination,SetImageViewMethod set,void * context)870 MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
871   SetImageViewMethod set,void *context)
872 {
873   Image
874     *destination_image;
875 
876   MagickBooleanType
877     status;
878 
879   MagickOffsetType
880     progress;
881 
882 #if defined(MAGICKCORE_OPENMP_SUPPORT)
883   size_t
884     height;
885 #endif
886 
887   ssize_t
888     y;
889 
890   assert(destination != (ImageView *) NULL);
891   assert(destination->signature == MagickCoreSignature);
892   if (set == (SetImageViewMethod) NULL)
893     return(MagickFalse);
894   destination_image=destination->image;
895   status=SetImageStorageClass(destination_image,DirectClass,
896     destination->exception);
897   if (status == MagickFalse)
898     return(MagickFalse);
899   status=MagickTrue;
900   progress=0;
901 #if defined(MAGICKCORE_OPENMP_SUPPORT)
902   height=destination->extent.height-destination->extent.y;
903   #pragma omp parallel for schedule(static) shared(progress,status) \
904     magick_number_threads(destination_image,destination_image,height,1)
905 #endif
906   for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
907   {
908     const int
909       id = GetOpenMPThreadId();
910 
911     MagickBooleanType
912       sync;
913 
914     Quantum
915       *magick_restrict pixels;
916 
917     if (status == MagickFalse)
918       continue;
919     pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
920       y,destination->extent.width,1,destination->exception);
921     if (pixels == (Quantum *) NULL)
922       {
923         status=MagickFalse;
924         continue;
925       }
926     if (set(destination,y,id,context) == MagickFalse)
927       status=MagickFalse;
928     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
929     if (sync == MagickFalse)
930       status=MagickFalse;
931     if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
932       {
933         MagickBooleanType
934           proceed;
935 
936 #if defined(MAGICKCORE_OPENMP_SUPPORT)
937         #pragma omp atomic
938 #endif
939         progress++;
940         proceed=SetImageProgress(destination_image,destination->description,
941           progress,destination->extent.height);
942         if (proceed == MagickFalse)
943           status=MagickFalse;
944       }
945   }
946   return(status);
947 }
948 
949 /*
950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %   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                         %
955 %                                                                             %
956 %                                                                             %
957 %                                                                             %
958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959 %
960 %  TransferImageViewIterator() iterates over two image views in parallel and
961 %  calls your transfer method for each scanline of the view.  The source pixel
962 %  extent is not confined to the image canvas-- that is you can include
963 %  negative offsets or widths or heights that exceed the image dimension.
964 %  However, the destination image view is confined to the image canvas-- that
965 %  is no negative offsets or widths or heights that exceed the image dimension
966 %  are permitted.
967 %
968 %  The callback signature is:
969 %
970 %      MagickBooleanType TransferImageViewMethod(const ImageView *source,
971 %        ImageView *destination,const ssize_t y,const int thread_id,
972 %        void *context)
973 %
974 %  Use this pragma if the view is not single threaded:
975 %
976 %    #pragma omp critical
977 %
978 %  to define a section of code in your callback transfer method that must be
979 %  executed by a single thread at a time.
980 %
981 %  The format of the TransferImageViewIterator method is:
982 %
983 %      MagickBooleanType TransferImageViewIterator(ImageView *source,
984 %        ImageView *destination,TransferImageViewMethod transfer,void *context)
985 %
986 %  A description of each parameter follows:
987 %
988 %    o source: the source image view.
989 %
990 %    o destination: the destination image view.
991 %
992 %    o transfer: the transfer callback method.
993 %
994 %    o context: the user defined context.
995 %
996 */
TransferImageViewIterator(ImageView * source,ImageView * destination,TransferImageViewMethod transfer,void * context)997 MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
998   ImageView *destination,TransferImageViewMethod transfer,void *context)
999 {
1000   Image
1001     *destination_image,
1002     *source_image;
1003 
1004   MagickBooleanType
1005     status;
1006 
1007   MagickOffsetType
1008     progress;
1009 
1010 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1011   size_t
1012     height;
1013 #endif
1014 
1015   ssize_t
1016     y;
1017 
1018   assert(source != (ImageView *) NULL);
1019   assert(source->signature == MagickCoreSignature);
1020   if (transfer == (TransferImageViewMethod) NULL)
1021     return(MagickFalse);
1022   source_image=source->image;
1023   destination_image=destination->image;
1024   status=SetImageStorageClass(destination_image,DirectClass,
1025     destination->exception);
1026   if (status == MagickFalse)
1027     return(MagickFalse);
1028   status=MagickTrue;
1029   progress=0;
1030 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1031   height=source->extent.height-source->extent.y;
1032   #pragma omp parallel for schedule(static) shared(progress,status) \
1033     magick_number_threads(source_image,destination_image,height,1)
1034 #endif
1035   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1036   {
1037     const int
1038       id = GetOpenMPThreadId();
1039 
1040     MagickBooleanType
1041       sync;
1042 
1043     const Quantum
1044       *magick_restrict pixels;
1045 
1046     Quantum
1047       *magick_restrict destination_pixels;
1048 
1049     if (status == MagickFalse)
1050       continue;
1051     pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1052       source->extent.width,1,source->exception);
1053     if (pixels == (const Quantum *) NULL)
1054       {
1055         status=MagickFalse;
1056         continue;
1057       }
1058     destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1059       destination->extent.x,y,destination->extent.width,1,
1060       destination->exception);
1061     if (destination_pixels == (Quantum *) NULL)
1062       {
1063         status=MagickFalse;
1064         continue;
1065       }
1066     if (transfer(source,destination,y,id,context) == MagickFalse)
1067       status=MagickFalse;
1068     sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1069     if (sync == MagickFalse)
1070       status=MagickFalse;
1071     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1072       {
1073         MagickBooleanType
1074           proceed;
1075 
1076 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1077         #pragma omp atomic
1078 #endif
1079         progress++;
1080         proceed=SetImageProgress(source_image,source->description,progress,
1081           source->extent.height);
1082         if (proceed == MagickFalse)
1083           status=MagickFalse;
1084       }
1085   }
1086   return(status);
1087 }
1088 
1089 /*
1090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091 %                                                                             %
1092 %                                                                             %
1093 %                                                                             %
1094 %   U p d a t e I m a g e V i e w I t e r a t o r                             %
1095 %                                                                             %
1096 %                                                                             %
1097 %                                                                             %
1098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099 %
1100 %  UpdateImageViewIterator() iterates over the image view in parallel and calls
1101 %  your update method for each scanline of the view.  The pixel extent is
1102 %  confined to the image canvas-- that is no negative offsets or widths or
1103 %  heights that exceed the image dimension are permitted.  Updates to pixels
1104 %  in your callback are automagically synced back to the image.
1105 %
1106 %  The callback signature is:
1107 %
1108 %      MagickBooleanType UpdateImageViewMethod(ImageView *source,
1109 %        const ssize_t y,const int thread_id,void *context)
1110 %
1111 %  Use this pragma if the view is not single threaded:
1112 %
1113 %    #pragma omp critical
1114 %
1115 %  to define a section of code in your callback update method that must be
1116 %  executed by a single thread at a time.
1117 %
1118 %  The format of the UpdateImageViewIterator method is:
1119 %
1120 %      MagickBooleanType UpdateImageViewIterator(ImageView *source,
1121 %        UpdateImageViewMethod update,void *context)
1122 %
1123 %  A description of each parameter follows:
1124 %
1125 %    o source: the source image view.
1126 %
1127 %    o update: the update callback method.
1128 %
1129 %    o context: the user defined context.
1130 %
1131 */
UpdateImageViewIterator(ImageView * source,UpdateImageViewMethod update,void * context)1132 MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1133   UpdateImageViewMethod update,void *context)
1134 {
1135   Image
1136     *source_image;
1137 
1138   MagickBooleanType
1139     status;
1140 
1141   MagickOffsetType
1142     progress;
1143 
1144 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1145   size_t
1146     height;
1147 #endif
1148 
1149   ssize_t
1150     y;
1151 
1152   assert(source != (ImageView *) NULL);
1153   assert(source->signature == MagickCoreSignature);
1154   if (update == (UpdateImageViewMethod) NULL)
1155     return(MagickFalse);
1156   source_image=source->image;
1157   status=SetImageStorageClass(source_image,DirectClass,source->exception);
1158   if (status == MagickFalse)
1159     return(MagickFalse);
1160   status=MagickTrue;
1161   progress=0;
1162 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1163   height=source->extent.height-source->extent.y;
1164   #pragma omp parallel for schedule(static) shared(progress,status) \
1165     magick_number_threads(source_image,source_image,height,1)
1166 #endif
1167   for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1168   {
1169     const int
1170       id = GetOpenMPThreadId();
1171 
1172     Quantum
1173       *magick_restrict pixels;
1174 
1175     if (status == MagickFalse)
1176       continue;
1177     pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1178       source->extent.width,1,source->exception);
1179     if (pixels == (Quantum *) NULL)
1180       {
1181         status=MagickFalse;
1182         continue;
1183       }
1184     if (update(source,y,id,context) == MagickFalse)
1185       status=MagickFalse;
1186     status=SyncCacheViewAuthenticPixels(source->view,source->exception);
1187     if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1188       {
1189         MagickBooleanType
1190           proceed;
1191 
1192 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1193         #pragma omp atomic
1194 #endif
1195         progress++;
1196         proceed=SetImageProgress(source_image,source->description,progress,
1197           source->extent.height);
1198         if (proceed == MagickFalse)
1199           status=MagickFalse;
1200       }
1201   }
1202   return(status);
1203 }
1204