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