MagickCore  7.1.0
Convert, Edit, Or Compose Bitmap Images
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 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 
64  extent;
65 
66  Image
67  *image;
68 
69  CacheView
70  *view;
71 
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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=(GetLogEventMask() & ImageEvent) != 0 ? MagickTrue :
735  MagickFalse;
736  image_view->signature=MagickCoreSignature;
737  return(image_view);
738 }
739 ␌
740 /*
741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
742 % %
743 % %
744 % %
745 % N e w I m a g e V i e w R e g i o n %
746 % %
747 % %
748 % %
749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
750 %
751 % NewImageViewRegion() returns a image view required for all other methods
752 % in the Image View API.
753 %
754 % The format of the NewImageViewRegion method is:
755 %
756 % ImageView *NewImageViewRegion(MagickCore *wand,const ssize_t x,
757 % const ssize_t y,const size_t width,const size_t height,
758 % ExceptionInfo *exception)
759 %
760 % A description of each parameter follows:
761 %
762 % o wand: the magick wand.
763 %
764 % o x,y,columns,rows: These values define the perimeter of a extent of
765 % pixel_wands view.
766 %
767 % o exception: return any errors or warnings in this structure.
768 %
769 */
770 MagickExport ImageView *NewImageViewRegion(Image *image,const ssize_t x,
771  const ssize_t y,const size_t width,const size_t height,
772  ExceptionInfo *exception)
773 {
774  ImageView
775  *image_view;
776 
777  assert(image != (Image *) NULL);
778  assert(image->signature == MagickCoreSignature);
779  image_view=(ImageView *) AcquireCriticalMemory(sizeof(*image_view));
780  (void) memset(image_view,0,sizeof(*image_view));
781  image_view->description=ConstantString("ImageView");
782  image_view->view=AcquireVirtualCacheView(image_view->image,exception);
783  image_view->image=image;
784  image_view->extent.width=width;
785  image_view->extent.height=height;
786  image_view->extent.x=x;
787  image_view->extent.y=y;
788  image_view->exception=AcquireExceptionInfo();
789  image_view->debug=(GetLogEventMask() & ImageEvent) != 0 ? MagickTrue :
790  MagickFalse;
791  image_view->signature=MagickCoreSignature;
792  return(image_view);
793 }
794 ␌
795 /*
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797 % %
798 % %
799 % %
800 % S e t I m a g e V i e w D e s c r i p t i o n %
801 % %
802 % %
803 % %
804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805 %
806 % SetImageViewDescription() associates a description with an image view.
807 %
808 % The format of the SetImageViewDescription method is:
809 %
810 % void SetImageViewDescription(ImageView *image_view,
811 % const char *description)
812 %
813 % A description of each parameter follows:
814 %
815 % o image_view: the image view.
816 %
817 % o description: the image view description.
818 %
819 */
820 MagickExport void SetImageViewDescription(ImageView *image_view,
821  const char *description)
822 {
823  assert(image_view != (ImageView *) NULL);
824  assert(image_view->signature == MagickCoreSignature);
825  image_view->description=ConstantString(description);
826 }
827 ␌
828 /*
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 % %
831 % %
832 % %
833 % S e t I m a g e V i e w I t e r a t o r %
834 % %
835 % %
836 % %
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838 %
839 % SetImageViewIterator() iterates over the image view in parallel and calls
840 % your set method for each scanline of the view. The pixel extent is
841 % confined to the image canvas-- that is no negative offsets or widths or
842 % heights that exceed the image dimension. The pixels are initiallly
843 % undefined and any settings you make in the callback method are automagically
844 % synced back to your image.
845 %
846 % The callback signature is:
847 %
848 % MagickBooleanType SetImageViewMethod(ImageView *destination,
849 % const ssize_t y,const int thread_id,void *context)
850 %
851 % Use this pragma if the view is not single threaded:
852 %
853 % #pragma omp critical
854 %
855 % to define a section of code in your callback set method that must be
856 % executed by a single thread at a time.
857 %
858 % The format of the SetImageViewIterator method is:
859 %
860 % MagickBooleanType SetImageViewIterator(ImageView *destination,
861 % SetImageViewMethod set,void *context)
862 %
863 % A description of each parameter follows:
864 %
865 % o destination: the image view.
866 %
867 % o set: the set callback method.
868 %
869 % o context: the user defined context.
870 %
871 */
872 MagickExport MagickBooleanType SetImageViewIterator(ImageView *destination,
873  SetImageViewMethod set,void *context)
874 {
875  Image
876  *destination_image;
877 
878  MagickBooleanType
879  status;
880 
881  MagickOffsetType
882  progress;
883 
884 #if defined(MAGICKCORE_OPENMP_SUPPORT)
885  size_t
886  height;
887 #endif
888 
889  ssize_t
890  y;
891 
892  assert(destination != (ImageView *) NULL);
893  assert(destination->signature == MagickCoreSignature);
894  if (set == (SetImageViewMethod) NULL)
895  return(MagickFalse);
896  destination_image=destination->image;
897  status=SetImageStorageClass(destination_image,DirectClass,
898  destination->exception);
899  if (status == MagickFalse)
900  return(MagickFalse);
901  status=MagickTrue;
902  progress=0;
903 #if defined(MAGICKCORE_OPENMP_SUPPORT)
904  height=destination->extent.height-destination->extent.y;
905  #pragma omp parallel for schedule(static) shared(progress,status) \
906  magick_number_threads(destination_image,destination_image,height,1)
907 #endif
908  for (y=destination->extent.y; y < (ssize_t) destination->extent.height; y++)
909  {
910  const int
911  id = GetOpenMPThreadId();
912 
913  MagickBooleanType
914  sync;
915 
916  Quantum
917  *magick_restrict pixels;
918 
919  if (status == MagickFalse)
920  continue;
921  pixels=GetCacheViewAuthenticPixels(destination->view,destination->extent.x,
922  y,destination->extent.width,1,destination->exception);
923  if (pixels == (Quantum *) NULL)
924  {
925  status=MagickFalse;
926  continue;
927  }
928  if (set(destination,y,id,context) == MagickFalse)
929  status=MagickFalse;
930  sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
931  if (sync == MagickFalse)
932  status=MagickFalse;
933  if (destination_image->progress_monitor != (MagickProgressMonitor) NULL)
934  {
935  MagickBooleanType
936  proceed;
937 
938 #if defined(MAGICKCORE_OPENMP_SUPPORT)
939  #pragma omp atomic
940 #endif
941  progress++;
942  proceed=SetImageProgress(destination_image,destination->description,
943  progress,destination->extent.height);
944  if (proceed == MagickFalse)
945  status=MagickFalse;
946  }
947  }
948  return(status);
949 }
950 ␌
951 /*
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 % %
954 % %
955 % %
956 % T r a n s f e r I m a g e V i e w I t e r a t o r %
957 % %
958 % %
959 % %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 %
962 % TransferImageViewIterator() iterates over two image views in parallel and
963 % calls your transfer method for each scanline of the view. The source pixel
964 % extent is not confined to the image canvas-- that is you can include
965 % negative offsets or widths or heights that exceed the image dimension.
966 % However, the destination image view is confined to the image canvas-- that
967 % is no negative offsets or widths or heights that exceed the image dimension
968 % are permitted.
969 %
970 % The callback signature is:
971 %
972 % MagickBooleanType TransferImageViewMethod(const ImageView *source,
973 % ImageView *destination,const ssize_t y,const int thread_id,
974 % void *context)
975 %
976 % Use this pragma if the view is not single threaded:
977 %
978 % #pragma omp critical
979 %
980 % to define a section of code in your callback transfer method that must be
981 % executed by a single thread at a time.
982 %
983 % The format of the TransferImageViewIterator method is:
984 %
985 % MagickBooleanType TransferImageViewIterator(ImageView *source,
986 % ImageView *destination,TransferImageViewMethod transfer,void *context)
987 %
988 % A description of each parameter follows:
989 %
990 % o source: the source image view.
991 %
992 % o destination: the destination image view.
993 %
994 % o transfer: the transfer callback method.
995 %
996 % o context: the user defined context.
997 %
998 */
999 MagickExport MagickBooleanType TransferImageViewIterator(ImageView *source,
1000  ImageView *destination,TransferImageViewMethod transfer,void *context)
1001 {
1002  Image
1003  *destination_image,
1004  *source_image;
1005 
1006  MagickBooleanType
1007  status;
1008 
1009  MagickOffsetType
1010  progress;
1011 
1012 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1013  size_t
1014  height;
1015 #endif
1016 
1017  ssize_t
1018  y;
1019 
1020  assert(source != (ImageView *) NULL);
1021  assert(source->signature == MagickCoreSignature);
1022  if (transfer == (TransferImageViewMethod) NULL)
1023  return(MagickFalse);
1024  source_image=source->image;
1025  destination_image=destination->image;
1026  status=SetImageStorageClass(destination_image,DirectClass,
1027  destination->exception);
1028  if (status == MagickFalse)
1029  return(MagickFalse);
1030  status=MagickTrue;
1031  progress=0;
1032 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1033  height=source->extent.height-source->extent.y;
1034  #pragma omp parallel for schedule(static) shared(progress,status) \
1035  magick_number_threads(source_image,destination_image,height,1)
1036 #endif
1037  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1038  {
1039  const int
1040  id = GetOpenMPThreadId();
1041 
1042  MagickBooleanType
1043  sync;
1044 
1045  const Quantum
1046  *magick_restrict pixels;
1047 
1048  Quantum
1049  *magick_restrict destination_pixels;
1050 
1051  if (status == MagickFalse)
1052  continue;
1053  pixels=GetCacheViewVirtualPixels(source->view,source->extent.x,y,
1054  source->extent.width,1,source->exception);
1055  if (pixels == (const Quantum *) NULL)
1056  {
1057  status=MagickFalse;
1058  continue;
1059  }
1060  destination_pixels=GetCacheViewAuthenticPixels(destination->view,
1061  destination->extent.x,y,destination->extent.width,1,
1062  destination->exception);
1063  if (destination_pixels == (Quantum *) NULL)
1064  {
1065  status=MagickFalse;
1066  continue;
1067  }
1068  if (transfer(source,destination,y,id,context) == MagickFalse)
1069  status=MagickFalse;
1070  sync=SyncCacheViewAuthenticPixels(destination->view,destination->exception);
1071  if (sync == MagickFalse)
1072  status=MagickFalse;
1073  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1074  {
1075  MagickBooleanType
1076  proceed;
1077 
1078 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1079  #pragma omp atomic
1080 #endif
1081  progress++;
1082  proceed=SetImageProgress(source_image,source->description,progress,
1083  source->extent.height);
1084  if (proceed == MagickFalse)
1085  status=MagickFalse;
1086  }
1087  }
1088  return(status);
1089 }
1090 ␌
1091 /*
1092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093 % %
1094 % %
1095 % %
1096 % U p d a t e I m a g e V i e w I t e r a t o r %
1097 % %
1098 % %
1099 % %
1100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101 %
1102 % UpdateImageViewIterator() iterates over the image view in parallel and calls
1103 % your update method for each scanline of the view. The pixel extent is
1104 % confined to the image canvas-- that is no negative offsets or widths or
1105 % heights that exceed the image dimension are permitted. Updates to pixels
1106 % in your callback are automagically synced back to the image.
1107 %
1108 % The callback signature is:
1109 %
1110 % MagickBooleanType UpdateImageViewMethod(ImageView *source,
1111 % const ssize_t y,const int thread_id,void *context)
1112 %
1113 % Use this pragma if the view is not single threaded:
1114 %
1115 % #pragma omp critical
1116 %
1117 % to define a section of code in your callback update method that must be
1118 % executed by a single thread at a time.
1119 %
1120 % The format of the UpdateImageViewIterator method is:
1121 %
1122 % MagickBooleanType UpdateImageViewIterator(ImageView *source,
1123 % UpdateImageViewMethod update,void *context)
1124 %
1125 % A description of each parameter follows:
1126 %
1127 % o source: the source image view.
1128 %
1129 % o update: the update callback method.
1130 %
1131 % o context: the user defined context.
1132 %
1133 */
1134 MagickExport MagickBooleanType UpdateImageViewIterator(ImageView *source,
1135  UpdateImageViewMethod update,void *context)
1136 {
1137  Image
1138  *source_image;
1139 
1140  MagickBooleanType
1141  status;
1142 
1143  MagickOffsetType
1144  progress;
1145 
1146 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1147  size_t
1148  height;
1149 #endif
1150 
1151  ssize_t
1152  y;
1153 
1154  assert(source != (ImageView *) NULL);
1155  assert(source->signature == MagickCoreSignature);
1156  if (update == (UpdateImageViewMethod) NULL)
1157  return(MagickFalse);
1158  source_image=source->image;
1159  status=SetImageStorageClass(source_image,DirectClass,source->exception);
1160  if (status == MagickFalse)
1161  return(MagickFalse);
1162  status=MagickTrue;
1163  progress=0;
1164 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1165  height=source->extent.height-source->extent.y;
1166  #pragma omp parallel for schedule(static) shared(progress,status) \
1167  magick_number_threads(source_image,source_image,height,1)
1168 #endif
1169  for (y=source->extent.y; y < (ssize_t) source->extent.height; y++)
1170  {
1171  const int
1172  id = GetOpenMPThreadId();
1173 
1174  Quantum
1175  *magick_restrict pixels;
1176 
1177  if (status == MagickFalse)
1178  continue;
1179  pixels=GetCacheViewAuthenticPixels(source->view,source->extent.x,y,
1180  source->extent.width,1,source->exception);
1181  if (pixels == (Quantum *) NULL)
1182  {
1183  status=MagickFalse;
1184  continue;
1185  }
1186  if (update(source,y,id,context) == MagickFalse)
1187  status=MagickFalse;
1188  status=SyncCacheViewAuthenticPixels(source->view,source->exception);
1189  if (source_image->progress_monitor != (MagickProgressMonitor) NULL)
1190  {
1191  MagickBooleanType
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 }
Definition: image.h:152