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