MagickCore 7.1.1
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
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*/
59{
60 char
61 *description;
62
64 extent;
65
66 Image
67 *image;
68
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*/
104MagickExport ImageView *CloneImageView(const ImageView *image_view)
105{
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*/
145MagickExport 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*/
209MagickExport 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-(size_t) 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*/
334MagickExport 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*/
364MagickExport 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*/
398MagickExport 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*/
450MagickExport 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*/
479MagickExport 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*/
529MagickExport 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-(size_t) 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*/
622MagickExport 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*/
652MagickExport 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*/
683MagickExport 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*/
717MagickExport ImageView *NewImageView(Image *image,ExceptionInfo *exception)
718{
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*/
770MagickExport 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{
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*/
820MagickExport 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 initially
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*/
872MagickExport 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-(size_t) 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*/
999MagickExport 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-(size_t) 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*/
1134MagickExport 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-(size_t) 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}