MagickCore  7.0.8
Convert, Edit, Or Compose Bitmap Images
image-view.c
Go to the documentation of this file.
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-2019 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"
54 
55 /*
56  Typedef declarations.
57 */
58 struct _ImageView
59 {
60  char
62 
65 
66  Image
68 
69  CacheView
70  *view;
71 
74 
77 
78  size_t
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 */
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 */
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 */
210  ImageView *source,ImageView *duplex,ImageView *destination,
211  DuplexTransferImageViewMethod transfer,void *context)
212 {
213  Image
214  *destination_image,
215  *source_image;
216 
218  status;
219 
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 
254  sync;
255 
256  register const Quantum
257  *magick_restrict duplex_pixels,
258  *magick_restrict pixels;
259 
260  register 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  {
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 */
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 */
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 */
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),
417  if (image_view->exception->description != (char *) NULL)
418  {
419  (void) ConcatenateMagickString(description," (",MagickPathExtent);
421  image_view->exception->severity,image_view->exception->description),
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 */
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 */
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 */
530  GetImageViewMethod get,void *context)
531 {
532  Image
533  *source_image;
534 
536  status;
537 
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  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  {
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 */
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 */
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 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 */
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 */
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 */
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 */
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 */
871  SetImageViewMethod set,void *context)
872 {
873  Image
874  *destination_image;
875 
877  status;
878 
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 
912  sync;
913 
914  register 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  {
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 */
998  ImageView *destination,TransferImageViewMethod transfer,void *context)
999 {
1000  Image
1001  *destination_image,
1002  *source_image;
1003 
1005  status;
1006 
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 
1041  sync;
1042 
1043  register const Quantum
1044  *magick_restrict pixels;
1045 
1046  register 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  {
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 */
1133  UpdateImageViewMethod update,void *context)
1134 {
1135  Image
1136  *source_image;
1137 
1139  status;
1140 
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  register 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 (status == MagickFalse)
1188  status=MagickFalse;
1189  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1190  {
1192  proceed;
1193 
1194 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1195  #pragma omp atomic
1196 #endif
1197  progress++;
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 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport CacheView * DestroyCacheView(CacheView *cache_view)
Definition: cache-view.c:252
MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source, ImageView *destination, TransferImageViewMethod transfer, void *context)
Definition: image-view.c:997
RectangleInfo extent
Definition: image-view.c:64
MagickProgressMonitor progress_monitor
Definition: image.h:303
MagickExport const Quantum * GetCacheViewVirtualPixelQueue(const CacheView *cache_view)
Definition: cache-view.c:601
MagickExport ImageView * CloneImageView(const ImageView *image_view)
Definition: image-view.c:104
MagickExport MagickBooleanType GetImageViewIterator(ImageView *source, GetImageViewMethod get, void *context)
Definition: image-view.c:529
#define ThrowFatalException(severity, tag)
MagickExport ImageView * DestroyImageView(ImageView *image_view)
Definition: image-view.c:145
MagickBooleanType(*)(* GetImageViewMethod)(const ImageView *, const ssize_t, const int, void *)
Definition: image-view.h:31
MagickBooleanType debug
Definition: image-view.c:76
MagickExport size_t ConcatenateMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:426
MagickBooleanType(* DuplexTransferImageViewMethod)(const ImageView *, const ImageView *, ImageView *, const ssize_t, const int, void *)
Definition: image-view.h:29
MagickExport const void * GetImageViewVirtualMetacontent(const ImageView *image_view)
Definition: image-view.c:622
MagickExport ExceptionInfo * AcquireExceptionInfo(void)
Definition: exception.c:108
static void * AcquireCriticalMemory(const size_t size)
MagickExport const Quantum * GetCacheViewVirtualPixels(const CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:651
Image * image
Definition: image-view.c:67
size_t width
Definition: geometry.h:130
ssize_t MagickOffsetType
Definition: magick-type.h:129
Definition: image.h:151
ExceptionType
Definition: exception.h:27
MagickExport Quantum * GetImageViewAuthenticPixels(const ImageView *image_view)
Definition: image-view.c:364
#define MagickCoreSignature
MagickExport Quantum * GetCacheViewAuthenticPixels(CacheView *cache_view, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache-view.c:299
MagickExport ImageView * NewImageView(Image *image, ExceptionInfo *exception)
Definition: image-view.c:717
CacheView * view
Definition: image-view.c:70
MagickBooleanType
Definition: magick-type.h:158
MagickBooleanType(*)(*)(* SetImageViewMethod)(ImageView *, const ssize_t, const int, void *)
Definition: image-view.h:32
size_t signature
Definition: image-view.c:79
char * description
Definition: image-view.c:61
ExceptionInfo * exception
Definition: image-view.c:73
char * reason
Definition: exception.h:110
MagickExport char * GetImageViewException(const ImageView *image_view, ExceptionType *severity)
Definition: image-view.c:398
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:533
static int GetOpenMPThreadId(void)
MagickExport void * GetCacheViewAuthenticMetacontent(CacheView *cache_view)
Definition: cache-view.c:342
MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source, UpdateImageViewMethod update, void *context)
Definition: image-view.c:1132
MagickExport void * GetImageViewAuthenticMetacontent(const ImageView *image_view)
Definition: image-view.c:334
MagickExport const void * GetCacheViewVirtualMetacontent(const CacheView *cache_view)
Definition: cache-view.c:558
MagickExport RectangleInfo GetImageViewExtent(const ImageView *image_view)
Definition: image-view.c:450
#define MagickPathExtent
MagickExport MagickBooleanType IsEventLogging(void)
Definition: log.c:717
MagickExport void SetImageViewDescription(ImageView *image_view, const char *description)
Definition: image-view.c:818
MagickExport const Quantum * GetImageViewVirtualPixels(const ImageView *image_view)
Definition: image-view.c:652
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
MagickBooleanType(* MagickProgressMonitor)(const char *, const MagickOffsetType, const MagickSizeType, void *)
Definition: monitor.h:26
ssize_t x
Definition: geometry.h:134
size_t height
Definition: geometry.h:130
MagickExport MagickBooleanType SetImageStorageClass(Image *image, const ClassType storage_class, ExceptionInfo *exception)
Definition: image.c:2614
MagickExport size_t CopyMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:755
MagickExport CacheView * CloneCacheView(const CacheView *cache_view)
Definition: cache-view.c:205
MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination, SetImageViewMethod set, void *context)
Definition: image-view.c:870
MagickBooleanType(*)(*)(*)(* TransferImageViewMethod)(const ImageView *, ImageView *, const ssize_t, const int, void *)
Definition: image-view.h:33
MagickExport CacheView * AcquireVirtualCacheView(const Image *image, ExceptionInfo *exception)
Definition: cache-view.c:149
MagickBooleanType(*)(*)(*)(*)(* UpdateImageViewMethod)(ImageView *, const ssize_t, const int, void *)
Definition: image-view.h:35
unsigned short Quantum
Definition: magick-type.h:82
MagickExport char * DestroyString(char *string)
Definition: string.c:823
MagickExport Quantum * GetCacheViewAuthenticPixelQueue(CacheView *cache_view)
Definition: cache-view.c:379
MagickExport MagickBooleanType IsImageView(const ImageView *image_view)
Definition: image-view.c:683
MagickExport MagickBooleanType DuplexTransferImageViewIterator(ImageView *source, ImageView *duplex, ImageView *destination, DuplexTransferImageViewMethod transfer, void *context)
Definition: image-view.c:209
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1054
MagickExport Image * GetImageViewImage(const ImageView *image_view)
Definition: image-view.c:479
#define MagickExport
MagickExport MagickBooleanType SyncCacheViewAuthenticPixels(CacheView *magick_restrict cache_view, ExceptionInfo *exception)
Definition: cache-view.c:1100
ssize_t y
Definition: geometry.h:134
MagickExport ImageView * NewImageViewRegion(Image *image, const ssize_t x, const ssize_t y, const size_t width, const size_t height, ExceptionInfo *exception)
Definition: image-view.c:769
MagickExport const char * GetLocaleExceptionMessage(const ExceptionType severity, const char *tag)
Definition: exception.c:584
char * description
Definition: exception.h:110
MagickExport char * ConstantString(const char *source)
Definition: string.c:700
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition: exception.c:411
MagickExport void InheritException(ExceptionInfo *exception, const ExceptionInfo *relative)
Definition: exception.c:628
ExceptionType severity
Definition: exception.h:104